@yuneta/gobj-ui 7.23.9 → 7.23.10
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 +22 -6
- package/dist/gobj-ui.cjs.js +87 -5
- package/dist/gobj-ui.es.js +88 -6
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +81 -13
- package/src/g6_brush_select_owned.js +69 -0
package/README.md
CHANGED
|
@@ -964,12 +964,28 @@ gone wrong:
|
|
|
964
964
|
work — so a marquee shows up in the `machine` trace like every other action.
|
|
965
965
|
Shift+click is not G6's `click-select` at all: this gclass already owns
|
|
966
966
|
`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
|
-
|
|
967
|
+
the two end up disagreeing. The band comes from `g6_brush_select_owned.js`,
|
|
968
|
+
a `brush-select` under our own id with ONE half removed: the built-in also
|
|
969
|
+
rewrites the `selected` state of every node and every edge on each canvas
|
|
970
|
+
click, behind the gclass and outside the history pause with which it sets
|
|
971
|
+
and clears the selection — a recorded command whose before and after are
|
|
972
|
+
identical, which is a lit Save on a graph nobody has touched (`7.23.10`).
|
|
973
|
+
|
|
974
|
+
Panning gives way while **Shift** is held AND while the pointer is on a card
|
|
975
|
+
(`drag-canvas` takes an `enable` predicate) — the first because the canvas
|
|
976
|
+
would otherwise pan under the rubber band, the second because it would
|
|
977
|
+
otherwise pan under the node being dragged. That second half is G6's own
|
|
978
|
+
default, and an `enable` REPLACES the default rather than adding to it: while
|
|
979
|
+
it was missing, a drag moved the card at twice the pointer and slid the whole
|
|
980
|
+
graph underneath it (`7.23.10`).
|
|
981
|
+
|
|
982
|
+
**Undo, Redo and Save are the history plugin, and it follows the MODE.** It is
|
|
983
|
+
installed on entering edition and removed on leaving it — including when
|
|
984
|
+
edition is reached through the mode selector on a graph whose data is already
|
|
985
|
+
loaded, which is the ordinary way in. Before `7.23.10` it was installed at the
|
|
986
|
+
arrival of the last topic of the load and only if the graph was in edition
|
|
987
|
+
right then, so that ordinary way left the graph with dead Undo/Redo buttons
|
|
988
|
+
and a `history_pause()` nothing answered, while Save still lit on its own.
|
|
973
989
|
|
|
974
990
|
**A delete says what it takes, whether it is one or twenty.** The Delete key
|
|
975
991
|
asks the same question the per-node delete icon asks, built by the same
|
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -47507,6 +47507,58 @@ function inject_svg_icons() {
|
|
|
47507
47507
|
document.body.appendChild(div);
|
|
47508
47508
|
}
|
|
47509
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 _antv_g6.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
|
+
(0, _antv_g6.register)(_antv_g6.ExtensionCategory.BEHAVIOR, BRUSH_SELECT_OWNED, BrushSelectOwned);
|
|
47559
|
+
__brush_select_registered__ = true;
|
|
47560
|
+
}
|
|
47561
|
+
//#endregion
|
|
47510
47562
|
//#region src/c_g6_nodes_tree.js
|
|
47511
47563
|
/***********************************************************************
|
|
47512
47564
|
* c_g6_nodes_tree.js
|
|
@@ -47565,6 +47617,7 @@ var YuiToolbar = class extends _antv_g6.Toolbar {
|
|
|
47565
47617
|
};
|
|
47566
47618
|
(0, _antv_g6.register)(_antv_g6.ExtensionCategory.PLUGIN, "yui-toolbar", YuiToolbar);
|
|
47567
47619
|
ensure_drag_canvas_patch();
|
|
47620
|
+
ensure_brush_select_owned();
|
|
47568
47621
|
ensure_pinch_zoom_patch();
|
|
47569
47622
|
/***************************************************************
|
|
47570
47623
|
* Constants
|
|
@@ -48315,12 +48368,16 @@ function configure_behaviour(gobj) {
|
|
|
48315
48368
|
{
|
|
48316
48369
|
type: "drag-canvas",
|
|
48317
48370
|
key: "drag-canvas",
|
|
48318
|
-
enable: (event) =>
|
|
48371
|
+
enable: (event) => {
|
|
48372
|
+
if (event.shiftKey) return false;
|
|
48373
|
+
if ("targetType" in event) return event.targetType === "canvas";
|
|
48374
|
+
return true;
|
|
48375
|
+
}
|
|
48319
48376
|
},
|
|
48320
48377
|
"zoom-canvas",
|
|
48321
48378
|
"drag-element",
|
|
48322
48379
|
{
|
|
48323
|
-
type:
|
|
48380
|
+
type: BRUSH_SELECT_OWNED,
|
|
48324
48381
|
key: "brush-select",
|
|
48325
48382
|
trigger: ["shift"],
|
|
48326
48383
|
enableElements: ["node"],
|
|
@@ -48904,6 +48961,30 @@ function history_resume(gobj) {
|
|
|
48904
48961
|
gobj.priv._history_paused = false;
|
|
48905
48962
|
}
|
|
48906
48963
|
/************************************************************
|
|
48964
|
+
* The history plugin exists while the graph is in EDITION,
|
|
48965
|
+
* and only there.
|
|
48966
|
+
*
|
|
48967
|
+
* It used to be installed at one MOMENT -- the arrival of the
|
|
48968
|
+
* last topic of the load -- and only if the graph happened to
|
|
48969
|
+
* be in edition right then. Entering edition afterwards, which
|
|
48970
|
+
* is the ordinary way in (the graph opens in reading and the
|
|
48971
|
+
* mode selector is next to it), left no history at all: Undo
|
|
48972
|
+
* and Redo were dead buttons that never even lit, `history_
|
|
48973
|
+
* pause()` had no `beforeAddCommand` to answer, and the Save
|
|
48974
|
+
* button was told the graph was dirty by `mark_graph_dirty()`
|
|
48975
|
+
* alone -- which is why a move offered Save without Undo.
|
|
48976
|
+
*
|
|
48977
|
+
* So it follows the MODE, and every place that changes the
|
|
48978
|
+
* mode calls this.
|
|
48979
|
+
************************************************************/
|
|
48980
|
+
function sync_history_plugin(gobj) {
|
|
48981
|
+
let priv = gobj.priv;
|
|
48982
|
+
if (!priv.graph || !priv.graph_rendered) return;
|
|
48983
|
+
if (priv.edit_mode) graph_add_plugin(gobj, "history");
|
|
48984
|
+
else graph_remove_plugin(gobj, "history");
|
|
48985
|
+
update_history_buttons(gobj);
|
|
48986
|
+
}
|
|
48987
|
+
/************************************************************
|
|
48907
48988
|
*
|
|
48908
48989
|
************************************************************/
|
|
48909
48990
|
function update_history_buttons(gobj) {
|
|
@@ -49194,6 +49275,7 @@ function graph_add_plugin(gobj, plugin_key, options) {
|
|
|
49194
49275
|
let priv = gobj.priv;
|
|
49195
49276
|
let graph = priv.graph;
|
|
49196
49277
|
let plugin = graph_get_plugin(gobj, plugin_key);
|
|
49278
|
+
let existed = !!plugin;
|
|
49197
49279
|
if (!plugin) {
|
|
49198
49280
|
let plugin_def = {
|
|
49199
49281
|
key: plugin_key,
|
|
@@ -49204,7 +49286,7 @@ function graph_add_plugin(gobj, plugin_key, options) {
|
|
|
49204
49286
|
}
|
|
49205
49287
|
plugin = graph_get_plugin(gobj, plugin_key);
|
|
49206
49288
|
switch (plugin_key) {
|
|
49207
|
-
case "history": if (plugin) {
|
|
49289
|
+
case "history": if (plugin && !existed) {
|
|
49208
49290
|
plugin.on(_antv_g6.HistoryEvent.CHANGE, () => {
|
|
49209
49291
|
update_history_buttons(gobj);
|
|
49210
49292
|
});
|
|
@@ -51935,8 +52017,7 @@ function ac_load_data(gobj, event, kw, src) {
|
|
|
51935
52017
|
if (auto_laid) graph_fit_readable(gobj).catch((e) => {
|
|
51936
52018
|
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot fit the graph: ${e}`);
|
|
51937
52019
|
});
|
|
51938
|
-
|
|
51939
|
-
else graph_remove_plugin(gobj, "history");
|
|
52020
|
+
sync_history_plugin(gobj);
|
|
51940
52021
|
if (priv._pending_focus_topic !== null) {
|
|
51941
52022
|
let ft = priv._pending_focus_topic;
|
|
51942
52023
|
priv._pending_focus_topic = null;
|
|
@@ -52238,6 +52319,7 @@ function ac_set_operation_mode$1(gobj, event, kw, src) {
|
|
|
52238
52319
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "operation_mode", kw.operation_mode);
|
|
52239
52320
|
configure_behaviour(gobj);
|
|
52240
52321
|
update_toolbar(gobj);
|
|
52322
|
+
sync_history_plugin(gobj);
|
|
52241
52323
|
return 0;
|
|
52242
52324
|
}
|
|
52243
52325
|
/************************************************************
|
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;
|
|
@@ -47494,6 +47494,58 @@ function inject_svg_icons() {
|
|
|
47494
47494
|
document.body.appendChild(div);
|
|
47495
47495
|
}
|
|
47496
47496
|
//#endregion
|
|
47497
|
+
//#region src/g6_brush_select_owned.js
|
|
47498
|
+
/***********************************************************************
|
|
47499
|
+
* g6_brush_select_owned.js
|
|
47500
|
+
*
|
|
47501
|
+
* The rubber band, for a graph whose FSM owns the selection.
|
|
47502
|
+
*
|
|
47503
|
+
* Why this exists
|
|
47504
|
+
* ----------------
|
|
47505
|
+
* G6 v5 `brush-select` does two things: it draws the band and
|
|
47506
|
+
* it keeps the `selected` element state. The second one is
|
|
47507
|
+
* not ours to give away -- `C_G6_NODES_TREE` owns the
|
|
47508
|
+
* selection, sets it in `set_selection()` and clears it in
|
|
47509
|
+
* `deselect_node()`, both with the history recorder paused,
|
|
47510
|
+
* because a selection is not an edit.
|
|
47511
|
+
*
|
|
47512
|
+
* The built-in disagrees on one path: on EVERY canvas click
|
|
47513
|
+
* it calls `clearElementsStates()`, which writes the state of
|
|
47514
|
+
* every node and every edge of the graph -- whether or not
|
|
47515
|
+
* any of them carried it -- outside our pause. G6's history
|
|
47516
|
+
* then records the redraw as a command whose `original` and
|
|
47517
|
+
* `current` are identical: an undo entry that undoes nothing,
|
|
47518
|
+
* and a Save button lit on a graph nobody has touched. One
|
|
47519
|
+
* click on the background was enough.
|
|
47520
|
+
*
|
|
47521
|
+
* So this subclass drops that half and keeps the band. The
|
|
47522
|
+
* selection still clears on a canvas click -- through
|
|
47523
|
+
* `EV_CANVAS_CLICK`, where the gclass has always cleared it.
|
|
47524
|
+
*
|
|
47525
|
+
* Registered under its OWN id: the built-in `brush-select` is
|
|
47526
|
+
* right for a graph that does not own its selection, and no
|
|
47527
|
+
* other consumer of this library asked for this.
|
|
47528
|
+
*
|
|
47529
|
+
* Copyright (c) 2026, ArtGins.
|
|
47530
|
+
* All Rights Reserved.
|
|
47531
|
+
***********************************************************************/
|
|
47532
|
+
/************************************************************
|
|
47533
|
+
* Same band, no state bookkeeping behind the gclass's back
|
|
47534
|
+
************************************************************/
|
|
47535
|
+
var BrushSelectOwned = class extends BrushSelect {
|
|
47536
|
+
clearElementsStates() {}
|
|
47537
|
+
};
|
|
47538
|
+
/************************************************************
|
|
47539
|
+
* Register once, under our own id
|
|
47540
|
+
************************************************************/
|
|
47541
|
+
var BRUSH_SELECT_OWNED = "yui-brush-select";
|
|
47542
|
+
var __brush_select_registered__ = false;
|
|
47543
|
+
function ensure_brush_select_owned() {
|
|
47544
|
+
if (__brush_select_registered__) return;
|
|
47545
|
+
register(ExtensionCategory.BEHAVIOR, BRUSH_SELECT_OWNED, BrushSelectOwned);
|
|
47546
|
+
__brush_select_registered__ = true;
|
|
47547
|
+
}
|
|
47548
|
+
//#endregion
|
|
47497
47549
|
//#region src/c_g6_nodes_tree.js
|
|
47498
47550
|
/***********************************************************************
|
|
47499
47551
|
* c_g6_nodes_tree.js
|
|
@@ -47552,6 +47604,7 @@ var YuiToolbar = class extends Toolbar {
|
|
|
47552
47604
|
};
|
|
47553
47605
|
register(ExtensionCategory.PLUGIN, "yui-toolbar", YuiToolbar);
|
|
47554
47606
|
ensure_drag_canvas_patch();
|
|
47607
|
+
ensure_brush_select_owned();
|
|
47555
47608
|
ensure_pinch_zoom_patch();
|
|
47556
47609
|
/***************************************************************
|
|
47557
47610
|
* Constants
|
|
@@ -48302,12 +48355,16 @@ function configure_behaviour(gobj) {
|
|
|
48302
48355
|
{
|
|
48303
48356
|
type: "drag-canvas",
|
|
48304
48357
|
key: "drag-canvas",
|
|
48305
|
-
enable: (event) =>
|
|
48358
|
+
enable: (event) => {
|
|
48359
|
+
if (event.shiftKey) return false;
|
|
48360
|
+
if ("targetType" in event) return event.targetType === "canvas";
|
|
48361
|
+
return true;
|
|
48362
|
+
}
|
|
48306
48363
|
},
|
|
48307
48364
|
"zoom-canvas",
|
|
48308
48365
|
"drag-element",
|
|
48309
48366
|
{
|
|
48310
|
-
type:
|
|
48367
|
+
type: BRUSH_SELECT_OWNED,
|
|
48311
48368
|
key: "brush-select",
|
|
48312
48369
|
trigger: ["shift"],
|
|
48313
48370
|
enableElements: ["node"],
|
|
@@ -48891,6 +48948,30 @@ function history_resume(gobj) {
|
|
|
48891
48948
|
gobj.priv._history_paused = false;
|
|
48892
48949
|
}
|
|
48893
48950
|
/************************************************************
|
|
48951
|
+
* The history plugin exists while the graph is in EDITION,
|
|
48952
|
+
* and only there.
|
|
48953
|
+
*
|
|
48954
|
+
* It used to be installed at one MOMENT -- the arrival of the
|
|
48955
|
+
* last topic of the load -- and only if the graph happened to
|
|
48956
|
+
* be in edition right then. Entering edition afterwards, which
|
|
48957
|
+
* is the ordinary way in (the graph opens in reading and the
|
|
48958
|
+
* mode selector is next to it), left no history at all: Undo
|
|
48959
|
+
* and Redo were dead buttons that never even lit, `history_
|
|
48960
|
+
* pause()` had no `beforeAddCommand` to answer, and the Save
|
|
48961
|
+
* button was told the graph was dirty by `mark_graph_dirty()`
|
|
48962
|
+
* alone -- which is why a move offered Save without Undo.
|
|
48963
|
+
*
|
|
48964
|
+
* So it follows the MODE, and every place that changes the
|
|
48965
|
+
* mode calls this.
|
|
48966
|
+
************************************************************/
|
|
48967
|
+
function sync_history_plugin(gobj) {
|
|
48968
|
+
let priv = gobj.priv;
|
|
48969
|
+
if (!priv.graph || !priv.graph_rendered) return;
|
|
48970
|
+
if (priv.edit_mode) graph_add_plugin(gobj, "history");
|
|
48971
|
+
else graph_remove_plugin(gobj, "history");
|
|
48972
|
+
update_history_buttons(gobj);
|
|
48973
|
+
}
|
|
48974
|
+
/************************************************************
|
|
48894
48975
|
*
|
|
48895
48976
|
************************************************************/
|
|
48896
48977
|
function update_history_buttons(gobj) {
|
|
@@ -49181,6 +49262,7 @@ function graph_add_plugin(gobj, plugin_key, options) {
|
|
|
49181
49262
|
let priv = gobj.priv;
|
|
49182
49263
|
let graph = priv.graph;
|
|
49183
49264
|
let plugin = graph_get_plugin(gobj, plugin_key);
|
|
49265
|
+
let existed = !!plugin;
|
|
49184
49266
|
if (!plugin) {
|
|
49185
49267
|
let plugin_def = {
|
|
49186
49268
|
key: plugin_key,
|
|
@@ -49191,7 +49273,7 @@ function graph_add_plugin(gobj, plugin_key, options) {
|
|
|
49191
49273
|
}
|
|
49192
49274
|
plugin = graph_get_plugin(gobj, plugin_key);
|
|
49193
49275
|
switch (plugin_key) {
|
|
49194
|
-
case "history": if (plugin) {
|
|
49276
|
+
case "history": if (plugin && !existed) {
|
|
49195
49277
|
plugin.on(HistoryEvent.CHANGE, () => {
|
|
49196
49278
|
update_history_buttons(gobj);
|
|
49197
49279
|
});
|
|
@@ -51922,8 +52004,7 @@ function ac_load_data(gobj, event, kw, src) {
|
|
|
51922
52004
|
if (auto_laid) graph_fit_readable(gobj).catch((e) => {
|
|
51923
52005
|
log_error(`${gobj_short_name(gobj)}: cannot fit the graph: ${e}`);
|
|
51924
52006
|
});
|
|
51925
|
-
|
|
51926
|
-
else graph_remove_plugin(gobj, "history");
|
|
52007
|
+
sync_history_plugin(gobj);
|
|
51927
52008
|
if (priv._pending_focus_topic !== null) {
|
|
51928
52009
|
let ft = priv._pending_focus_topic;
|
|
51929
52010
|
priv._pending_focus_topic = null;
|
|
@@ -52225,6 +52306,7 @@ function ac_set_operation_mode$1(gobj, event, kw, src) {
|
|
|
52225
52306
|
gobj_write_attr(gobj, "operation_mode", kw.operation_mode);
|
|
52226
52307
|
configure_behaviour(gobj);
|
|
52227
52308
|
update_toolbar(gobj);
|
|
52309
|
+
sync_history_plugin(gobj);
|
|
52228
52310
|
return 0;
|
|
52229
52311
|
}
|
|
52230
52312
|
/************************************************************
|
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
|
/***************************************************************
|
|
@@ -1410,11 +1415,28 @@ function configure_behaviour(gobj)
|
|
|
1410
1415
|
/* Panning gives way while Shift is held: that is the
|
|
1411
1416
|
* marquee's gesture, and G6 binds drag-canvas straight
|
|
1412
1417
|
* to the drag events, so without this the canvas pans
|
|
1413
|
-
* under the rubber band.
|
|
1418
|
+
* under the rubber band.
|
|
1419
|
+
*
|
|
1420
|
+
* And it gives way to a NODE drag, which is what G6's
|
|
1421
|
+
* own default `enable` says and what this one has to
|
|
1422
|
+
* repeat: `enable` REPLACES it, it does not add to it.
|
|
1423
|
+
* Dropping the `targetType` half made every drag of a
|
|
1424
|
+
* card pan the canvas as well as move the card -- the
|
|
1425
|
+
* card ran at twice the pointer and the whole graph
|
|
1426
|
+
* slid underneath it, on a move whose RESULT was
|
|
1427
|
+
* right, because a pan writes nothing. */
|
|
1414
1428
|
{
|
|
1415
1429
|
type: "drag-canvas",
|
|
1416
1430
|
key: "drag-canvas",
|
|
1417
|
-
enable: (event) =>
|
|
1431
|
+
enable: (event) => {
|
|
1432
|
+
if(event.shiftKey) {
|
|
1433
|
+
return false;
|
|
1434
|
+
}
|
|
1435
|
+
if('targetType' in event) {
|
|
1436
|
+
return event.targetType === 'canvas';
|
|
1437
|
+
}
|
|
1438
|
+
return true; /* a key, not a pointer */
|
|
1439
|
+
},
|
|
1418
1440
|
},
|
|
1419
1441
|
"zoom-canvas",
|
|
1420
1442
|
/* Moves EVERY node in the `selected` state, not just
|
|
@@ -1429,7 +1451,12 @@ function configure_behaviour(gobj)
|
|
|
1429
1451
|
* ids travel with the event and the action does not
|
|
1430
1452
|
* have to race it. */
|
|
1431
1453
|
{
|
|
1432
|
-
|
|
1454
|
+
/* Ours: the built-in also rewrites the state of
|
|
1455
|
+
* EVERY element on a canvas click, behind the
|
|
1456
|
+
* gclass's back and outside its history pause --
|
|
1457
|
+
* a command that changed nothing, and a Save
|
|
1458
|
+
* button lit on a graph nobody had touched. */
|
|
1459
|
+
type: BRUSH_SELECT_OWNED,
|
|
1433
1460
|
key: "brush-select",
|
|
1434
1461
|
trigger: ["shift"],
|
|
1435
1462
|
enableElements: ["node"],
|
|
@@ -2370,6 +2397,42 @@ function history_resume(gobj)
|
|
|
2370
2397
|
gobj.priv._history_paused = false;
|
|
2371
2398
|
}
|
|
2372
2399
|
|
|
2400
|
+
/************************************************************
|
|
2401
|
+
* The history plugin exists while the graph is in EDITION,
|
|
2402
|
+
* and only there.
|
|
2403
|
+
*
|
|
2404
|
+
* It used to be installed at one MOMENT -- the arrival of the
|
|
2405
|
+
* last topic of the load -- and only if the graph happened to
|
|
2406
|
+
* be in edition right then. Entering edition afterwards, which
|
|
2407
|
+
* is the ordinary way in (the graph opens in reading and the
|
|
2408
|
+
* mode selector is next to it), left no history at all: Undo
|
|
2409
|
+
* and Redo were dead buttons that never even lit, `history_
|
|
2410
|
+
* pause()` had no `beforeAddCommand` to answer, and the Save
|
|
2411
|
+
* button was told the graph was dirty by `mark_graph_dirty()`
|
|
2412
|
+
* alone -- which is why a move offered Save without Undo.
|
|
2413
|
+
*
|
|
2414
|
+
* So it follows the MODE, and every place that changes the
|
|
2415
|
+
* mode calls this.
|
|
2416
|
+
************************************************************/
|
|
2417
|
+
function sync_history_plugin(gobj)
|
|
2418
|
+
{
|
|
2419
|
+
let priv = gobj.priv;
|
|
2420
|
+
|
|
2421
|
+
if(!priv.graph || !priv.graph_rendered) {
|
|
2422
|
+
/* Nothing to hang a plugin on yet: the load path calls
|
|
2423
|
+
* this again once the graph is drawn. */
|
|
2424
|
+
return;
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2427
|
+
if(priv.edit_mode) {
|
|
2428
|
+
graph_add_plugin(gobj, "history");
|
|
2429
|
+
} else {
|
|
2430
|
+
graph_remove_plugin(gobj, "history");
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
update_history_buttons(gobj);
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2373
2436
|
/************************************************************
|
|
2374
2437
|
*
|
|
2375
2438
|
************************************************************/
|
|
@@ -2775,6 +2838,7 @@ function graph_add_plugin(gobj, plugin_key, options)
|
|
|
2775
2838
|
let graph = priv.graph;
|
|
2776
2839
|
|
|
2777
2840
|
let plugin = graph_get_plugin(gobj, plugin_key);
|
|
2841
|
+
let existed = !!plugin;
|
|
2778
2842
|
if(!plugin) {
|
|
2779
2843
|
let plugin_def = {
|
|
2780
2844
|
key: plugin_key,
|
|
@@ -2790,7 +2854,11 @@ function graph_add_plugin(gobj, plugin_key, options)
|
|
|
2790
2854
|
|
|
2791
2855
|
switch(plugin_key) {
|
|
2792
2856
|
case "history":
|
|
2793
|
-
|
|
2857
|
+
/* Wired once per INSTANCE: this is called again on every
|
|
2858
|
+
* load and on every entry into edition, and a second
|
|
2859
|
+
* listener on the same emitter is a second repaint of the
|
|
2860
|
+
* same two buttons. */
|
|
2861
|
+
if(plugin && !existed) {
|
|
2794
2862
|
plugin.on(HistoryEvent.CHANGE, () => {
|
|
2795
2863
|
update_history_buttons(gobj);
|
|
2796
2864
|
});
|
|
@@ -3563,10 +3631,10 @@ function toggle_in_selection(gobj, node_id)
|
|
|
3563
3631
|
{
|
|
3564
3632
|
let priv = gobj.priv;
|
|
3565
3633
|
|
|
3566
|
-
/* The union of the two views of the same thing
|
|
3567
|
-
* G6's state
|
|
3568
|
-
*
|
|
3569
|
-
* ring. */
|
|
3634
|
+
/* The union of the two views of the same thing: either can hold
|
|
3635
|
+
* an id the other lost -- G6's state is what a drag moves, the
|
|
3636
|
+
* painted set is what the reader can see -- and a card on screen
|
|
3637
|
+
* wearing a ring belongs to the selection whichever view has it. */
|
|
3570
3638
|
let current = new Set(selected_node_ids(gobj));
|
|
3571
3639
|
for(let id of (priv._selected_paint_ids || [])) {
|
|
3572
3640
|
current.add(id);
|
|
@@ -7000,11 +7068,7 @@ function ac_load_data(gobj, event, kw, src)
|
|
|
7000
7068
|
log_error(`${gobj_short_name(gobj)}: cannot fit the graph: ${e}`);
|
|
7001
7069
|
});
|
|
7002
7070
|
}
|
|
7003
|
-
|
|
7004
|
-
graph_add_plugin(gobj, "history");
|
|
7005
|
-
} else {
|
|
7006
|
-
graph_remove_plugin(gobj, "history");
|
|
7007
|
-
}
|
|
7071
|
+
sync_history_plugin(gobj);
|
|
7008
7072
|
/* Nodes exist and are positioned now: apply a focus
|
|
7009
7073
|
* requested before the data was ready (deep link). */
|
|
7010
7074
|
if(priv._pending_focus_topic !== null) {
|
|
@@ -7462,6 +7526,10 @@ function ac_set_operation_mode(gobj, event, kw, src)
|
|
|
7462
7526
|
gobj_write_attr(gobj, "operation_mode", kw.operation_mode);
|
|
7463
7527
|
configure_behaviour(gobj);
|
|
7464
7528
|
update_toolbar(gobj);
|
|
7529
|
+
|
|
7530
|
+
/* `configure_behaviour` is what decides `edit_mode`, and the
|
|
7531
|
+
* history plugin belongs to that decision. */
|
|
7532
|
+
sync_history_plugin(gobj);
|
|
7465
7533
|
return 0;
|
|
7466
7534
|
}
|
|
7467
7535
|
|
|
@@ -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 };
|