@hpcc-js/common 3.6.5 → 3.7.0

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.
Files changed (54) hide show
  1. package/LICENSE +43 -43
  2. package/README.md +59 -59
  3. package/dist/index.js +4 -4
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.umd.cjs +1 -1
  6. package/dist/index.umd.cjs.map +1 -1
  7. package/package.json +2 -2
  8. package/src/CanvasWidget.ts +31 -31
  9. package/src/Class.ts +72 -72
  10. package/src/Database.ts +860 -860
  11. package/src/Entity.ts +235 -235
  12. package/src/EntityCard.ts +66 -66
  13. package/src/EntityPin.ts +103 -103
  14. package/src/EntityRect.css +15 -15
  15. package/src/EntityRect.ts +254 -254
  16. package/src/EntityVertex.ts +86 -86
  17. package/src/FAChar.css +2 -2
  18. package/src/FAChar.ts +89 -89
  19. package/src/HTMLWidget.ts +191 -191
  20. package/src/IList.ts +4 -4
  21. package/src/IMenu.ts +5 -5
  22. package/src/Icon.css +9 -9
  23. package/src/Icon.ts +176 -176
  24. package/src/Image.ts +104 -104
  25. package/src/List.css +13 -13
  26. package/src/List.ts +102 -102
  27. package/src/Menu.css +23 -23
  28. package/src/Menu.ts +139 -139
  29. package/src/Palette.ts +341 -341
  30. package/src/Platform.ts +125 -125
  31. package/src/ProgressBar.ts +115 -115
  32. package/src/PropertyExt.ts +770 -770
  33. package/src/ResizeSurface.css +39 -39
  34. package/src/ResizeSurface.ts +225 -225
  35. package/src/SVGWidget.ts +583 -583
  36. package/src/SVGZoomWidget.css +12 -12
  37. package/src/SVGZoomWidget.ts +427 -427
  38. package/src/Shape.css +3 -3
  39. package/src/Shape.ts +186 -186
  40. package/src/Surface.css +35 -35
  41. package/src/Surface.ts +364 -364
  42. package/src/Text.css +4 -4
  43. package/src/Text.ts +131 -131
  44. package/src/TextBox.css +4 -4
  45. package/src/TextBox.ts +183 -183
  46. package/src/TitleBar.css +114 -114
  47. package/src/TitleBar.ts +407 -407
  48. package/src/Transition.ts +45 -45
  49. package/src/Utility.ts +843 -839
  50. package/src/Widget.css +8 -8
  51. package/src/Widget.ts +731 -731
  52. package/src/WidgetArray.ts +15 -15
  53. package/src/__package__.ts +3 -3
  54. package/src/index.ts +55 -55
@@ -1,427 +1,427 @@
1
- import { event as d3Event, mouse as d3Mouse } from "d3-selection";
2
- import { zoom as d3Zoom, zoomIdentity as d3ZoomIdentity } from "d3-zoom";
3
- import { SVGWidget } from "./SVGWidget.ts";
4
- import { safeRaise } from "./Utility.ts";
5
- import { Button, IconBar, Spacer, ToggleButton } from "./TitleBar.ts";
6
-
7
- import "../src/SVGZoomWidget.css";
8
-
9
- export type MouseMode = "zoom" | "marqueeSelection";
10
-
11
- export class SVGZoomWidget extends SVGWidget {
12
-
13
- protected _renderElement;
14
-
15
- private _currZoom;
16
- protected _zoomScale = 1;
17
- protected _zoomTranslate = [0, 0];
18
- protected _zoomRoot;
19
- protected _zoomGrab;
20
- protected _zoomG;
21
- private _prevZoomable;
22
-
23
- protected _marqueeSelectionRoot;
24
- protected _marqueeSelection;
25
-
26
- protected _autoSelectionMode = false;
27
-
28
- protected _toggleMarqueeSelection = new ToggleButton().faChar("fa-square-o").tooltip("Marquee Selection")
29
- .on("click", () => {
30
- if (this._toggleMarqueeSelection.selected()) {
31
- this.mouseMode("marqueeSelection");
32
- }
33
- this.updateIconBar();
34
- })
35
- ;
36
-
37
- protected _toggleZoom = new ToggleButton().faChar("fa-mouse-pointer").tooltip("Zoom")
38
- .on("click", () => {
39
- if (this._toggleZoom.selected()) {
40
- this.mouseMode("zoom");
41
- }
42
- this.updateIconBar();
43
- })
44
- ;
45
-
46
- _iconBar = new IconBar()
47
- .buttons([
48
- this._toggleMarqueeSelection,
49
- this._toggleZoom,
50
- new Spacer().vline(false),
51
- new Button().faChar("fa-arrows-alt").tooltip("Zoom to fit")
52
- .on("click", () => {
53
- this.zoomToFit();
54
- }),
55
- new Spacer().vline(false),
56
- new Button().faChar("fa-plus").tooltip("Zoom in")
57
- .on("click", () => {
58
- this.zoomPlus();
59
- }),
60
- new Button().faChar("fa-minus").tooltip("Zoom out")
61
- .on("click", () => {
62
- this.zoomMinus();
63
- })
64
- ])
65
- ;
66
-
67
- constructor() {
68
- super();
69
-
70
- this._currZoom = d3Zoom()
71
- .scaleExtent([0.05, 20])
72
- .on("zoom end", (evt) => {
73
- this.onZoomed();
74
- })
75
- ;
76
- }
77
-
78
- getScreenBBox(target: any) {
79
- let targetel = target;
80
-
81
- while (targetel.getScreenCTM == null && targetel.parentNode == null) {
82
- targetel = targetel.parentNode;
83
- }
84
-
85
- const bbox: any = {};
86
- const matrix = targetel.getScreenCTM();
87
- const tbbox = targetel.getBBox();
88
- const width = tbbox.width;
89
- const height = tbbox.height;
90
- const x = tbbox.x;
91
- const y = tbbox.y;
92
- const point = this._placeholderElement.node().createSVGPoint();
93
- point.x = x;
94
- point.y = y;
95
-
96
- bbox.nw = point.matrixTransform(matrix);
97
- point.x += width;
98
- bbox.ne = point.matrixTransform(matrix);
99
- point.y += height;
100
- bbox.se = point.matrixTransform(matrix);
101
- point.x -= width;
102
- bbox.sw = point.matrixTransform(matrix);
103
- point.y -= height / 2;
104
- bbox.w = point.matrixTransform(matrix);
105
- point.x += width;
106
- bbox.e = point.matrixTransform(matrix);
107
- point.x -= width / 2;
108
- point.y -= height / 2;
109
- bbox.n = point.matrixTransform(matrix);
110
- point.y += height;
111
- bbox.s = point.matrixTransform(matrix);
112
-
113
- return {
114
- x: bbox.nw.x,
115
- y: bbox.nw.y,
116
- width: bbox.se.x - bbox.nw.x,
117
- height: bbox.se.y - bbox.nw.y
118
- };
119
- }
120
-
121
- zoomScale(): number {
122
- return this._zoomScale;
123
- }
124
-
125
- zoomTranslate(): number[] {
126
- return this._zoomTranslate;
127
- }
128
-
129
- zoomExtent(range): void {
130
- this._currZoom.scaleExtent(range);
131
- }
132
-
133
- zoomTo(translate?, scale?, transitionDuration = 250) {
134
- translate = translate || this._zoomTranslate;
135
- scale = scale || this._zoomScale;
136
- transitionDuration = transitionDuration === undefined ? this.zoomDuration() : transitionDuration;
137
-
138
- this._zoomRoot.transition().duration(transitionDuration)
139
- .call(this._currZoom.transform, d3ZoomIdentity.translate(translate[0], translate[1]).scale(scale))
140
- ;
141
- }
142
-
143
- zoomPlus() {
144
- this._zoomRoot.transition()
145
- .call(this._currZoom.scaleBy, 1.33)
146
- ;
147
- }
148
-
149
- zoomMinus() {
150
- this._zoomRoot.transition()
151
- .call(this._currZoom.scaleBy, 1 / 1.33)
152
- ;
153
- }
154
-
155
- centerOnBBox(bbox, transitionDuration?) {
156
- if (bbox.width && bbox.height) {
157
- const x = bbox.x + bbox.width / 2;
158
- const y = bbox.y + bbox.height / 2;
159
- const width = this.width();
160
- const height = this.height();
161
-
162
- const scale = this.zoomScale();
163
- const translate = [width / 2 - scale * x, height / 2 - scale * y];
164
- this.zoomTo(translate, scale, transitionDuration);
165
- }
166
- }
167
-
168
- getRenderElementBBox() {
169
- return this._renderElement.node().getBBox();
170
- }
171
-
172
- calcZoomToBBox(bbox, widthOnly: boolean = false, scale?: number) {
173
- const width = this.width();
174
- const height = this.height();
175
- if (bbox.width && bbox.height) {
176
- const x = bbox.x + bbox.width / 2;
177
- const y = bbox.y + bbox.height / 2;
178
- const dx = bbox.width;
179
- const dy = bbox.height;
180
-
181
- let newScale = scale || 1 / (widthOnly ? dx / width : Math.max(dx / width, dy / height));
182
- if (this.zoomToFitLimit_exists() && newScale > this.zoomToFitLimit()) {
183
- newScale = this.zoomToFitLimit();
184
- }
185
- const translate = [width / 2 - newScale * x, height / 2 - newScale * y];
186
- return { translate, newScale };
187
- }
188
- return { translate: [width / 2, height / 2], newScale: scale };
189
- }
190
-
191
- zoomToBBox(bbox, transitionDuration?, widthOnly: boolean = false, scale?: number) {
192
- const { translate, newScale } = this.calcZoomToBBox(bbox, widthOnly, scale);
193
- this.zoomTo(translate, newScale, transitionDuration);
194
- }
195
-
196
- zoomToScale(scale, transitionDuration?) {
197
- if (this._renderElement) {
198
- const bbox = this.getRenderElementBBox();
199
- this.zoomToBBox(bbox, transitionDuration, undefined, scale);
200
- }
201
- }
202
-
203
- zoomToWidth(transitionDuration?) {
204
- if (this._renderElement) {
205
- const bbox = this.getRenderElementBBox();
206
- this.zoomToBBox(bbox, transitionDuration, true);
207
- }
208
- }
209
-
210
- zoomToFit(transitionDuration?) {
211
- if (this._renderElement) {
212
- const bbox = this.getRenderElementBBox();
213
- this.zoomToBBox(bbox, transitionDuration);
214
- }
215
- }
216
-
217
- onZoomed() {
218
- if (d3Event && d3Event.transform && this.mouseMode() === "zoom") {
219
- this.zoomed(d3Event.transform);
220
- }
221
- }
222
-
223
- zoomed(transform) {
224
- this._zoomScale = transform.k;
225
- this._zoomTranslate = [transform.x, transform.y];
226
- this._zoomG.attr("transform", transform);
227
- }
228
-
229
- updateIconBar() {
230
- this._toggleMarqueeSelection.selected(this.mouseMode() === "marqueeSelection").render();
231
- this._toggleZoom.selected(this.mouseMode() === "zoom").render();
232
- }
233
-
234
- mousedownMarqueeSelection() {
235
- const p = d3Mouse(this._marqueeSelectionRoot.node());
236
- this._marqueeSelection = this.element().append("rect")
237
- .attr("class", "marqueeSelection")
238
- .attr("rx", 6)
239
- .attr("ry", 6)
240
- .attr("x", p[0])
241
- .attr("y", p[1])
242
- .attr("width", 0)
243
- .attr("height", 0)
244
- ;
245
- this.startMarqueeSelection();
246
- }
247
-
248
- mousemoveMarqueeSelection() {
249
- if (this._marqueeSelection) {
250
- const p = d3Mouse(this._marqueeSelectionRoot.node());
251
- const d = {
252
- x: parseInt(this._marqueeSelection.attr("x"), 10),
253
- y: parseInt(this._marqueeSelection.attr("y"), 10),
254
- width: parseInt(this._marqueeSelection.attr("width"), 10),
255
- height: parseInt(this._marqueeSelection.attr("height"), 10)
256
- };
257
- const move = {
258
- x: p[0] - d.x,
259
- y: p[1] - d.y
260
- };
261
-
262
- if (move.x < 1 || (move.x * 2 < d.width)) {
263
- d.x = p[0];
264
- d.width -= move.x;
265
- } else {
266
- d.width = move.x;
267
- }
268
-
269
- if (move.y < 1 || (move.y * 2 < d.height)) {
270
- d.y = p[1];
271
- d.height -= move.y;
272
- } else {
273
- d.height = move.y;
274
- }
275
-
276
- this._marqueeSelection
277
- .attr("x", d.x)
278
- .attr("y", d.y)
279
- .attr("width", d.width)
280
- .attr("height", d.height)
281
- ;
282
-
283
- this.updateMarqueeSelection({
284
- x: (d.x - this._zoomTranslate[0]) / this._zoomScale,
285
- y: (d.y - this._zoomTranslate[1]) / this._zoomScale,
286
- width: d.width / this._zoomScale,
287
- height: d.height / this._zoomScale
288
- });
289
- }
290
- }
291
-
292
- mouseupMarqueeSelection() {
293
- if (this._marqueeSelection) {
294
- this._marqueeSelection.remove();
295
- delete this._marqueeSelection;
296
- if (this._autoSelectionMode) {
297
- this._autoSelectionMode = false;
298
- this.mouseMode("zoom");
299
- this.updateIconBar();
300
- }
301
- this.endMarqueeSelection();
302
- }
303
- }
304
-
305
- enter(domNode, _element) {
306
- super.enter(domNode, _element);
307
- _element.style("user-select", "none");
308
-
309
- this._marqueeSelectionRoot = _element.append("rect")
310
- .attr("class", "zoomBackground")
311
- .attr("width", this.width())
312
- .attr("height", this.height())
313
- .style("fill", "transparent")
314
- .style("cursor", "crosshair")
315
- .on("mousedown", () => {
316
- this.mousedownMarqueeSelection();
317
- })
318
- .on("mousemove", () => {
319
- this.mousemoveMarqueeSelection();
320
- })
321
- .on("mouseup mouseout", () => {
322
- this.mouseupMarqueeSelection();
323
- })
324
- ;
325
-
326
- this._zoomRoot = _element.append("g");
327
-
328
- this._zoomGrab = this._zoomRoot.append("rect")
329
- .attr("class", "zoomBackground")
330
- .attr("width", this.width())
331
- .attr("height", this.height())
332
- .style("fill", "transparent")
333
- .on("mousedown", () => {
334
- if (d3Event.shiftKey && this.mouseMode() === "zoom") {
335
- d3Event.stopPropagation();
336
- this.mouseMode("marqueeSelection");
337
- this._autoSelectionMode = true;
338
- this.mousedownMarqueeSelection();
339
- }
340
- })
341
- ;
342
- this._zoomG = this._zoomRoot.append("g");
343
- this._renderElement = this._zoomG.append("g");
344
-
345
- if (this._prevZoomable !== this.zoomable()) {
346
- if (this.zoomable()) {
347
- this._zoomRoot.call(this._currZoom);
348
- } else {
349
- this._zoomRoot.on(".zoom", null);
350
- }
351
- this._prevZoomable = this.zoomable();
352
- }
353
-
354
- this._iconBar.target(this._zoomRoot.node());
355
- }
356
-
357
- update(domNode, element) {
358
- super.update(domNode, element);
359
-
360
- this._zoomGrab
361
- .attr("width", this.width())
362
- .attr("height", this.height())
363
- ;
364
-
365
- this._marqueeSelectionRoot
366
- .attr("width", this.width())
367
- .attr("height", this.height())
368
- ;
369
-
370
- this._iconBar
371
- .visible(this.zoomable() && this.showToolbar())
372
- .render((w: IconBar) => {
373
- const bbox = w.getBBox();
374
- w.reposition({ x: this.width() - bbox.width - 4, y: -4 });
375
- })
376
- ;
377
- }
378
-
379
- exit(domNode, element) {
380
- this._iconBar.target(null);
381
- super.exit(domNode, element);
382
- }
383
-
384
- // Events
385
- startMarqueeSelection() {
386
- }
387
-
388
- updateMarqueeSelection(rect: { x: number, y: number, width: number, height: number }) {
389
- }
390
-
391
- endMarqueeSelection() {
392
- }
393
- }
394
- SVGZoomWidget.prototype._class += " common_SVGZoomWidget";
395
-
396
- export interface SVGZoomWidget {
397
- showToolbar(): boolean;
398
- showToolbar(_: boolean): this;
399
- zoomable(): boolean;
400
- zoomable(_: boolean): this;
401
- zoomDuration(): number;
402
- zoomDuration(_: number): this;
403
- zoomToFitLimit(): number;
404
- zoomToFitLimit(_: number): this;
405
- zoomToFitLimit_exists(): boolean;
406
- mouseMode(_: MouseMode): this;
407
- mouseMode(): MouseMode;
408
- }
409
- SVGZoomWidget.prototype.publish("showToolbar", true, "boolean", "Show Toolbar");
410
- SVGZoomWidget.prototype.publish("zoomable", true, "boolean", "Enable/Disable Zooming");
411
- SVGZoomWidget.prototype.publish("zoomDuration", 250, "number", "Transition Duration");
412
- SVGZoomWidget.prototype.publish("zoomToFitLimit", undefined, "number", "Zoom to fit limit", undefined, { optional: true });
413
- SVGZoomWidget.prototype.publish("mouseMode", "zoom", "set", "Mouse Mode (zoom | marqueeSelection)", ["zoom", "marqueeSelection"]);
414
-
415
- const _origMouseMode = SVGZoomWidget.prototype.mouseMode;
416
- SVGZoomWidget.prototype.mouseMode = function (_?, transitionDuration?) {
417
- const retVal = _origMouseMode.apply(this, arguments);
418
- if (arguments.length) {
419
- if (_ === "zoom") {
420
- safeRaise(this._zoomRoot.node());
421
- } else {
422
- safeRaise(this._marqueeSelectionRoot.node());
423
- }
424
- this.updateIconBar();
425
- }
426
- return retVal;
427
- };
1
+ import { event as d3Event, mouse as d3Mouse } from "d3-selection";
2
+ import { zoom as d3Zoom, zoomIdentity as d3ZoomIdentity } from "d3-zoom";
3
+ import { SVGWidget } from "./SVGWidget.ts";
4
+ import { safeRaise } from "./Utility.ts";
5
+ import { Button, IconBar, Spacer, ToggleButton } from "./TitleBar.ts";
6
+
7
+ import "../src/SVGZoomWidget.css";
8
+
9
+ export type MouseMode = "zoom" | "marqueeSelection";
10
+
11
+ export class SVGZoomWidget extends SVGWidget {
12
+
13
+ protected _renderElement;
14
+
15
+ private _currZoom;
16
+ protected _zoomScale = 1;
17
+ protected _zoomTranslate = [0, 0];
18
+ protected _zoomRoot;
19
+ protected _zoomGrab;
20
+ protected _zoomG;
21
+ private _prevZoomable;
22
+
23
+ protected _marqueeSelectionRoot;
24
+ protected _marqueeSelection;
25
+
26
+ protected _autoSelectionMode = false;
27
+
28
+ protected _toggleMarqueeSelection = new ToggleButton().faChar("fa-square-o").tooltip("Marquee Selection")
29
+ .on("click", () => {
30
+ if (this._toggleMarqueeSelection.selected()) {
31
+ this.mouseMode("marqueeSelection");
32
+ }
33
+ this.updateIconBar();
34
+ })
35
+ ;
36
+
37
+ protected _toggleZoom = new ToggleButton().faChar("fa-mouse-pointer").tooltip("Zoom")
38
+ .on("click", () => {
39
+ if (this._toggleZoom.selected()) {
40
+ this.mouseMode("zoom");
41
+ }
42
+ this.updateIconBar();
43
+ })
44
+ ;
45
+
46
+ _iconBar = new IconBar()
47
+ .buttons([
48
+ this._toggleMarqueeSelection,
49
+ this._toggleZoom,
50
+ new Spacer().vline(false),
51
+ new Button().faChar("fa-arrows-alt").tooltip("Zoom to fit")
52
+ .on("click", () => {
53
+ this.zoomToFit();
54
+ }),
55
+ new Spacer().vline(false),
56
+ new Button().faChar("fa-plus").tooltip("Zoom in")
57
+ .on("click", () => {
58
+ this.zoomPlus();
59
+ }),
60
+ new Button().faChar("fa-minus").tooltip("Zoom out")
61
+ .on("click", () => {
62
+ this.zoomMinus();
63
+ })
64
+ ])
65
+ ;
66
+
67
+ constructor() {
68
+ super();
69
+
70
+ this._currZoom = d3Zoom()
71
+ .scaleExtent([0.05, 20])
72
+ .on("zoom end", (evt) => {
73
+ this.onZoomed();
74
+ })
75
+ ;
76
+ }
77
+
78
+ getScreenBBox(target: any) {
79
+ let targetel = target;
80
+
81
+ while (targetel.getScreenCTM == null && targetel.parentNode == null) {
82
+ targetel = targetel.parentNode;
83
+ }
84
+
85
+ const bbox: any = {};
86
+ const matrix = targetel.getScreenCTM();
87
+ const tbbox = targetel.getBBox();
88
+ const width = tbbox.width;
89
+ const height = tbbox.height;
90
+ const x = tbbox.x;
91
+ const y = tbbox.y;
92
+ const point = this._placeholderElement.node().createSVGPoint();
93
+ point.x = x;
94
+ point.y = y;
95
+
96
+ bbox.nw = point.matrixTransform(matrix);
97
+ point.x += width;
98
+ bbox.ne = point.matrixTransform(matrix);
99
+ point.y += height;
100
+ bbox.se = point.matrixTransform(matrix);
101
+ point.x -= width;
102
+ bbox.sw = point.matrixTransform(matrix);
103
+ point.y -= height / 2;
104
+ bbox.w = point.matrixTransform(matrix);
105
+ point.x += width;
106
+ bbox.e = point.matrixTransform(matrix);
107
+ point.x -= width / 2;
108
+ point.y -= height / 2;
109
+ bbox.n = point.matrixTransform(matrix);
110
+ point.y += height;
111
+ bbox.s = point.matrixTransform(matrix);
112
+
113
+ return {
114
+ x: bbox.nw.x,
115
+ y: bbox.nw.y,
116
+ width: bbox.se.x - bbox.nw.x,
117
+ height: bbox.se.y - bbox.nw.y
118
+ };
119
+ }
120
+
121
+ zoomScale(): number {
122
+ return this._zoomScale;
123
+ }
124
+
125
+ zoomTranslate(): number[] {
126
+ return this._zoomTranslate;
127
+ }
128
+
129
+ zoomExtent(range): void {
130
+ this._currZoom.scaleExtent(range);
131
+ }
132
+
133
+ zoomTo(translate?, scale?, transitionDuration = 250) {
134
+ translate = translate || this._zoomTranslate;
135
+ scale = scale || this._zoomScale;
136
+ transitionDuration = transitionDuration === undefined ? this.zoomDuration() : transitionDuration;
137
+
138
+ this._zoomRoot.transition().duration(transitionDuration)
139
+ .call(this._currZoom.transform, d3ZoomIdentity.translate(translate[0], translate[1]).scale(scale))
140
+ ;
141
+ }
142
+
143
+ zoomPlus() {
144
+ this._zoomRoot.transition()
145
+ .call(this._currZoom.scaleBy, 1.33)
146
+ ;
147
+ }
148
+
149
+ zoomMinus() {
150
+ this._zoomRoot.transition()
151
+ .call(this._currZoom.scaleBy, 1 / 1.33)
152
+ ;
153
+ }
154
+
155
+ centerOnBBox(bbox, transitionDuration?) {
156
+ if (bbox.width && bbox.height) {
157
+ const x = bbox.x + bbox.width / 2;
158
+ const y = bbox.y + bbox.height / 2;
159
+ const width = this.width();
160
+ const height = this.height();
161
+
162
+ const scale = this.zoomScale();
163
+ const translate = [width / 2 - scale * x, height / 2 - scale * y];
164
+ this.zoomTo(translate, scale, transitionDuration);
165
+ }
166
+ }
167
+
168
+ getRenderElementBBox() {
169
+ return this._renderElement.node().getBBox();
170
+ }
171
+
172
+ calcZoomToBBox(bbox, widthOnly: boolean = false, scale?: number) {
173
+ const width = this.width();
174
+ const height = this.height();
175
+ if (bbox.width && bbox.height) {
176
+ const x = bbox.x + bbox.width / 2;
177
+ const y = bbox.y + bbox.height / 2;
178
+ const dx = bbox.width;
179
+ const dy = bbox.height;
180
+
181
+ let newScale = scale || 1 / (widthOnly ? dx / width : Math.max(dx / width, dy / height));
182
+ if (this.zoomToFitLimit_exists() && newScale > this.zoomToFitLimit()) {
183
+ newScale = this.zoomToFitLimit();
184
+ }
185
+ const translate = [width / 2 - newScale * x, height / 2 - newScale * y];
186
+ return { translate, newScale };
187
+ }
188
+ return { translate: [width / 2, height / 2], newScale: scale };
189
+ }
190
+
191
+ zoomToBBox(bbox, transitionDuration?, widthOnly: boolean = false, scale?: number) {
192
+ const { translate, newScale } = this.calcZoomToBBox(bbox, widthOnly, scale);
193
+ this.zoomTo(translate, newScale, transitionDuration);
194
+ }
195
+
196
+ zoomToScale(scale, transitionDuration?) {
197
+ if (this._renderElement) {
198
+ const bbox = this.getRenderElementBBox();
199
+ this.zoomToBBox(bbox, transitionDuration, undefined, scale);
200
+ }
201
+ }
202
+
203
+ zoomToWidth(transitionDuration?) {
204
+ if (this._renderElement) {
205
+ const bbox = this.getRenderElementBBox();
206
+ this.zoomToBBox(bbox, transitionDuration, true);
207
+ }
208
+ }
209
+
210
+ zoomToFit(transitionDuration?) {
211
+ if (this._renderElement) {
212
+ const bbox = this.getRenderElementBBox();
213
+ this.zoomToBBox(bbox, transitionDuration);
214
+ }
215
+ }
216
+
217
+ onZoomed() {
218
+ if (d3Event && d3Event.transform && this.mouseMode() === "zoom") {
219
+ this.zoomed(d3Event.transform);
220
+ }
221
+ }
222
+
223
+ zoomed(transform) {
224
+ this._zoomScale = transform.k;
225
+ this._zoomTranslate = [transform.x, transform.y];
226
+ this._zoomG.attr("transform", transform);
227
+ }
228
+
229
+ updateIconBar() {
230
+ this._toggleMarqueeSelection.selected(this.mouseMode() === "marqueeSelection").render();
231
+ this._toggleZoom.selected(this.mouseMode() === "zoom").render();
232
+ }
233
+
234
+ mousedownMarqueeSelection() {
235
+ const p = d3Mouse(this._marqueeSelectionRoot.node());
236
+ this._marqueeSelection = this.element().append("rect")
237
+ .attr("class", "marqueeSelection")
238
+ .attr("rx", 6)
239
+ .attr("ry", 6)
240
+ .attr("x", p[0])
241
+ .attr("y", p[1])
242
+ .attr("width", 0)
243
+ .attr("height", 0)
244
+ ;
245
+ this.startMarqueeSelection();
246
+ }
247
+
248
+ mousemoveMarqueeSelection() {
249
+ if (this._marqueeSelection) {
250
+ const p = d3Mouse(this._marqueeSelectionRoot.node());
251
+ const d = {
252
+ x: parseInt(this._marqueeSelection.attr("x"), 10),
253
+ y: parseInt(this._marqueeSelection.attr("y"), 10),
254
+ width: parseInt(this._marqueeSelection.attr("width"), 10),
255
+ height: parseInt(this._marqueeSelection.attr("height"), 10)
256
+ };
257
+ const move = {
258
+ x: p[0] - d.x,
259
+ y: p[1] - d.y
260
+ };
261
+
262
+ if (move.x < 1 || (move.x * 2 < d.width)) {
263
+ d.x = p[0];
264
+ d.width -= move.x;
265
+ } else {
266
+ d.width = move.x;
267
+ }
268
+
269
+ if (move.y < 1 || (move.y * 2 < d.height)) {
270
+ d.y = p[1];
271
+ d.height -= move.y;
272
+ } else {
273
+ d.height = move.y;
274
+ }
275
+
276
+ this._marqueeSelection
277
+ .attr("x", d.x)
278
+ .attr("y", d.y)
279
+ .attr("width", d.width)
280
+ .attr("height", d.height)
281
+ ;
282
+
283
+ this.updateMarqueeSelection({
284
+ x: (d.x - this._zoomTranslate[0]) / this._zoomScale,
285
+ y: (d.y - this._zoomTranslate[1]) / this._zoomScale,
286
+ width: d.width / this._zoomScale,
287
+ height: d.height / this._zoomScale
288
+ });
289
+ }
290
+ }
291
+
292
+ mouseupMarqueeSelection() {
293
+ if (this._marqueeSelection) {
294
+ this._marqueeSelection.remove();
295
+ delete this._marqueeSelection;
296
+ if (this._autoSelectionMode) {
297
+ this._autoSelectionMode = false;
298
+ this.mouseMode("zoom");
299
+ this.updateIconBar();
300
+ }
301
+ this.endMarqueeSelection();
302
+ }
303
+ }
304
+
305
+ enter(domNode, _element) {
306
+ super.enter(domNode, _element);
307
+ _element.style("user-select", "none");
308
+
309
+ this._marqueeSelectionRoot = _element.append("rect")
310
+ .attr("class", "zoomBackground")
311
+ .attr("width", this.width())
312
+ .attr("height", this.height())
313
+ .style("fill", "transparent")
314
+ .style("cursor", "crosshair")
315
+ .on("mousedown", () => {
316
+ this.mousedownMarqueeSelection();
317
+ })
318
+ .on("mousemove", () => {
319
+ this.mousemoveMarqueeSelection();
320
+ })
321
+ .on("mouseup mouseout", () => {
322
+ this.mouseupMarqueeSelection();
323
+ })
324
+ ;
325
+
326
+ this._zoomRoot = _element.append("g");
327
+
328
+ this._zoomGrab = this._zoomRoot.append("rect")
329
+ .attr("class", "zoomBackground")
330
+ .attr("width", this.width())
331
+ .attr("height", this.height())
332
+ .style("fill", "transparent")
333
+ .on("mousedown", () => {
334
+ if (d3Event.shiftKey && this.mouseMode() === "zoom") {
335
+ d3Event.stopPropagation();
336
+ this.mouseMode("marqueeSelection");
337
+ this._autoSelectionMode = true;
338
+ this.mousedownMarqueeSelection();
339
+ }
340
+ })
341
+ ;
342
+ this._zoomG = this._zoomRoot.append("g");
343
+ this._renderElement = this._zoomG.append("g");
344
+
345
+ if (this._prevZoomable !== this.zoomable()) {
346
+ if (this.zoomable()) {
347
+ this._zoomRoot.call(this._currZoom);
348
+ } else {
349
+ this._zoomRoot.on(".zoom", null);
350
+ }
351
+ this._prevZoomable = this.zoomable();
352
+ }
353
+
354
+ this._iconBar.target(this._zoomRoot.node());
355
+ }
356
+
357
+ update(domNode, element) {
358
+ super.update(domNode, element);
359
+
360
+ this._zoomGrab
361
+ .attr("width", this.width())
362
+ .attr("height", this.height())
363
+ ;
364
+
365
+ this._marqueeSelectionRoot
366
+ .attr("width", this.width())
367
+ .attr("height", this.height())
368
+ ;
369
+
370
+ this._iconBar
371
+ .visible(this.zoomable() && this.showToolbar())
372
+ .render((w: IconBar) => {
373
+ const bbox = w.getBBox();
374
+ w.reposition({ x: this.width() - bbox.width - 4, y: -4 });
375
+ })
376
+ ;
377
+ }
378
+
379
+ exit(domNode, element) {
380
+ this._iconBar.target(null);
381
+ super.exit(domNode, element);
382
+ }
383
+
384
+ // Events
385
+ startMarqueeSelection() {
386
+ }
387
+
388
+ updateMarqueeSelection(rect: { x: number, y: number, width: number, height: number }) {
389
+ }
390
+
391
+ endMarqueeSelection() {
392
+ }
393
+ }
394
+ SVGZoomWidget.prototype._class += " common_SVGZoomWidget";
395
+
396
+ export interface SVGZoomWidget {
397
+ showToolbar(): boolean;
398
+ showToolbar(_: boolean): this;
399
+ zoomable(): boolean;
400
+ zoomable(_: boolean): this;
401
+ zoomDuration(): number;
402
+ zoomDuration(_: number): this;
403
+ zoomToFitLimit(): number;
404
+ zoomToFitLimit(_: number): this;
405
+ zoomToFitLimit_exists(): boolean;
406
+ mouseMode(_: MouseMode): this;
407
+ mouseMode(): MouseMode;
408
+ }
409
+ SVGZoomWidget.prototype.publish("showToolbar", true, "boolean", "Show Toolbar");
410
+ SVGZoomWidget.prototype.publish("zoomable", true, "boolean", "Enable/Disable Zooming");
411
+ SVGZoomWidget.prototype.publish("zoomDuration", 250, "number", "Transition Duration");
412
+ SVGZoomWidget.prototype.publish("zoomToFitLimit", undefined, "number", "Zoom to fit limit", undefined, { optional: true });
413
+ SVGZoomWidget.prototype.publish("mouseMode", "zoom", "set", "Mouse Mode (zoom | marqueeSelection)", ["zoom", "marqueeSelection"]);
414
+
415
+ const _origMouseMode = SVGZoomWidget.prototype.mouseMode;
416
+ SVGZoomWidget.prototype.mouseMode = function (_?, transitionDuration?) {
417
+ const retVal = _origMouseMode.apply(this, arguments);
418
+ if (arguments.length) {
419
+ if (_ === "zoom") {
420
+ safeRaise(this._zoomRoot.node());
421
+ } else {
422
+ safeRaise(this._marqueeSelectionRoot.node());
423
+ }
424
+ this.updateIconBar();
425
+ }
426
+ return retVal;
427
+ };