1 | /*
|
2 | * Copyright (C) 1998-2021 by Northwoods Software Corporation. All Rights Reserved.
|
3 | */
|
4 | /*
|
5 | * This is an extension and not part of the main GoJS library.
|
6 | * Note that the API for this class may change with any version, even point releases.
|
7 | * If you intend to use an extension in production, you should copy the code to your own source directory.
|
8 | * Extensions can be found in the GoJS kit under the extensions or extensionsTS folders.
|
9 | * See the Extensions intro page (https://gojs.net/latest/intro/extensions.html) for more information.
|
10 | */
|
11 | import * as go from '../release/go-module.js';
|
12 | /**
|
13 | * A class for simulating mouse and keyboard input.
|
14 | *
|
15 | * As a special hack, this supports limited simulation of drag-and-drop between Diagrams,
|
16 | * by setting both the `sourceDiagram` and `targetDiagram` properties
|
17 | * on the `eventprops` argument of the mouseDown/mouseMove/mouseUp methods.
|
18 | * Although {@link InputEvent#targetDiagram} is a real property,
|
19 | * the `sourceDiagram` property is only used by these Robot methods.
|
20 | *
|
21 | * If you want to experiment with this extension, try the <a href="../../extensionsJSM/Robot.html">Simulating Input</a> sample.
|
22 | * @category Extension
|
23 | */
|
24 | export class Robot {
|
25 | /**
|
26 | * Construct a robot for a given {@link Diagram}. If none is provided, a new Diagram will be created.
|
27 | */
|
28 | constructor(dia) {
|
29 | if (dia instanceof go.Diagram) {
|
30 | this._diagram = dia;
|
31 | }
|
32 | else {
|
33 | this._diagram = new go.Diagram();
|
34 | }
|
35 | }
|
36 | /**
|
37 | * Gets or sets the {@link Diagram} associated with this Robot.
|
38 | */
|
39 | get diagram() { return this._diagram; }
|
40 | set diagram(val) {
|
41 | if (!(val instanceof go.Diagram))
|
42 | throw new Error('Robot.diagram must be a Diagram, not: ' + val);
|
43 | this._diagram = val;
|
44 | }
|
45 | /**
|
46 | * @hidden @internal
|
47 | * Transfer property settings from a JavaScript Object to an {@link InputEvent}.
|
48 | */
|
49 | initializeEvent(e, props) {
|
50 | if (!props)
|
51 | return;
|
52 | for (const p in props) {
|
53 | if (p !== 'sourceDiagram')
|
54 | e[p] = props[p];
|
55 | }
|
56 | }
|
57 | /**
|
58 | * Simulate a mouse down event.
|
59 | * @param {number} x the X-coordinate of the mouse point in document coordinates.
|
60 | * @param {number} y the Y-coordinate of the mouse point in document coordinates.
|
61 | * @param {number=} time the timestamp of the simulated event, in milliseconds; default zero
|
62 | * @param {Object=} eventprops an optional argument providing properties for the InputEvent.
|
63 | */
|
64 | mouseDown(x, y, time, eventprops) {
|
65 | if (typeof x !== 'number' || typeof y !== 'number')
|
66 | throw new Error('Robot.mouseDown first two args must be X,Y numbers');
|
67 | if (time === undefined)
|
68 | time = 0;
|
69 | let diagram = this._diagram;
|
70 | if (eventprops && eventprops.sourceDiagram)
|
71 | diagram = eventprops.sourceDiagram;
|
72 | if (!diagram.isEnabled)
|
73 | return;
|
74 | const n = new go.InputEvent();
|
75 | n.diagram = diagram;
|
76 | n.documentPoint = new go.Point(x, y);
|
77 | n.viewPoint = diagram.transformDocToView(n.documentPoint);
|
78 | n.timestamp = time;
|
79 | n.down = true;
|
80 | this.initializeEvent(n, eventprops);
|
81 | diagram.lastInput = n;
|
82 | diagram.firstInput = n.copy();
|
83 | diagram.currentTool.doMouseDown();
|
84 | }
|
85 | /**
|
86 | * Simulate a mouse move event.
|
87 | * @param {number} x the X-coordinate of the mouse point in document coordinates.
|
88 | * @param {number} y the Y-coordinate of the mouse point in document coordinates.
|
89 | * @param {number=} time the timestamp of the simulated event, in milliseconds; default zero
|
90 | * @param {Object=} eventprops an optional argument providing properties for the InputEvent.
|
91 | */
|
92 | mouseMove(x, y, time, eventprops) {
|
93 | if (typeof x !== 'number' || typeof y !== 'number')
|
94 | throw new Error('Robot.mouseMove first two args must be X,Y numbers');
|
95 | if (time === undefined)
|
96 | time = 0;
|
97 | let diagram = this._diagram;
|
98 | if (eventprops && eventprops.sourceDiagram)
|
99 | diagram = eventprops.sourceDiagram;
|
100 | if (!diagram.isEnabled)
|
101 | return;
|
102 | const n = new go.InputEvent();
|
103 | n.diagram = diagram;
|
104 | n.documentPoint = new go.Point(x, y);
|
105 | n.viewPoint = diagram.transformDocToView(n.documentPoint);
|
106 | n.timestamp = time;
|
107 | this.initializeEvent(n, eventprops);
|
108 | diagram.lastInput = n;
|
109 | diagram.currentTool.doMouseMove();
|
110 | }
|
111 | /**
|
112 | * Simulate a mouse up event.
|
113 | * @param {number} x the X-coordinate of the mouse point in document coordinates.
|
114 | * @param {number} y the Y-coordinate of the mouse point in document coordinates.
|
115 | * @param {number=} time the timestamp of the simulated event, in milliseconds; default zero
|
116 | * @param {Object=} eventprops an optional argument providing properties for the InputEvent.
|
117 | */
|
118 | mouseUp(x, y, time, eventprops) {
|
119 | if (typeof x !== 'number' || typeof y !== 'number')
|
120 | throw new Error('Robot.mouseUp first two args must be X,Y numbers');
|
121 | if (time === undefined)
|
122 | time = 0;
|
123 | let diagram = this._diagram;
|
124 | if (eventprops && eventprops.sourceDiagram)
|
125 | diagram = eventprops.sourceDiagram;
|
126 | if (!diagram.isEnabled)
|
127 | return;
|
128 | const n = new go.InputEvent();
|
129 | n.diagram = diagram;
|
130 | n.documentPoint = new go.Point(x, y);
|
131 | n.viewPoint = diagram.transformDocToView(n.documentPoint);
|
132 | n.timestamp = time;
|
133 | n.up = true;
|
134 | if (diagram.firstInput.documentPoint.equals(n.documentPoint))
|
135 | n.clickCount = 1; // at least??
|
136 | this.initializeEvent(n, eventprops);
|
137 | diagram.lastInput = n;
|
138 | // if (diagram.simulatedMouseUp(null, (n as any).sourceDiagram, n.documentPoint, n.targetDiagram)) return;
|
139 | diagram.currentTool.doMouseUp();
|
140 | }
|
141 | /**
|
142 | * Simulate a mouse wheel event.
|
143 | * @param {number} delta non-zero turn
|
144 | * @param {number=} time the timestamp of the simulated event, in milliseconds; default zero
|
145 | * @param {Object=} eventprops an optional argument providing properties for the InputEvent.
|
146 | */
|
147 | mouseWheel(delta, time, eventprops) {
|
148 | if (typeof delta !== 'number')
|
149 | throw new Error('Robot.mouseWheel first arg must be DELTA number');
|
150 | if (time === undefined)
|
151 | time = 0;
|
152 | const diagram = this._diagram;
|
153 | if (!diagram.isEnabled)
|
154 | return;
|
155 | const n = diagram.lastInput.copy();
|
156 | n.diagram = diagram;
|
157 | n.delta = delta;
|
158 | n.timestamp = time;
|
159 | this.initializeEvent(n, eventprops);
|
160 | diagram.lastInput = n;
|
161 | diagram.currentTool.doMouseWheel();
|
162 | }
|
163 | /**
|
164 | * Simulate a key down event.
|
165 | * @param {string|number} keyorcode
|
166 | * @param {number=} time the timestamp of the simulated event, in milliseconds; default zero
|
167 | * @param {Object=} eventprops an optional argument providing properties for the InputEvent.
|
168 | */
|
169 | keyDown(keyorcode, time, eventprops) {
|
170 | if (typeof keyorcode !== 'string' && typeof keyorcode !== 'number')
|
171 | throw new Error('Robot.keyDown first arg must be a string or a number');
|
172 | if (time === undefined)
|
173 | time = 0;
|
174 | const diagram = this._diagram;
|
175 | if (!diagram.isEnabled)
|
176 | return;
|
177 | const n = diagram.lastInput.copy();
|
178 | n.diagram = diagram;
|
179 | if (typeof (keyorcode) === 'string') {
|
180 | n.key = keyorcode;
|
181 | }
|
182 | else if (typeof (keyorcode) === 'number') {
|
183 | n.key = String.fromCharCode(keyorcode);
|
184 | }
|
185 | n.timestamp = time;
|
186 | n.down = true;
|
187 | this.initializeEvent(n, eventprops);
|
188 | diagram.lastInput = n;
|
189 | diagram.currentTool.doKeyDown();
|
190 | }
|
191 | /**
|
192 | * Simulate a key up event.
|
193 | * @param {string|number} keyorcode
|
194 | * @param {number=} time the timestamp of the simulated event, in milliseconds; default zero
|
195 | * @param {Object=} eventprops an optional argument providing properties for the InputEvent.
|
196 | */
|
197 | keyUp(keyorcode, time, eventprops) {
|
198 | if (typeof keyorcode !== 'string' && typeof keyorcode !== 'number')
|
199 | throw new Error('Robot.keyUp first arg must be a string or a number');
|
200 | if (time === undefined)
|
201 | time = 0;
|
202 | const diagram = this._diagram;
|
203 | if (!diagram.isEnabled)
|
204 | return;
|
205 | const n = diagram.lastInput.copy();
|
206 | n.diagram = diagram;
|
207 | if (typeof (keyorcode) === 'string') {
|
208 | n.key = keyorcode;
|
209 | }
|
210 | else if (typeof (keyorcode) === 'number') {
|
211 | n.key = String.fromCharCode(keyorcode);
|
212 | }
|
213 | n.timestamp = time;
|
214 | n.up = true;
|
215 | this.initializeEvent(n, eventprops);
|
216 | diagram.lastInput = n;
|
217 | diagram.currentTool.doKeyUp();
|
218 | }
|
219 | }
|