@yuneta/gobj-ui 7.23.8 → 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 +75 -6
- package/dist/gobj-ui.cjs.js +625 -76
- package/dist/gobj-ui.es.js +626 -77
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +496 -68
- package/src/c_yui_gobj_tree_js.js +2 -0
- package/src/c_yui_json_graph.js +2 -0
- package/src/g6_brush_select_owned.js +69 -0
- package/src/g6_drag_canvas_touch.js +21 -0
- package/src/g6_touch_gestures.js +413 -0
- package/src/lib_graph.css +19 -0
- package/src/lib_icons.js +14 -0
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -9504,6 +9504,275 @@ function yui_graph_refresh_item(gobj, wide) {
|
|
|
9504
9504
|
return camera_button(gobj, "yi-arrows-rotate", "EV_REFRESH", "refresh", wide);
|
|
9505
9505
|
}
|
|
9506
9506
|
//#endregion
|
|
9507
|
+
//#region src/g6_touch_gestures.js
|
|
9508
|
+
/***********************************************************************
|
|
9509
|
+
* g6_touch_gestures.js
|
|
9510
|
+
*
|
|
9511
|
+
* The two gestures a G6 graph needs on a touch screen and
|
|
9512
|
+
* does not have: PINCH to zoom, and LONG PRESS to open the
|
|
9513
|
+
* context menu.
|
|
9514
|
+
*
|
|
9515
|
+
* Why this exists
|
|
9516
|
+
* ----------------
|
|
9517
|
+
* G6 v5 draws a graph that reads fine on a phone and cannot
|
|
9518
|
+
* be OPERATED on one. Two gaps, both structural:
|
|
9519
|
+
*
|
|
9520
|
+
* 1. `zoom-canvas` binds the WHEEL and nothing else
|
|
9521
|
+
* (`trigger: []`). There is no wheel on a phone, so the
|
|
9522
|
+
* only zoom is the toolbar's +/- buttons. G6 does ship a
|
|
9523
|
+
* pinch recogniser, and `zoom-canvas` will use it -- with
|
|
9524
|
+
* `trigger: ['pinch']`, which its `bindEvents` treats as
|
|
9525
|
+
* an ALTERNATIVE to the wheel (`if pinch ... else wheel`),
|
|
9526
|
+
* so opting in costs the mouse. Worse, its `PinchHandler`
|
|
9527
|
+
* keeps its instance and its callback list in STATICS: on
|
|
9528
|
+
* a page with two graphs the second one registers its
|
|
9529
|
+
* callback against the FIRST one's emitter, so pinching
|
|
9530
|
+
* graph A zooms both and pinching graph B does nothing.
|
|
9531
|
+
* We recognise the gesture ourselves, per graph.
|
|
9532
|
+
*
|
|
9533
|
+
* 2. The context menu is bound to `contextmenu`, and G6 does
|
|
9534
|
+
* not take that from the DOM: its `BehaviorController`
|
|
9535
|
+
* SYNTHESISES it from `pointerdown` with `button === 2`.
|
|
9536
|
+
* A long press therefore never reaches the plugin on ANY
|
|
9537
|
+
* platform, whatever the browser does with the gesture.
|
|
9538
|
+
* So we synthesise it the same way G6 does, from the same
|
|
9539
|
+
* forwarded event object -- which is why the plugin's
|
|
9540
|
+
* `getItems(e)` receives exactly the shape it expects.
|
|
9541
|
+
*
|
|
9542
|
+
* Both are built on ONE per-graph record of the fingers
|
|
9543
|
+
* on the glass, read from the NATIVE touch events -- see
|
|
9544
|
+
* `touch_state_of` for why the pointer stream, which looks
|
|
9545
|
+
* like the right source, is not. That record is also what
|
|
9546
|
+
* tells `drag-canvas` to stop panning while two fingers are
|
|
9547
|
+
* down (`is_pinching`), the guard G6's own drag-canvas has
|
|
9548
|
+
* and our replacement dropped.
|
|
9549
|
+
*
|
|
9550
|
+
* Copyright (c) 2026, ArtGins.
|
|
9551
|
+
* All Rights Reserved.
|
|
9552
|
+
***********************************************************************/
|
|
9553
|
+
/***************************************************************
|
|
9554
|
+
* Constants
|
|
9555
|
+
***************************************************************/
|
|
9556
|
+
var LONG_PRESS_MS = 500;
|
|
9557
|
+
var LONG_PRESS_SLOP = 10;
|
|
9558
|
+
/***************************************************************
|
|
9559
|
+
* Per-graph record of the fingers on the glass
|
|
9560
|
+
***************************************************************/
|
|
9561
|
+
var __touch_state__ = /* @__PURE__ */ new WeakMap();
|
|
9562
|
+
/************************************************************
|
|
9563
|
+
* The touch record of one graph, installing its listeners
|
|
9564
|
+
* the first time it is asked for.
|
|
9565
|
+
*
|
|
9566
|
+
* Read from the NATIVE touch events, not from G6's
|
|
9567
|
+
* forwarded pointer stream.
|
|
9568
|
+
*
|
|
9569
|
+
* The pointer stream looks like the right source and is
|
|
9570
|
+
* not: @antv/g re-issues pointer ids in the middle of a
|
|
9571
|
+
* two-finger gesture (measured: a pinch that started on
|
|
9572
|
+
* ids 2 and 3 finished on id 1), so anything that keys a
|
|
9573
|
+
* Map on `pointerId` loses one of the two fingers halfway
|
|
9574
|
+
* and reads the gesture as a fraction of what it was.
|
|
9575
|
+
* G6's own `PinchHandler` is built exactly that way.
|
|
9576
|
+
*
|
|
9577
|
+
* `event.touches` needs no bookkeeping at all: it IS the
|
|
9578
|
+
* list of fingers currently down, re-stated on every event.
|
|
9579
|
+
************************************************************/
|
|
9580
|
+
function touch_state_of(graph) {
|
|
9581
|
+
let state = __touch_state__.get(graph);
|
|
9582
|
+
if (state) return state;
|
|
9583
|
+
state = {
|
|
9584
|
+
count: 0,
|
|
9585
|
+
container: null
|
|
9586
|
+
};
|
|
9587
|
+
__touch_state__.set(graph, state);
|
|
9588
|
+
let container = graph.getCanvas?.()?.getContainer?.();
|
|
9589
|
+
if (!container) return state;
|
|
9590
|
+
state.container = container;
|
|
9591
|
+
let read = (event) => {
|
|
9592
|
+
state.count = event.touches ? event.touches.length : 0;
|
|
9593
|
+
};
|
|
9594
|
+
container.addEventListener("touchstart", read, { passive: true });
|
|
9595
|
+
container.addEventListener("touchmove", read, { passive: true });
|
|
9596
|
+
container.addEventListener("touchend", read, { passive: true });
|
|
9597
|
+
container.addEventListener("touchcancel", read, { passive: true });
|
|
9598
|
+
return state;
|
|
9599
|
+
}
|
|
9600
|
+
/************************************************************
|
|
9601
|
+
* Is a two-finger gesture in progress on this graph?
|
|
9602
|
+
*
|
|
9603
|
+
* Read by our `drag-canvas` replacement: panning and zooming
|
|
9604
|
+
* the same drag at the same time fights the user for the
|
|
9605
|
+
* camera.
|
|
9606
|
+
************************************************************/
|
|
9607
|
+
function is_pinching(graph) {
|
|
9608
|
+
if (!graph) return false;
|
|
9609
|
+
let state = __touch_state__.get(graph);
|
|
9610
|
+
if (!state) return false;
|
|
9611
|
+
return state.count >= 2;
|
|
9612
|
+
}
|
|
9613
|
+
/***************************
|
|
9614
|
+
* Pinch to zoom
|
|
9615
|
+
***************************/
|
|
9616
|
+
/************************************************************
|
|
9617
|
+
* `zoom-canvas` that also answers the pinch.
|
|
9618
|
+
*
|
|
9619
|
+
* The base class keeps the wheel; the pinch is added on top
|
|
9620
|
+
* instead of replacing it, so one build serves the mouse and
|
|
9621
|
+
* the finger. The scale is ABSOLUTE against the zoom the
|
|
9622
|
+
* gesture started at -- G6's own pinch feeds `zoom()` an
|
|
9623
|
+
* increment per frame, which drifts away from the fingers
|
|
9624
|
+
* over a long gesture.
|
|
9625
|
+
************************************************************/
|
|
9626
|
+
var ZoomCanvasPinch = class extends _antv_g6.ZoomCanvas {
|
|
9627
|
+
constructor(context, options) {
|
|
9628
|
+
super(context, options);
|
|
9629
|
+
this._pinch_dist0 = 0;
|
|
9630
|
+
this._pinch_zoom0 = 1;
|
|
9631
|
+
this._on_touch_move = null;
|
|
9632
|
+
let { trigger } = this.options;
|
|
9633
|
+
if (Array.isArray(trigger) && trigger.includes(_antv_g6.CommonEvent.PINCH)) return;
|
|
9634
|
+
let graph = this.context.graph;
|
|
9635
|
+
let state = touch_state_of(graph);
|
|
9636
|
+
if (!state.container) return;
|
|
9637
|
+
this._on_touch_move = (event) => {
|
|
9638
|
+
let touches = event.touches;
|
|
9639
|
+
if (!touches || touches.length !== 2) {
|
|
9640
|
+
this._pinch_dist0 = 0;
|
|
9641
|
+
return;
|
|
9642
|
+
}
|
|
9643
|
+
let dx = touches[0].clientX - touches[1].clientX;
|
|
9644
|
+
let dy = touches[0].clientY - touches[1].clientY;
|
|
9645
|
+
let dist = Math.sqrt(dx * dx + dy * dy);
|
|
9646
|
+
if (dist <= 0) return;
|
|
9647
|
+
if (this._pinch_dist0 === 0) {
|
|
9648
|
+
this._pinch_dist0 = dist;
|
|
9649
|
+
this._pinch_zoom0 = graph.getZoom();
|
|
9650
|
+
return;
|
|
9651
|
+
}
|
|
9652
|
+
this._pinch_to(dist / this._pinch_dist0, touches, event);
|
|
9653
|
+
};
|
|
9654
|
+
state.container.addEventListener("touchmove", this._on_touch_move, { passive: true });
|
|
9655
|
+
}
|
|
9656
|
+
/************************************************************
|
|
9657
|
+
* Zoom to `scale` times the zoom the pinch started at,
|
|
9658
|
+
* about the midpoint between the two fingers.
|
|
9659
|
+
*
|
|
9660
|
+
* ABSOLUTE against the start of the gesture, where G6's
|
|
9661
|
+
* own pinch feeds `zoom()` an increment per frame: an
|
|
9662
|
+
* increment drifts away from the fingers over a long
|
|
9663
|
+
* gesture, and cannot come back when they close again.
|
|
9664
|
+
************************************************************/
|
|
9665
|
+
_pinch_to(scale, touches, event) {
|
|
9666
|
+
if (!this.validate(event)) return;
|
|
9667
|
+
let graph = this.context.graph;
|
|
9668
|
+
let state = touch_state_of(graph);
|
|
9669
|
+
let origin = null;
|
|
9670
|
+
let rect = state.container?.getBoundingClientRect();
|
|
9671
|
+
if (rect) origin = [(touches[0].clientX + touches[1].clientX) / 2 - rect.left, (touches[0].clientY + touches[1].clientY) / 2 - rect.top];
|
|
9672
|
+
graph.zoomTo(this._pinch_zoom0 * scale, false, origin);
|
|
9673
|
+
this.options.onFinish?.();
|
|
9674
|
+
}
|
|
9675
|
+
destroy() {
|
|
9676
|
+
if (this._on_touch_move) {
|
|
9677
|
+
__touch_state__.get(this.context.graph)?.container?.removeEventListener("touchmove", this._on_touch_move);
|
|
9678
|
+
this._on_touch_move = null;
|
|
9679
|
+
}
|
|
9680
|
+
super.destroy();
|
|
9681
|
+
}
|
|
9682
|
+
};
|
|
9683
|
+
/************************************************************
|
|
9684
|
+
* Register once, over the built-in `zoom-canvas`, so every
|
|
9685
|
+
* graph (tree, json, treedb, editor) pinches without
|
|
9686
|
+
* touching its behaviors list.
|
|
9687
|
+
************************************************************/
|
|
9688
|
+
var __zoom_canvas_patched__ = false;
|
|
9689
|
+
function ensure_pinch_zoom_patch() {
|
|
9690
|
+
if (__zoom_canvas_patched__) return;
|
|
9691
|
+
(0, _antv_g6.register)(_antv_g6.ExtensionCategory.BEHAVIOR, "zoom-canvas", ZoomCanvasPinch);
|
|
9692
|
+
__zoom_canvas_patched__ = true;
|
|
9693
|
+
}
|
|
9694
|
+
/***************************
|
|
9695
|
+
* Long press
|
|
9696
|
+
***************************/
|
|
9697
|
+
/************************************************************
|
|
9698
|
+
* Make a long press open the context menu.
|
|
9699
|
+
*
|
|
9700
|
+
* Returns the function that uninstalls it.
|
|
9701
|
+
*
|
|
9702
|
+
* The menu the press opens is whatever the `contextmenu`
|
|
9703
|
+
* plugin builds: we re-emit G6's own forwarded event under
|
|
9704
|
+
* the name the plugin listens for, so `getItems(e)` and
|
|
9705
|
+
* `enable(e)` see the same object a right-click would give
|
|
9706
|
+
* them -- same `target`, same `targetType`, same `client`.
|
|
9707
|
+
************************************************************/
|
|
9708
|
+
function install_long_press_contextmenu(graph) {
|
|
9709
|
+
if (!graph) return () => {};
|
|
9710
|
+
let state = touch_state_of(graph);
|
|
9711
|
+
let pending = null;
|
|
9712
|
+
let cancel = () => {
|
|
9713
|
+
if (pending) {
|
|
9714
|
+
clearTimeout(pending.timer);
|
|
9715
|
+
pending = null;
|
|
9716
|
+
}
|
|
9717
|
+
};
|
|
9718
|
+
let fire = (event) => {
|
|
9719
|
+
pending = null;
|
|
9720
|
+
let swallow = (evt) => {
|
|
9721
|
+
evt.stopPropagation();
|
|
9722
|
+
document.removeEventListener("click", swallow, true);
|
|
9723
|
+
};
|
|
9724
|
+
document.addEventListener("click", swallow, true);
|
|
9725
|
+
setTimeout(() => {
|
|
9726
|
+
document.removeEventListener("click", swallow, true);
|
|
9727
|
+
}, 1e3);
|
|
9728
|
+
let container = graph.getCanvas?.()?.getContainer?.();
|
|
9729
|
+
if (container) container.addEventListener("contextmenu", (evt) => {
|
|
9730
|
+
evt.preventDefault();
|
|
9731
|
+
}, {
|
|
9732
|
+
once: true,
|
|
9733
|
+
capture: true
|
|
9734
|
+
});
|
|
9735
|
+
graph.emit(`${event.targetType}:${_antv_g6.CommonEvent.CONTEXT_MENU}`, event);
|
|
9736
|
+
graph.emit(_antv_g6.CommonEvent.CONTEXT_MENU, event);
|
|
9737
|
+
};
|
|
9738
|
+
let on_down = (event) => {
|
|
9739
|
+
cancel();
|
|
9740
|
+
if (event.pointerType !== "touch") return;
|
|
9741
|
+
if (state.count > 1) return;
|
|
9742
|
+
let x = event.client?.x;
|
|
9743
|
+
let y = event.client?.y;
|
|
9744
|
+
if (x === void 0 || y === void 0) return;
|
|
9745
|
+
let frozen = Object.assign({}, event);
|
|
9746
|
+
pending = {
|
|
9747
|
+
x,
|
|
9748
|
+
y,
|
|
9749
|
+
timer: setTimeout(() => {
|
|
9750
|
+
fire(frozen);
|
|
9751
|
+
}, LONG_PRESS_MS)
|
|
9752
|
+
};
|
|
9753
|
+
};
|
|
9754
|
+
let on_move = (event) => {
|
|
9755
|
+
if (!pending) return;
|
|
9756
|
+
if (state.count > 1) {
|
|
9757
|
+
cancel();
|
|
9758
|
+
return;
|
|
9759
|
+
}
|
|
9760
|
+
let x = event.client?.x;
|
|
9761
|
+
let y = event.client?.y;
|
|
9762
|
+
if (x === void 0 || y === void 0) return;
|
|
9763
|
+
if (Math.abs(x - pending.x) > LONG_PRESS_SLOP || Math.abs(y - pending.y) > LONG_PRESS_SLOP) cancel();
|
|
9764
|
+
};
|
|
9765
|
+
graph.on(_antv_g6.CommonEvent.POINTER_DOWN, on_down);
|
|
9766
|
+
graph.on(_antv_g6.CommonEvent.POINTER_MOVE, on_move);
|
|
9767
|
+
graph.on(_antv_g6.CommonEvent.POINTER_UP, cancel);
|
|
9768
|
+
return () => {
|
|
9769
|
+
cancel();
|
|
9770
|
+
graph.off(_antv_g6.CommonEvent.POINTER_DOWN, on_down);
|
|
9771
|
+
graph.off(_antv_g6.CommonEvent.POINTER_MOVE, on_move);
|
|
9772
|
+
graph.off(_antv_g6.CommonEvent.POINTER_UP, cancel);
|
|
9773
|
+
};
|
|
9774
|
+
}
|
|
9775
|
+
//#endregion
|
|
9507
9776
|
//#region src/g6_drag_canvas_touch.js
|
|
9508
9777
|
/***********************************************************************
|
|
9509
9778
|
* g6_drag_canvas_touch.js
|
|
@@ -9548,6 +9817,12 @@ function yui_graph_refresh_item(gobj, wide) {
|
|
|
9548
9817
|
* every graph (tree, json, treedb, editor) is fixed without
|
|
9549
9818
|
* touching each consumer's behaviors list.
|
|
9550
9819
|
*
|
|
9820
|
+
* It also has to keep the ONE guard the base class has and
|
|
9821
|
+
* this replacement dropped: G6's `onDrag` refuses to pan
|
|
9822
|
+
* while a pinch is in progress. See `is_pinching` in
|
|
9823
|
+
* `g6_touch_gestures.js`, which is where the pinch that
|
|
9824
|
+
* matters is now recognised.
|
|
9825
|
+
*
|
|
9551
9826
|
* Copyright (c) 2026, ArtGins.
|
|
9552
9827
|
* All Rights Reserved.
|
|
9553
9828
|
***********************************************************************/
|
|
@@ -9563,6 +9838,10 @@ var DragCanvasTouch = class extends _antv_g6.DragCanvas {
|
|
|
9563
9838
|
this._lastVP = null;
|
|
9564
9839
|
return;
|
|
9565
9840
|
}
|
|
9841
|
+
if (is_pinching(this.context.graph)) {
|
|
9842
|
+
this._lastVP = null;
|
|
9843
|
+
return;
|
|
9844
|
+
}
|
|
9566
9845
|
let vp = event.viewport;
|
|
9567
9846
|
if (!vp || typeof vp.x !== "number" || typeof vp.y !== "number") return;
|
|
9568
9847
|
if (this._lastVP === null) {
|
|
@@ -9792,6 +10071,7 @@ function mt_create$11(gobj) {
|
|
|
9792
10071
|
priv.theme_observer = yui_watch_theme(gobj);
|
|
9793
10072
|
build_ui$10(gobj);
|
|
9794
10073
|
ensure_drag_canvas_patch();
|
|
10074
|
+
ensure_pinch_zoom_patch();
|
|
9795
10075
|
if (!__layout_registered__$1) {
|
|
9796
10076
|
(0, _antv_g6.register)(_antv_g6.ExtensionCategory.LAYOUT, "json-tree-layout", JsonTreeLayout);
|
|
9797
10077
|
__layout_registered__$1 = true;
|
|
@@ -12420,6 +12700,7 @@ function mt_create$9(gobj) {
|
|
|
12420
12700
|
priv.theme_observer = yui_watch_theme(gobj);
|
|
12421
12701
|
build_ui$8(gobj);
|
|
12422
12702
|
ensure_drag_canvas_patch();
|
|
12703
|
+
ensure_pinch_zoom_patch();
|
|
12423
12704
|
if (!__layout_registered__) {
|
|
12424
12705
|
(0, _antv_g6.register)(_antv_g6.ExtensionCategory.LAYOUT, "gobj-tree-v", GobjTreeVLayout);
|
|
12425
12706
|
(0, _antv_g6.register)(_antv_g6.ExtensionCategory.LAYOUT, "gobj-tree-h", GobjTreeHLayout);
|
|
@@ -47198,6 +47479,20 @@ var ICONS = `<svg xmlns="http://www.w3.org/2000/svg">
|
|
|
47198
47479
|
<symbol id="g6-icon-plus" viewBox="0 0 512 512">
|
|
47199
47480
|
<path fill="currentColor" d="M316 32 L316 196 L480 196 L480 316 L316 316 L316 480 L196 480 L196 316 L32 316 L32 196 L196 196 L196 32 Z"/>
|
|
47200
47481
|
</symbol>
|
|
47482
|
+
<!-- ellipsis-vertical (unfold the floating toolbar).
|
|
47483
|
+
The strip it stands for is a vertical stack, and a vertical
|
|
47484
|
+
ellipsis is what "there is more of this here" is drawn as
|
|
47485
|
+
everywhere else. -->
|
|
47486
|
+
<symbol id="g6-icon-toolbar-show" viewBox="0 0 128 512">
|
|
47487
|
+
<path fill="currentColor" d="M64 360a56 56 0 1 0 0 112 56 56 0 1 0 0-112zm0-160a56 56 0 1 0 0 112 56 56 0 1 0 0-112zM120 96A56 56 0 1 0 8 96a56 56 0 1 0 112 0z"/>
|
|
47488
|
+
</symbol>
|
|
47489
|
+
<!-- xmark (fold the floating toolbar away).
|
|
47490
|
+
Not a chevron: the two toolbars sit on OPPOSITE edges, so a
|
|
47491
|
+
direction would point the wrong way on one of them. What the
|
|
47492
|
+
button does is close an overlay, and that is an x. -->
|
|
47493
|
+
<symbol id="g6-icon-toolbar-hide" viewBox="0 0 384 512">
|
|
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
|
+
</symbol>
|
|
47201
47496
|
<!-- floppy-disk (save) -->
|
|
47202
47497
|
<symbol id="g6-icon-save" viewBox="0 0 448 512">
|
|
47203
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"/>
|
|
@@ -47212,6 +47507,58 @@ function inject_svg_icons() {
|
|
|
47212
47507
|
document.body.appendChild(div);
|
|
47213
47508
|
}
|
|
47214
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
|
|
47215
47562
|
//#region src/c_g6_nodes_tree.js
|
|
47216
47563
|
/***********************************************************************
|
|
47217
47564
|
* c_g6_nodes_tree.js
|
|
@@ -47270,6 +47617,8 @@ var YuiToolbar = class extends _antv_g6.Toolbar {
|
|
|
47270
47617
|
};
|
|
47271
47618
|
(0, _antv_g6.register)(_antv_g6.ExtensionCategory.PLUGIN, "yui-toolbar", YuiToolbar);
|
|
47272
47619
|
ensure_drag_canvas_patch();
|
|
47620
|
+
ensure_brush_select_owned();
|
|
47621
|
+
ensure_pinch_zoom_patch();
|
|
47273
47622
|
/***************************************************************
|
|
47274
47623
|
* Constants
|
|
47275
47624
|
***************************************************************/
|
|
@@ -47389,6 +47738,9 @@ var PRIVATE_DATA$4 = {
|
|
|
47389
47738
|
_focus_topic: null,
|
|
47390
47739
|
_focus_ids: [],
|
|
47391
47740
|
_on_pointerdown_focus: null,
|
|
47741
|
+
_uninstall_long_press: null,
|
|
47742
|
+
toolbar_collapsed: true,
|
|
47743
|
+
_toolbars_could_collapse: null,
|
|
47392
47744
|
_on_focusout_restore: null,
|
|
47393
47745
|
_selected_paint_ids: [],
|
|
47394
47746
|
_pending_focus_topic: null,
|
|
@@ -47474,6 +47826,10 @@ function mt_destroy$4(gobj) {
|
|
|
47474
47826
|
cancelAnimationFrame(priv._resize_raf);
|
|
47475
47827
|
priv._resize_raf = 0;
|
|
47476
47828
|
}
|
|
47829
|
+
if (priv._uninstall_long_press) {
|
|
47830
|
+
priv._uninstall_long_press();
|
|
47831
|
+
priv._uninstall_long_press = null;
|
|
47832
|
+
}
|
|
47477
47833
|
if (priv.graph) {
|
|
47478
47834
|
priv.graph.destroy();
|
|
47479
47835
|
priv.graph = null;
|
|
@@ -47688,6 +48044,8 @@ function configure_plugins(gobj) {
|
|
|
47688
48044
|
return e.targetType === "node" || e.targetType === "edge";
|
|
47689
48045
|
}
|
|
47690
48046
|
});
|
|
48047
|
+
if (priv._uninstall_long_press) priv._uninstall_long_press();
|
|
48048
|
+
priv._uninstall_long_press = install_long_press_contextmenu(priv.graph);
|
|
47691
48049
|
if ((0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "with_toolbar")) {
|
|
47692
48050
|
configure_toolbar(gobj);
|
|
47693
48051
|
configure_toolbar_edit(gobj);
|
|
@@ -47717,6 +48075,55 @@ function update_toolbar(gobj) {
|
|
|
47717
48075
|
* flipping now; the fallbacks are the old forced-light values, so
|
|
47718
48076
|
* a host without Bulma gets exactly what it had.
|
|
47719
48077
|
************************************************************/
|
|
48078
|
+
/************************************************************
|
|
48079
|
+
* Is the canvas too narrow to give both floating toolbars a
|
|
48080
|
+
* strip of it?
|
|
48081
|
+
*
|
|
48082
|
+
* They are drawn INSIDE the canvas, one on each edge. On a
|
|
48083
|
+
* desktop that is a corner; on a 356px-wide phone canvas the
|
|
48084
|
+
* two of them take a third of the drawing area and stand on
|
|
48085
|
+
* top of the nodes -- and a node under a toolbar cannot be
|
|
48086
|
+
* read, tapped or dragged out from under it.
|
|
48087
|
+
*
|
|
48088
|
+
* Measured on the CONTAINER, not on the window: the same
|
|
48089
|
+
* graph is a full page in one app and a card in a column in
|
|
48090
|
+
* another, and it is the box it actually got that decides.
|
|
48091
|
+
************************************************************/
|
|
48092
|
+
var TOOLBAR_COLLAPSE_WIDTH = 480;
|
|
48093
|
+
function toolbars_can_collapse(gobj) {
|
|
48094
|
+
let $container = gobj.priv.$container;
|
|
48095
|
+
if (!$container) return false;
|
|
48096
|
+
let width = $container.getBoundingClientRect().width;
|
|
48097
|
+
if (!width) return false;
|
|
48098
|
+
return width < TOOLBAR_COLLAPSE_WIDTH;
|
|
48099
|
+
}
|
|
48100
|
+
/************************************************************
|
|
48101
|
+
* Are they folded RIGHT NOW? Wide enough and the question
|
|
48102
|
+
* does not arise -- the desktop toolbar never grows a button
|
|
48103
|
+
* it does not need.
|
|
48104
|
+
************************************************************/
|
|
48105
|
+
function toolbars_collapsed(gobj) {
|
|
48106
|
+
if (!toolbars_can_collapse(gobj)) return false;
|
|
48107
|
+
return gobj.priv.toolbar_collapsed !== false;
|
|
48108
|
+
}
|
|
48109
|
+
/************************************************************
|
|
48110
|
+
* The one item a folded toolbar shows, and the one an
|
|
48111
|
+
* unfolded narrow toolbar adds to fold itself again.
|
|
48112
|
+
************************************************************/
|
|
48113
|
+
function toolbar_fold_item(gobj) {
|
|
48114
|
+
if (toolbars_collapsed(gobj)) return {
|
|
48115
|
+
id: "g6-icon-toolbar-show",
|
|
48116
|
+
value: "toolbar-toggle",
|
|
48117
|
+
className: "EV_TOGGLE_TOOLBARS",
|
|
48118
|
+
title: (0, i18next.t)("show toolbar")
|
|
48119
|
+
};
|
|
48120
|
+
return {
|
|
48121
|
+
id: "g6-icon-toolbar-hide",
|
|
48122
|
+
value: "toolbar-toggle",
|
|
48123
|
+
className: "EV_TOGGLE_TOOLBARS",
|
|
48124
|
+
title: (0, i18next.t)("hide toolbar")
|
|
48125
|
+
};
|
|
48126
|
+
}
|
|
47720
48127
|
function toolbar_style(extra) {
|
|
47721
48128
|
return Object.assign({
|
|
47722
48129
|
backgroundColor: "var(--bulma-scheme-main, #f5f5f5)",
|
|
@@ -47774,6 +48181,7 @@ function configure_toolbar(gobj) {
|
|
|
47774
48181
|
marginLeft: "12px"
|
|
47775
48182
|
}),
|
|
47776
48183
|
getItems: () => {
|
|
48184
|
+
if (toolbars_collapsed(gobj)) return [toolbar_fold_item(gobj)];
|
|
47777
48185
|
let items = [
|
|
47778
48186
|
{
|
|
47779
48187
|
id: "g6-icon-zoom-in",
|
|
@@ -47829,6 +48237,10 @@ function configure_toolbar(gobj) {
|
|
|
47829
48237
|
title: (0, i18next.t)("enter full screen")
|
|
47830
48238
|
});
|
|
47831
48239
|
}
|
|
48240
|
+
if (toolbars_can_collapse(gobj)) {
|
|
48241
|
+
items.push({ separator: true });
|
|
48242
|
+
items.push(toolbar_fold_item(gobj));
|
|
48243
|
+
}
|
|
47832
48244
|
return items;
|
|
47833
48245
|
},
|
|
47834
48246
|
onClick: (value) => {
|
|
@@ -47854,7 +48266,10 @@ function configure_toolbar(gobj) {
|
|
|
47854
48266
|
case "request-fullscreen":
|
|
47855
48267
|
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_REQUEST_FULLSCREEN", {}, gobj);
|
|
47856
48268
|
break;
|
|
47857
|
-
case "exit-fullscreen":
|
|
48269
|
+
case "exit-fullscreen":
|
|
48270
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_EXIT_FULLSCREEN", {}, gobj);
|
|
48271
|
+
break;
|
|
48272
|
+
case "toolbar-toggle": (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_TOGGLE_TOOLBARS", {}, gobj);
|
|
47858
48273
|
}
|
|
47859
48274
|
}
|
|
47860
48275
|
});
|
|
@@ -47864,7 +48279,7 @@ function configure_toolbar(gobj) {
|
|
|
47864
48279
|
* Contains edit-mode buttons: Undo, Redo, Save
|
|
47865
48280
|
************************************************************/
|
|
47866
48281
|
function configure_toolbar_edit(gobj) {
|
|
47867
|
-
if (!gobj.priv.edit_mode) {
|
|
48282
|
+
if (!gobj.priv.edit_mode || toolbars_collapsed(gobj)) {
|
|
47868
48283
|
graph_remove_plugin(gobj, "toolbar-edit");
|
|
47869
48284
|
return;
|
|
47870
48285
|
}
|
|
@@ -47953,12 +48368,16 @@ function configure_behaviour(gobj) {
|
|
|
47953
48368
|
{
|
|
47954
48369
|
type: "drag-canvas",
|
|
47955
48370
|
key: "drag-canvas",
|
|
47956
|
-
enable: (event) =>
|
|
48371
|
+
enable: (event) => {
|
|
48372
|
+
if (event.shiftKey) return false;
|
|
48373
|
+
if ("targetType" in event) return event.targetType === "canvas";
|
|
48374
|
+
return true;
|
|
48375
|
+
}
|
|
47957
48376
|
},
|
|
47958
48377
|
"zoom-canvas",
|
|
47959
48378
|
"drag-element",
|
|
47960
48379
|
{
|
|
47961
|
-
type:
|
|
48380
|
+
type: BRUSH_SELECT_OWNED,
|
|
47962
48381
|
key: "brush-select",
|
|
47963
48382
|
trigger: ["shift"],
|
|
47964
48383
|
enableElements: ["node"],
|
|
@@ -47972,6 +48391,7 @@ function configure_behaviour(gobj) {
|
|
|
47972
48391
|
break;
|
|
47973
48392
|
case "operation":
|
|
47974
48393
|
priv.edit_mode = false;
|
|
48394
|
+
behaviors = ["drag-canvas", "zoom-canvas"];
|
|
47975
48395
|
break;
|
|
47976
48396
|
default: (0, _yuneta_gobj_js.log_error)(`operation mode unknown: ${operation_mode}`);
|
|
47977
48397
|
}
|
|
@@ -48541,6 +48961,30 @@ function history_resume(gobj) {
|
|
|
48541
48961
|
gobj.priv._history_paused = false;
|
|
48542
48962
|
}
|
|
48543
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
|
+
/************************************************************
|
|
48544
48988
|
*
|
|
48545
48989
|
************************************************************/
|
|
48546
48990
|
function update_history_buttons(gobj) {
|
|
@@ -48831,6 +49275,7 @@ function graph_add_plugin(gobj, plugin_key, options) {
|
|
|
48831
49275
|
let priv = gobj.priv;
|
|
48832
49276
|
let graph = priv.graph;
|
|
48833
49277
|
let plugin = graph_get_plugin(gobj, plugin_key);
|
|
49278
|
+
let existed = !!plugin;
|
|
48834
49279
|
if (!plugin) {
|
|
48835
49280
|
let plugin_def = {
|
|
48836
49281
|
key: plugin_key,
|
|
@@ -48841,7 +49286,7 @@ function graph_add_plugin(gobj, plugin_key, options) {
|
|
|
48841
49286
|
}
|
|
48842
49287
|
plugin = graph_get_plugin(gobj, plugin_key);
|
|
48843
49288
|
switch (plugin_key) {
|
|
48844
|
-
case "history": if (plugin) {
|
|
49289
|
+
case "history": if (plugin && !existed) {
|
|
48845
49290
|
plugin.on(_antv_g6.HistoryEvent.CHANGE, () => {
|
|
48846
49291
|
update_history_buttons(gobj);
|
|
48847
49292
|
});
|
|
@@ -48934,6 +49379,14 @@ var ManualLayout = class extends _antv_g6.BaseLayout {
|
|
|
48934
49379
|
************************************************************/
|
|
48935
49380
|
var RESIZE_HANDLE_SIZE = 8;
|
|
48936
49381
|
var RESIZE_MIN_VP = 20;
|
|
49382
|
+
var RESIZE_HANDLE_VISUAL_COARSE = 14;
|
|
49383
|
+
var RESIZE_HANDLE_HIT_COARSE = 44;
|
|
49384
|
+
function resize_handle_visual() {
|
|
49385
|
+
return coarse_pointer() ? RESIZE_HANDLE_VISUAL_COARSE : RESIZE_HANDLE_SIZE;
|
|
49386
|
+
}
|
|
49387
|
+
function resize_handle_hit() {
|
|
49388
|
+
return coarse_pointer() ? RESIZE_HANDLE_HIT_COARSE : RESIZE_HANDLE_SIZE;
|
|
49389
|
+
}
|
|
48937
49390
|
/************************************************************
|
|
48938
49391
|
* SVG icons for floating action buttons (28×28 circles).
|
|
48939
49392
|
* Each value is a raw SVG string sized 18×18 in a 24×24 viewBox.
|
|
@@ -48946,7 +49399,50 @@ var SVG_ICONS = {
|
|
|
48946
49399
|
plus: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/></svg>"
|
|
48947
49400
|
};
|
|
48948
49401
|
/************************************************************
|
|
48949
|
-
*
|
|
49402
|
+
* Is the primary pointer a FINGER?
|
|
49403
|
+
*
|
|
49404
|
+
* Everything this gclass draws over the canvas is sized from
|
|
49405
|
+
* this answer. A mouse is a pixel and can hit an 8px square;
|
|
49406
|
+
* a fingertip covers about 40, and the overlay it lands on
|
|
49407
|
+
* decides between "open the properties" and "delete the node".
|
|
49408
|
+
*
|
|
49409
|
+
* Asked per call, not cached: a tablet with a keyboard dock
|
|
49410
|
+
* changes the answer without reloading the page.
|
|
49411
|
+
************************************************************/
|
|
49412
|
+
function coarse_pointer() {
|
|
49413
|
+
if (typeof window.matchMedia !== "function") return false;
|
|
49414
|
+
try {
|
|
49415
|
+
return window.matchMedia("(pointer: coarse)").matches === true;
|
|
49416
|
+
} catch (e) {
|
|
49417
|
+
return false;
|
|
49418
|
+
}
|
|
49419
|
+
}
|
|
49420
|
+
/************************************************************
|
|
49421
|
+
* The size of the round floating buttons (properties,
|
|
49422
|
+
* delete, link), and the GAP between two of them.
|
|
49423
|
+
*
|
|
49424
|
+
* The gap matters as much as the size: `node properties` and
|
|
49425
|
+
* `delete node` are drawn one under the other, and at 28px
|
|
49426
|
+
* with 4px between them a fingertip covers both -- with the
|
|
49427
|
+
* destructive one underneath.
|
|
49428
|
+
************************************************************/
|
|
49429
|
+
function floating_icon_size() {
|
|
49430
|
+
return coarse_pointer() ? 44 : 28;
|
|
49431
|
+
}
|
|
49432
|
+
function floating_icon_gap() {
|
|
49433
|
+
return coarse_pointer() ? 12 : 4;
|
|
49434
|
+
}
|
|
49435
|
+
function floating_icon_dy() {
|
|
49436
|
+
return -floating_icon_size() / 2;
|
|
49437
|
+
}
|
|
49438
|
+
function floating_icon_step() {
|
|
49439
|
+
return floating_icon_size() + floating_icon_gap();
|
|
49440
|
+
}
|
|
49441
|
+
function floating_popover_dx() {
|
|
49442
|
+
return 4 + floating_icon_size() + 4;
|
|
49443
|
+
}
|
|
49444
|
+
/************************************************************
|
|
49445
|
+
* Create a floating circular icon button.
|
|
48950
49446
|
* @param {string} svgKey - key into SVG_ICONS
|
|
48951
49447
|
* @param {string} color - border & text color (e.g. '#1890ff')
|
|
48952
49448
|
* @param {number} left - CSS left in px
|
|
@@ -48956,10 +49452,18 @@ var SVG_ICONS = {
|
|
|
48956
49452
|
* @returns {HTMLElement}
|
|
48957
49453
|
************************************************************/
|
|
48958
49454
|
function create_floating_icon(svgKey, color, left, top, title, onClick) {
|
|
49455
|
+
const size = floating_icon_size();
|
|
48959
49456
|
const el = document.createElement("div");
|
|
48960
49457
|
el.title = title;
|
|
49458
|
+
el.setAttribute("aria-label", title);
|
|
48961
49459
|
el.innerHTML = SVG_ICONS[svgKey] || "";
|
|
48962
|
-
el.style.cssText = "position:absolute;left:" + left + "px;top:" + top + "px;width:
|
|
49460
|
+
el.style.cssText = "position:absolute;left:" + left + "px;top:" + top + "px;width:" + size + "px;height:" + size + "px;display:flex;align-items:center;justify-content:center;background:#fff;border:1px solid " + color + ";border-radius:50%;cursor:pointer;pointer-events:all;z-index:11;touch-action:none;box-shadow:0 2px 6px rgba(0,0,0,0.15);color:" + color + ";";
|
|
49461
|
+
const $svg = el.querySelector("svg");
|
|
49462
|
+
if ($svg) {
|
|
49463
|
+
const glyph = Math.round(size * .5);
|
|
49464
|
+
$svg.setAttribute("width", String(glyph));
|
|
49465
|
+
$svg.setAttribute("height", String(glyph));
|
|
49466
|
+
}
|
|
48963
49467
|
el.addEventListener("click", (e) => {
|
|
48964
49468
|
e.stopPropagation();
|
|
48965
49469
|
onClick();
|
|
@@ -49005,7 +49509,7 @@ function show_dual_icons(gobj, x, y, gear_title, gear_click, trash_title, trash_
|
|
|
49005
49509
|
let priv = gobj.priv;
|
|
49006
49510
|
const icon_el = create_floating_icon("gear", "#1890ff", x, y, gear_title, gear_click);
|
|
49007
49511
|
priv.$container.appendChild(icon_el);
|
|
49008
|
-
const delete_el = create_floating_icon("trash", "#ff4d4f", x, y +
|
|
49512
|
+
const delete_el = create_floating_icon("trash", "#ff4d4f", x, y + floating_icon_step(), trash_title, trash_click);
|
|
49009
49513
|
priv.$container.appendChild(delete_el);
|
|
49010
49514
|
return {
|
|
49011
49515
|
icon_el,
|
|
@@ -49023,6 +49527,21 @@ function create_popover_base(left, top, className, borderColor, minWidth) {
|
|
|
49023
49527
|
popover.addEventListener("pointerdown", (e) => e.stopPropagation());
|
|
49024
49528
|
return popover;
|
|
49025
49529
|
}
|
|
49530
|
+
/************************************************************
|
|
49531
|
+
* Extra CSS every control inside a popover carries on a
|
|
49532
|
+
* touch screen.
|
|
49533
|
+
*
|
|
49534
|
+
* A popover is where the graph is TYPED into -- a colour, a
|
|
49535
|
+
* radius, an id -- and its controls were sized by their
|
|
49536
|
+
* padding alone, which lands them at 25-30px. A finger needs
|
|
49537
|
+
* 44, and the number is not ours: it is the floor both Apple
|
|
49538
|
+
* and Google publish, and the one every native control on the
|
|
49539
|
+
* device already meets.
|
|
49540
|
+
************************************************************/
|
|
49541
|
+
function touch_control_css() {
|
|
49542
|
+
if (!coarse_pointer()) return "";
|
|
49543
|
+
return "min-height:44px;font-size:16px;";
|
|
49544
|
+
}
|
|
49026
49545
|
function create_form_label(parent, text) {
|
|
49027
49546
|
let label = document.createElement("label");
|
|
49028
49547
|
label.textContent = (0, i18next.t)(text);
|
|
@@ -49034,7 +49553,7 @@ function create_form_color_input(parent, value, onInput) {
|
|
|
49034
49553
|
let input = document.createElement("input");
|
|
49035
49554
|
input.type = "color";
|
|
49036
49555
|
input.value = value;
|
|
49037
|
-
input.style.cssText = "width:100%;height:30px;padding:0;border:1px solid var(--bulma-border-weak, #d9d9d9);border-radius:4px;cursor:pointer;margin-bottom:10px;";
|
|
49556
|
+
input.style.cssText = "width:100%;height:30px;padding:0;border:1px solid var(--bulma-border-weak, #d9d9d9);border-radius:4px;cursor:pointer;margin-bottom:10px;" + touch_control_css();
|
|
49038
49557
|
if (onInput) input.addEventListener("input", onInput);
|
|
49039
49558
|
parent.appendChild(input);
|
|
49040
49559
|
return input;
|
|
@@ -49045,14 +49564,14 @@ function create_form_number_input(parent, value, min, max, onInput) {
|
|
|
49045
49564
|
input.min = String(min);
|
|
49046
49565
|
input.max = String(max);
|
|
49047
49566
|
input.value = value;
|
|
49048
|
-
input.style.cssText = "width:100%;padding:4px 6px;background:var(--bulma-scheme-main-bis, #fff);color:var(--bulma-text-strong, #333);border:1px solid var(--bulma-border-weak, #d9d9d9);border-radius:4px;box-sizing:border-box;margin-bottom:10px;";
|
|
49567
|
+
input.style.cssText = "width:100%;padding:4px 6px;background:var(--bulma-scheme-main-bis, #fff);color:var(--bulma-text-strong, #333);border:1px solid var(--bulma-border-weak, #d9d9d9);border-radius:4px;box-sizing:border-box;margin-bottom:10px;" + touch_control_css();
|
|
49049
49568
|
if (onInput) input.addEventListener("input", onInput);
|
|
49050
49569
|
parent.appendChild(input);
|
|
49051
49570
|
return input;
|
|
49052
49571
|
}
|
|
49053
49572
|
function create_form_select(parent, options, marginBottom) {
|
|
49054
49573
|
let select = document.createElement("select");
|
|
49055
|
-
select.style.cssText = "width:100%;padding:4px 6px;background:var(--bulma-scheme-main-bis, #fff);color:var(--bulma-text-strong, #333);border:1px solid var(--bulma-border-weak, #d9d9d9);border-radius:4px;box-sizing:border-box;margin-bottom:" + (marginBottom || "12px") + ";";
|
|
49574
|
+
select.style.cssText = "width:100%;padding:4px 6px;background:var(--bulma-scheme-main-bis, #fff);color:var(--bulma-text-strong, #333);border:1px solid var(--bulma-border-weak, #d9d9d9);border-radius:4px;box-sizing:border-box;margin-bottom:" + (marginBottom || "12px") + ";" + touch_control_css();
|
|
49056
49575
|
for (let opt of options) {
|
|
49057
49576
|
let o = document.createElement("option");
|
|
49058
49577
|
o.value = opt.value;
|
|
@@ -49069,7 +49588,7 @@ function create_form_button_row(parent, buttons) {
|
|
|
49069
49588
|
for (let { text, style, onClick } of buttons) {
|
|
49070
49589
|
let btn = document.createElement("button");
|
|
49071
49590
|
btn.textContent = (0, i18next.t)(text);
|
|
49072
|
-
btn.style.cssText = style;
|
|
49591
|
+
btn.style.cssText = style + touch_control_css();
|
|
49073
49592
|
btn.addEventListener("click", (e) => {
|
|
49074
49593
|
e.stopPropagation();
|
|
49075
49594
|
onClick();
|
|
@@ -49307,7 +49826,7 @@ function show_resize_handles(gobj) {
|
|
|
49307
49826
|
container.style.cssText = "position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:10;";
|
|
49308
49827
|
const selRect = document.createElement("div");
|
|
49309
49828
|
container.appendChild(selRect);
|
|
49310
|
-
|
|
49829
|
+
let handle_defs = [
|
|
49311
49830
|
{
|
|
49312
49831
|
cursor: "nw-resize",
|
|
49313
49832
|
mx: -1,
|
|
@@ -49349,10 +49868,16 @@ function show_resize_handles(gobj) {
|
|
|
49349
49868
|
my: 1
|
|
49350
49869
|
}
|
|
49351
49870
|
];
|
|
49871
|
+
const hit = resize_handle_hit();
|
|
49872
|
+
const visual = resize_handle_visual();
|
|
49873
|
+
if (coarse_pointer()) handle_defs = handle_defs.filter((def) => def.mx !== 0 && def.my !== 0);
|
|
49352
49874
|
const handles = [];
|
|
49353
49875
|
for (const def of handle_defs) {
|
|
49354
49876
|
const el = document.createElement("div");
|
|
49355
|
-
el.style.cssText = "position:absolute;width:
|
|
49877
|
+
el.style.cssText = "position:absolute;width:" + hit + "px;height:" + hit + "px;display:flex;align-items:center;justify-content:center;cursor:" + def.cursor + ";pointer-events:all;touch-action:none;box-sizing:border-box;";
|
|
49878
|
+
const mark = document.createElement("div");
|
|
49879
|
+
mark.style.cssText = "width:" + visual + "px;height:" + visual + "px;background:#fff;border:1px solid #1890ff;pointer-events:none;box-sizing:border-box;";
|
|
49880
|
+
el.appendChild(mark);
|
|
49356
49881
|
el.addEventListener("pointerdown", (e) => {
|
|
49357
49882
|
start_node_resize(gobj, e, def.mx, def.my);
|
|
49358
49883
|
});
|
|
@@ -49392,52 +49917,18 @@ function update_resize_handles_position(gobj) {
|
|
|
49392
49917
|
}
|
|
49393
49918
|
function apply_handles_to_rect(gobj, rect) {
|
|
49394
49919
|
let priv = gobj.priv;
|
|
49395
|
-
const HALF =
|
|
49920
|
+
const HALF = resize_handle_hit() / 2;
|
|
49396
49921
|
const left = rect.left;
|
|
49397
49922
|
const top = rect.top;
|
|
49398
49923
|
const w = rect.right - rect.left;
|
|
49399
49924
|
const h = rect.bottom - rect.top;
|
|
49400
49925
|
const selRect = priv._resize_sel_rect;
|
|
49401
49926
|
if (selRect) selRect.style.cssText = "position:absolute;left:" + left + "px;top:" + top + "px;width:" + w + "px;height:" + h + "px;border:1px dashed #1890ff;pointer-events:none;box-sizing:border-box;";
|
|
49402
|
-
const
|
|
49403
|
-
|
|
49404
|
-
|
|
49405
|
-
|
|
49406
|
-
|
|
49407
|
-
{
|
|
49408
|
-
x: left + w / 2,
|
|
49409
|
-
y: top
|
|
49410
|
-
},
|
|
49411
|
-
{
|
|
49412
|
-
x: left + w,
|
|
49413
|
-
y: top
|
|
49414
|
-
},
|
|
49415
|
-
{
|
|
49416
|
-
x: left,
|
|
49417
|
-
y: top + h / 2
|
|
49418
|
-
},
|
|
49419
|
-
{
|
|
49420
|
-
x: left + w,
|
|
49421
|
-
y: top + h / 2
|
|
49422
|
-
},
|
|
49423
|
-
{
|
|
49424
|
-
x: left,
|
|
49425
|
-
y: top + h
|
|
49426
|
-
},
|
|
49427
|
-
{
|
|
49428
|
-
x: left + w / 2,
|
|
49429
|
-
y: top + h
|
|
49430
|
-
},
|
|
49431
|
-
{
|
|
49432
|
-
x: left + w,
|
|
49433
|
-
y: top + h
|
|
49434
|
-
}
|
|
49435
|
-
];
|
|
49436
|
-
for (let i = 0; i < priv._resize_handles.length; i++) {
|
|
49437
|
-
const handle = priv._resize_handles[i];
|
|
49438
|
-
const p = positions[i];
|
|
49439
|
-
handle.el.style.left = p.x - HALF + "px";
|
|
49440
|
-
handle.el.style.top = p.y - HALF + "px";
|
|
49927
|
+
for (const handle of priv._resize_handles) {
|
|
49928
|
+
const x = left + (handle.mx + 1) / 2 * w;
|
|
49929
|
+
const y = top + (handle.my + 1) / 2 * h;
|
|
49930
|
+
handle.el.style.left = x - HALF + "px";
|
|
49931
|
+
handle.el.style.top = y - HALF + "px";
|
|
49441
49932
|
}
|
|
49442
49933
|
}
|
|
49443
49934
|
function start_node_resize(gobj, e, mx, my) {
|
|
@@ -49513,6 +50004,14 @@ function start_node_resize(gobj, e, mx, my) {
|
|
|
49513
50004
|
* Port selection and individual port resizing
|
|
49514
50005
|
************************************************************/
|
|
49515
50006
|
var PORT_HANDLE_SIZE = 8;
|
|
50007
|
+
var PORT_HANDLE_VISUAL_COARSE = 12;
|
|
50008
|
+
var PORT_HANDLE_HIT_COARSE = 32;
|
|
50009
|
+
function port_handle_visual() {
|
|
50010
|
+
return coarse_pointer() ? PORT_HANDLE_VISUAL_COARSE : PORT_HANDLE_SIZE;
|
|
50011
|
+
}
|
|
50012
|
+
function port_handle_hit() {
|
|
50013
|
+
return coarse_pointer() ? PORT_HANDLE_HIT_COARSE : PORT_HANDLE_SIZE;
|
|
50014
|
+
}
|
|
49516
50015
|
/************************************************************
|
|
49517
50016
|
* Compute the canvas (world) position of a port on a node.
|
|
49518
50017
|
* Returns {x, y} in world coordinates.
|
|
@@ -49545,6 +50044,26 @@ function get_port_radius(gobj, node_id, port_key) {
|
|
|
49545
50044
|
return style.portR || 6;
|
|
49546
50045
|
}
|
|
49547
50046
|
/************************************************************
|
|
50047
|
+
* How much wider than the port itself its hit area is,
|
|
50048
|
+
* measured on the SCREEN and converted to world units.
|
|
50049
|
+
*
|
|
50050
|
+
* It used to be a flat `+4` in WORLD units, which is a
|
|
50051
|
+
* different target on every zoom: at the 50% a phone lands on
|
|
50052
|
+
* after fit, a 6-unit port plus 4 is a 5px radius -- one
|
|
50053
|
+
* fifth of a fingertip, and picking a port is the first step
|
|
50054
|
+
* of every link.
|
|
50055
|
+
************************************************************/
|
|
50056
|
+
function port_hit_slop_world(graph) {
|
|
50057
|
+
let slop = coarse_pointer() ? 22 : 6;
|
|
50058
|
+
let zoom = 1;
|
|
50059
|
+
try {
|
|
50060
|
+
zoom = graph.getZoom() || 1;
|
|
50061
|
+
} catch (e) {
|
|
50062
|
+
zoom = 1;
|
|
50063
|
+
}
|
|
50064
|
+
return slop / zoom;
|
|
50065
|
+
}
|
|
50066
|
+
/************************************************************
|
|
49548
50067
|
* Detect if a click in canvas coordinates hits a port.
|
|
49549
50068
|
* Returns the port key string, or null if no port hit.
|
|
49550
50069
|
************************************************************/
|
|
@@ -49557,6 +50076,7 @@ function detect_port_click(gobj, node_id, canvasX, canvasY) {
|
|
|
49557
50076
|
const defaultR = style.portR || 6;
|
|
49558
50077
|
let best_key = null;
|
|
49559
50078
|
let best_dist = Infinity;
|
|
50079
|
+
let slop = port_hit_slop_world(graph);
|
|
49560
50080
|
for (let i = 0; i < ports.length; i++) {
|
|
49561
50081
|
let pl = ports[i].placement || [.5, .5];
|
|
49562
50082
|
let px = pos[0] + (pl[0] - .5) * w;
|
|
@@ -49565,7 +50085,7 @@ function detect_port_click(gobj, node_id, canvasX, canvasY) {
|
|
|
49565
50085
|
let dx = canvasX - px;
|
|
49566
50086
|
let dy = canvasY - py;
|
|
49567
50087
|
let dist = Math.sqrt(dx * dx + dy * dy);
|
|
49568
|
-
if (dist <= r +
|
|
50088
|
+
if (dist <= r + slop && dist < best_dist) {
|
|
49569
50089
|
best_dist = dist;
|
|
49570
50090
|
best_key = ports[i].key;
|
|
49571
50091
|
}
|
|
@@ -49613,7 +50133,7 @@ function show_link_icon_if_fkey(gobj) {
|
|
|
49613
50133
|
let canvasPos = get_port_canvas_position(gobj, priv._selected_node_id, priv._selected_port_key);
|
|
49614
50134
|
if (!canvasPos) return;
|
|
49615
50135
|
let vp = graph.getViewportByCanvas([canvasPos.x, canvasPos.y]);
|
|
49616
|
-
let icon = create_floating_icon("link", "#52c41a", vp[0] +
|
|
50136
|
+
let icon = create_floating_icon("link", "#52c41a", vp[0] + floating_icon_size() / 2 + 4, vp[1] + floating_icon_dy(), (0, i18next.t)("link to hook"), () => {
|
|
49617
50137
|
if (!priv._linking_mode) enter_linking_mode(gobj);
|
|
49618
50138
|
});
|
|
49619
50139
|
icon.addEventListener("pointerdown", (e) => {
|
|
@@ -49638,8 +50158,8 @@ function update_link_icon_position(gobj) {
|
|
|
49638
50158
|
return;
|
|
49639
50159
|
}
|
|
49640
50160
|
let vp = graph.getViewportByCanvas([canvasPos.x, canvasPos.y]);
|
|
49641
|
-
priv._link_icon_el.style.left = vp[0] +
|
|
49642
|
-
priv._link_icon_el.style.top = vp[1]
|
|
50161
|
+
priv._link_icon_el.style.left = vp[0] + floating_icon_size() / 2 + 4 + "px";
|
|
50162
|
+
priv._link_icon_el.style.top = vp[1] + floating_icon_dy() + "px";
|
|
49643
50163
|
} catch (e) {
|
|
49644
50164
|
hide_link_icon(gobj);
|
|
49645
50165
|
}
|
|
@@ -49907,10 +50427,15 @@ function show_port_resize_handles(gobj) {
|
|
|
49907
50427
|
dy: 0
|
|
49908
50428
|
}
|
|
49909
50429
|
];
|
|
50430
|
+
const hit = port_handle_hit();
|
|
50431
|
+
const visual = port_handle_visual();
|
|
49910
50432
|
const handles = [];
|
|
49911
50433
|
for (const def of handle_defs) {
|
|
49912
50434
|
const el = document.createElement("div");
|
|
49913
|
-
el.style.cssText = "position:absolute;width:
|
|
50435
|
+
el.style.cssText = "position:absolute;width:" + hit + "px;height:" + hit + "px;display:flex;align-items:center;justify-content:center;cursor:" + def.cursor + ";pointer-events:all;touch-action:none;box-sizing:border-box;";
|
|
50436
|
+
const mark = document.createElement("div");
|
|
50437
|
+
mark.style.cssText = "width:" + visual + "px;height:" + visual + "px;background:#fff;border:1px solid #fa8c16;border-radius:50%;pointer-events:none;box-sizing:border-box;";
|
|
50438
|
+
el.appendChild(mark);
|
|
49914
50439
|
el.addEventListener("pointerdown", (e) => {
|
|
49915
50440
|
start_port_resize(gobj, e);
|
|
49916
50441
|
});
|
|
@@ -49964,7 +50489,7 @@ function update_port_resize_handles_position(gobj) {
|
|
|
49964
50489
|
************************************************************/
|
|
49965
50490
|
function apply_port_handles(gobj, cx, cy, vpR) {
|
|
49966
50491
|
let priv = gobj.priv;
|
|
49967
|
-
const HALF =
|
|
50492
|
+
const HALF = port_handle_hit() / 2;
|
|
49968
50493
|
const ring = priv._port_ring;
|
|
49969
50494
|
if (ring) {
|
|
49970
50495
|
const d = vpR * 2;
|
|
@@ -50109,7 +50634,7 @@ function show_edge_icon(gobj) {
|
|
|
50109
50634
|
if (!priv._selected_edge_id) return;
|
|
50110
50635
|
let mid = get_edge_viewport_midpoint(gobj, priv._selected_edge_id);
|
|
50111
50636
|
if (!mid) return;
|
|
50112
|
-
let icons = show_dual_icons(gobj, mid.x + 4, mid.y
|
|
50637
|
+
let icons = show_dual_icons(gobj, mid.x + 4, mid.y + floating_icon_dy(), (0, i18next.t)("edge properties"), () => toggle_edge_popover(gobj), (0, i18next.t)("unlink"), () => request_unlink_edge(gobj));
|
|
50113
50638
|
priv._edge_icon_el = icons.icon_el;
|
|
50114
50639
|
priv._edge_delete_el = icons.delete_el;
|
|
50115
50640
|
}
|
|
@@ -50127,14 +50652,14 @@ function update_edge_icon_position(gobj) {
|
|
|
50127
50652
|
return;
|
|
50128
50653
|
}
|
|
50129
50654
|
priv._edge_icon_el.style.left = mid.x + 4 + "px";
|
|
50130
|
-
priv._edge_icon_el.style.top = mid.y
|
|
50655
|
+
priv._edge_icon_el.style.top = mid.y + floating_icon_dy() + "px";
|
|
50131
50656
|
if (priv._edge_delete_el) {
|
|
50132
50657
|
priv._edge_delete_el.style.left = mid.x + 4 + "px";
|
|
50133
|
-
priv._edge_delete_el.style.top = mid.y +
|
|
50658
|
+
priv._edge_delete_el.style.top = mid.y + floating_icon_dy() + floating_icon_step() + "px";
|
|
50134
50659
|
}
|
|
50135
50660
|
if (priv._edge_popover_el) {
|
|
50136
|
-
priv._edge_popover_el.style.left = mid.x +
|
|
50137
|
-
priv._edge_popover_el.style.top = mid.y
|
|
50661
|
+
priv._edge_popover_el.style.left = mid.x + floating_popover_dx() + "px";
|
|
50662
|
+
priv._edge_popover_el.style.top = mid.y + floating_icon_dy() + "px";
|
|
50138
50663
|
clamp_popover_position(gobj, priv._edge_popover_el);
|
|
50139
50664
|
}
|
|
50140
50665
|
} catch (e) {
|
|
@@ -50172,7 +50697,7 @@ function show_edge_popover(gobj) {
|
|
|
50172
50697
|
});
|
|
50173
50698
|
let mid = get_edge_viewport_midpoint(gobj, edge_id);
|
|
50174
50699
|
if (!mid) return;
|
|
50175
|
-
const popover = create_popover_base(mid.x +
|
|
50700
|
+
const popover = create_popover_base(mid.x + floating_popover_dx(), mid.y + floating_icon_dy(), "g6-edge-popover", "#d9d9d9", 180);
|
|
50176
50701
|
function preview_edge() {
|
|
50177
50702
|
let lw = parseInt(lwInput.value) || 2;
|
|
50178
50703
|
let color = colorInput.value;
|
|
@@ -50259,7 +50784,7 @@ function show_node_icon(gobj) {
|
|
|
50259
50784
|
if (!priv._selected_node_id || priv._selected_port_key) return;
|
|
50260
50785
|
let rect = get_node_viewport_rect(gobj, priv._selected_node_id);
|
|
50261
50786
|
if (!rect) return;
|
|
50262
|
-
let icons = show_dual_icons(gobj, rect.right + 4, rect.top
|
|
50787
|
+
let icons = show_dual_icons(gobj, rect.right + 4, rect.top + floating_icon_dy(), (0, i18next.t)("node properties"), () => toggle_node_popover(gobj), (0, i18next.t)("delete node"), () => request_delete_node(gobj));
|
|
50263
50788
|
priv._node_icon_el = icons.icon_el;
|
|
50264
50789
|
priv._node_delete_el = icons.delete_el;
|
|
50265
50790
|
}
|
|
@@ -50281,14 +50806,14 @@ function update_node_icon_position(gobj) {
|
|
|
50281
50806
|
return;
|
|
50282
50807
|
}
|
|
50283
50808
|
priv._node_icon_el.style.left = rect.right + 4 + "px";
|
|
50284
|
-
priv._node_icon_el.style.top = rect.top
|
|
50809
|
+
priv._node_icon_el.style.top = rect.top + floating_icon_dy() + "px";
|
|
50285
50810
|
if (priv._node_delete_el) {
|
|
50286
50811
|
priv._node_delete_el.style.left = rect.right + 4 + "px";
|
|
50287
|
-
priv._node_delete_el.style.top = rect.top +
|
|
50812
|
+
priv._node_delete_el.style.top = rect.top + floating_icon_dy() + floating_icon_step() + "px";
|
|
50288
50813
|
}
|
|
50289
50814
|
if (priv._node_popover_el) {
|
|
50290
|
-
priv._node_popover_el.style.left = rect.right +
|
|
50291
|
-
priv._node_popover_el.style.top = rect.top
|
|
50815
|
+
priv._node_popover_el.style.left = rect.right + floating_popover_dx() + "px";
|
|
50816
|
+
priv._node_popover_el.style.top = rect.top + floating_icon_dy() + "px";
|
|
50292
50817
|
clamp_popover_position(gobj, priv._node_popover_el);
|
|
50293
50818
|
}
|
|
50294
50819
|
} catch (e) {
|
|
@@ -50321,7 +50846,7 @@ function show_node_popover(gobj) {
|
|
|
50321
50846
|
let origLW = currentLW;
|
|
50322
50847
|
let rect = get_node_viewport_rect(gobj, node_id);
|
|
50323
50848
|
if (!rect) return;
|
|
50324
|
-
const popover = create_popover_base(rect.right +
|
|
50849
|
+
const popover = create_popover_base(rect.right + floating_popover_dx(), rect.top + floating_icon_dy(), "g6-node-popover", "#d9d9d9", 180);
|
|
50325
50850
|
let node_graph_type = nodeData.data && nodeData.data.desc ? nodeData.data.desc.node_treedb_type : null;
|
|
50326
50851
|
function preview_node() {
|
|
50327
50852
|
let fill = fillInput.value;
|
|
@@ -50952,7 +51477,7 @@ function show_create_popover(gobj) {
|
|
|
50952
51477
|
topicLabel.textContent = (0, i18next.t)("topic") + ":";
|
|
50953
51478
|
popover.appendChild(topicLabel);
|
|
50954
51479
|
let topicSelect = document.createElement("select");
|
|
50955
|
-
topicSelect.style.cssText = "width:100%;padding:6px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;margin-bottom:8px;";
|
|
51480
|
+
topicSelect.style.cssText = "width:100%;padding:6px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;margin-bottom:8px;" + touch_control_css();
|
|
50956
51481
|
for (let i = 0; i < topics.length; i++) {
|
|
50957
51482
|
let opt = document.createElement("option");
|
|
50958
51483
|
opt.value = topics[i].topic_name;
|
|
@@ -50985,7 +51510,7 @@ function show_create_popover(gobj) {
|
|
|
50985
51510
|
let idInput = document.createElement("input");
|
|
50986
51511
|
idInput.type = "text";
|
|
50987
51512
|
idInput.placeholder = (0, i18next.t)("node id");
|
|
50988
|
-
idInput.style.cssText = "width:100%;padding:6px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;margin-bottom:10px;box-sizing:border-box;";
|
|
51513
|
+
idInput.style.cssText = "width:100%;padding:6px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;margin-bottom:10px;box-sizing:border-box;" + touch_control_css();
|
|
50989
51514
|
popover.appendChild(idInput);
|
|
50990
51515
|
let errorEl = document.createElement("div");
|
|
50991
51516
|
errorEl.style.cssText = "color:#ff4d4f;font-size:12px;margin-bottom:8px;display:none;";
|
|
@@ -51492,8 +52017,7 @@ function ac_load_data(gobj, event, kw, src) {
|
|
|
51492
52017
|
if (auto_laid) graph_fit_readable(gobj).catch((e) => {
|
|
51493
52018
|
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot fit the graph: ${e}`);
|
|
51494
52019
|
});
|
|
51495
|
-
|
|
51496
|
-
else graph_remove_plugin(gobj, "history");
|
|
52020
|
+
sync_history_plugin(gobj);
|
|
51497
52021
|
if (priv._pending_focus_topic !== null) {
|
|
51498
52022
|
let ft = priv._pending_focus_topic;
|
|
51499
52023
|
priv._pending_focus_topic = null;
|
|
@@ -51675,6 +52199,11 @@ function ac_resize(gobj, event, kw, src) {
|
|
|
51675
52199
|
if (h < 0) h = 80;
|
|
51676
52200
|
graph_resize(gobj, rect.width, h);
|
|
51677
52201
|
}
|
|
52202
|
+
let can_collapse = toolbars_can_collapse(gobj);
|
|
52203
|
+
if (can_collapse !== priv._toolbars_could_collapse) {
|
|
52204
|
+
priv._toolbars_could_collapse = can_collapse;
|
|
52205
|
+
update_toolbar(gobj);
|
|
52206
|
+
}
|
|
51678
52207
|
return 0;
|
|
51679
52208
|
}
|
|
51680
52209
|
/************************************************************
|
|
@@ -51713,6 +52242,19 @@ function ac_zoom_reset(gobj, event, kw, src) {
|
|
|
51713
52242
|
gobj.priv.graph.zoomTo(1);
|
|
51714
52243
|
return 0;
|
|
51715
52244
|
}
|
|
52245
|
+
/************************************************************
|
|
52246
|
+
* Fold / unfold the floating toolbars.
|
|
52247
|
+
*
|
|
52248
|
+
* One flag for BOTH: they are one wall over the canvas, and
|
|
52249
|
+
* the button that unfolds them has to be the same button
|
|
52250
|
+
* whichever edge the user reaches for.
|
|
52251
|
+
************************************************************/
|
|
52252
|
+
function ac_toggle_toolbars(gobj, event, kw, src) {
|
|
52253
|
+
let priv = gobj.priv;
|
|
52254
|
+
priv.toolbar_collapsed = !toolbars_collapsed(gobj);
|
|
52255
|
+
update_toolbar(gobj);
|
|
52256
|
+
return 0;
|
|
52257
|
+
}
|
|
51716
52258
|
function ac_auto_fit(gobj, event, kw, src) {
|
|
51717
52259
|
graph_fitview(gobj);
|
|
51718
52260
|
return 0;
|
|
@@ -51777,6 +52319,7 @@ function ac_set_operation_mode$1(gobj, event, kw, src) {
|
|
|
51777
52319
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "operation_mode", kw.operation_mode);
|
|
51778
52320
|
configure_behaviour(gobj);
|
|
51779
52321
|
update_toolbar(gobj);
|
|
52322
|
+
sync_history_plugin(gobj);
|
|
51780
52323
|
return 0;
|
|
51781
52324
|
}
|
|
51782
52325
|
/************************************************************
|
|
@@ -52097,6 +52640,11 @@ function create_gclass$4(gclass_name) {
|
|
|
52097
52640
|
ac_zoom_reset,
|
|
52098
52641
|
null
|
|
52099
52642
|
],
|
|
52643
|
+
[
|
|
52644
|
+
"EV_TOGGLE_TOOLBARS",
|
|
52645
|
+
ac_toggle_toolbars,
|
|
52646
|
+
null
|
|
52647
|
+
],
|
|
52100
52648
|
[
|
|
52101
52649
|
"EV_AUTO_FIT",
|
|
52102
52650
|
ac_auto_fit,
|
|
@@ -52200,6 +52748,7 @@ function create_gclass$4(gclass_name) {
|
|
|
52200
52748
|
["EV_ZOOM_IN", 0],
|
|
52201
52749
|
["EV_ZOOM_OUT", 0],
|
|
52202
52750
|
["EV_ZOOM_RESET", 0],
|
|
52751
|
+
["EV_TOGGLE_TOOLBARS", 0],
|
|
52203
52752
|
["EV_AUTO_FIT", 0],
|
|
52204
52753
|
["EV_ZOOM_SELECTION", 0],
|
|
52205
52754
|
["EV_FOCUS_TOPIC", 0],
|