UNPKG

5.38 kBPlain TextView Raw
1/*
2* Copyright (C) 1998-2021 by Northwoods Software Corporation. All Rights Reserved.
3*/
4
5/*
6* This is an extension and not part of the main GoJS library.
7* Note that the API for this class may change with any version, even point releases.
8* If you intend to use an extension in production, you should copy the code to your own source directory.
9* Extensions can be found in the GoJS kit under the extensions or extensionsTS folders.
10* See the Extensions intro page (https://gojs.net/latest/intro/extensions.html) for more information.
11*/
12
13import * as go from '../release/go-module.js';
14
15/**
16 * The NonRealtimeDraggingTool class lets the user drag an image instead of actually moving any selected nodes,
17 * until the mouse-up event.
18 *
19 * If you want to experiment with this extension, try the <a href="../../extensionsJSM/NonRealtimeDragging.html">Non Realtime Dragging</a> sample.
20 * @category Tool Extension
21 */
22export class NonRealtimeDraggingTool extends go.DraggingTool {
23 private _duration: number = 0; // duration of movement animation; <= 0 to disable
24 private _imagePart: go.Part | null = null; // a Part holding a translucent image of what would be dragged
25 private _ghostDraggedParts: go.Map<go.Part, go.DraggingInfo> | null = null; // a Map of the _imagePart and its dragging information
26 private _originalDraggedParts: go.Map<go.Part, go.DraggingInfo> | null = null; // the saved normal value of DraggingTool.draggedParts
27
28 /**
29 * Gets or sets how long the movement animation should be to move the actual parts upon a mouse-up.
30 * The default value is zero -- there is no animation of the movement.
31 */
32 get duration(): number { return this._duration; }
33 set duration(val: number) { this._duration = val; }
34
35 /**
36 * Call the base method, and then make an image of the returned collection,
37 * show it using a Picture, and hold the Picture in a temporary Part, as _imagePart.
38 * @param {Iterable.<Part>} parts A {@link Set} or {@link List} of {@link Part}s.
39 * @return {Map.<Part,DraggingInfo>}
40 */
41 public computeEffectiveCollection(coll: go.Iterable<go.Part>): go.Map<go.Part, go.DraggingInfo> {
42 const map = super.computeEffectiveCollection(coll, this.dragOptions);
43 if (this.isActive && this._imagePart === null) {
44 const bounds = this.diagram.computePartsBounds(map.toKeySet());
45 const offset = this.diagram.lastInput.documentPoint.copy().subtract(bounds.position);
46 const $ = go.GraphObject.make;
47 this._imagePart =
48 $(go.Part,
49 { layerName: 'Tool', opacity: 0.5, locationSpot: new go.Spot(0, 0, offset.x, offset.y) },
50 $(go.Picture,
51 { element: this.diagram.makeImage({ parts: map.toKeySet() }) })
52 );
53 }
54 return map;
55 }
56
57 /**
58 * When activated, replace the {@link #draggedParts} with the ghost dragged parts, which
59 * consists of just one Part, the image, added to the Diagram at the current mouse point.
60 */
61 public doActivate(): void {
62 super.doActivate();
63 if (this._imagePart !== null) {
64 this._imagePart.location = this.diagram.lastInput.documentPoint;
65 this.diagram.add(this._imagePart);
66 this._originalDraggedParts = this.draggedParts;
67 this._ghostDraggedParts = super.computeEffectiveCollection(new go.List<go.Part>().add(this._imagePart), this.dragOptions);
68 this.draggedParts = this._ghostDraggedParts;
69 }
70 }
71
72 /**
73 * When deactivated, make sure any image is removed from the Diagram and all references are cleared out.
74 */
75 public doDeactivate(): void {
76 if (this._imagePart !== null) {
77 this.diagram.remove(this._imagePart);
78 }
79 this._imagePart = null;
80 this._ghostDraggedParts = null;
81 this._originalDraggedParts = null;
82 super.doDeactivate();
83 }
84
85 /**
86 * Do the normal mouse-up behavior, but only after restoring {@link #draggedParts}.
87 */
88 public doMouseUp(): void {
89 const partsmap = this._originalDraggedParts;
90 if (partsmap !== null) {
91 this.draggedParts = partsmap;
92 }
93 super.doMouseUp();
94 if (partsmap !== null && this.duration > 0) {
95 var anim = new go.Animation();
96 anim.duration = this.duration;
97 partsmap.each(function(kvp) {
98 var part = kvp.key;
99 anim.add(part, "location", kvp.value.point, part.location);
100 });
101 anim.start();
102 }
103 }
104
105 /**
106 * If the user changes to "copying" mode by holding down the Control key,
107 * return to the regular behavior and remove the image.
108 */
109 public doKeyDown(): void {
110 if (this._imagePart !== null && this._originalDraggedParts !== null &&
111 (this.diagram.lastInput.control || this.diagram.lastInput.meta) && this.mayCopy()) {
112 this.draggedParts = this._originalDraggedParts;
113 this.diagram.remove(this._imagePart);
114 }
115 super.doKeyDown();
116 }
117
118 /**
119 * If the user changes back to "moving" mode,
120 * show the image again and go back to dragging the ghost dragged parts.
121 */
122 public doKeyUp(): void {
123 if (this._imagePart !== null && this._ghostDraggedParts !== null && this.mayMove()) {
124 this._imagePart.location = this.diagram.lastInput.documentPoint;
125 this.diagram.add(this._imagePart);
126 this.draggedParts = this._ghostDraggedParts;
127 }
128 super.doKeyUp();
129 }
130}