@itwin/core-markup 4.0.0-dev.8 → 4.0.0-dev.80

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 (49) hide show
  1. package/CHANGELOG.md +41 -1
  2. package/lib/cjs/Markup.d.ts +323 -310
  3. package/lib/cjs/Markup.d.ts.map +1 -1
  4. package/lib/cjs/Markup.js +451 -420
  5. package/lib/cjs/Markup.js.map +1 -1
  6. package/lib/cjs/MarkupTool.d.ts +38 -38
  7. package/lib/cjs/MarkupTool.js +88 -88
  8. package/lib/cjs/MarkupTool.js.map +1 -1
  9. package/lib/cjs/RedlineTool.d.ts +145 -145
  10. package/lib/cjs/RedlineTool.d.ts.map +1 -1
  11. package/lib/cjs/RedlineTool.js +498 -512
  12. package/lib/cjs/RedlineTool.js.map +1 -1
  13. package/lib/cjs/SelectTool.d.ts +126 -126
  14. package/lib/cjs/SelectTool.js +741 -741
  15. package/lib/cjs/SelectTool.js.map +1 -1
  16. package/lib/cjs/SvgJsExt.d.ts +85 -85
  17. package/lib/cjs/SvgJsExt.js +185 -185
  18. package/lib/cjs/TextEdit.d.ts +43 -43
  19. package/lib/cjs/TextEdit.js +196 -196
  20. package/lib/cjs/TextEdit.js.map +1 -1
  21. package/lib/cjs/Undo.d.ts +46 -46
  22. package/lib/cjs/Undo.js +168 -168
  23. package/lib/cjs/core-markup.d.ts +18 -18
  24. package/lib/cjs/core-markup.js +38 -34
  25. package/lib/cjs/core-markup.js.map +1 -1
  26. package/lib/esm/Markup.d.ts +323 -310
  27. package/lib/esm/Markup.d.ts.map +1 -1
  28. package/lib/esm/Markup.js +447 -415
  29. package/lib/esm/Markup.js.map +1 -1
  30. package/lib/esm/MarkupTool.d.ts +38 -38
  31. package/lib/esm/MarkupTool.js +85 -84
  32. package/lib/esm/MarkupTool.js.map +1 -1
  33. package/lib/esm/RedlineTool.d.ts +145 -145
  34. package/lib/esm/RedlineTool.d.ts.map +1 -1
  35. package/lib/esm/RedlineTool.js +494 -498
  36. package/lib/esm/RedlineTool.js.map +1 -1
  37. package/lib/esm/SelectTool.d.ts +126 -126
  38. package/lib/esm/SelectTool.js +735 -734
  39. package/lib/esm/SelectTool.js.map +1 -1
  40. package/lib/esm/SvgJsExt.d.ts +85 -85
  41. package/lib/esm/SvgJsExt.js +180 -180
  42. package/lib/esm/TextEdit.d.ts +43 -43
  43. package/lib/esm/TextEdit.js +193 -191
  44. package/lib/esm/TextEdit.js.map +1 -1
  45. package/lib/esm/Undo.d.ts +46 -46
  46. package/lib/esm/Undo.js +164 -164
  47. package/lib/esm/core-markup.d.ts +18 -18
  48. package/lib/esm/core-markup.js +22 -22
  49. package/package.json +19 -19
@@ -1,513 +1,499 @@
1
- "use strict";
2
- /*---------------------------------------------------------------------------------------------
3
- * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
- * See LICENSE.md in the project root for license terms and full copyright notice.
5
- *--------------------------------------------------------------------------------------------*/
6
- /** @packageDocumentation
7
- * @module MarkupTools
8
- */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.SymbolTool = exports.SketchTool = exports.DistanceTool = exports.ArrowTool = exports.EllipseTool = exports.CircleTool = exports.CloudTool = exports.PolygonTool = exports.RectangleTool = exports.LineTool = exports.RedlineTool = void 0;
11
- // cspell:ignore rtmp stmp
12
- const core_geometry_1 = require("@itwin/core-geometry");
13
- const core_frontend_1 = require("@itwin/core-frontend");
14
- const svg_js_1 = require("@svgdotjs/svg.js");
15
- const Markup_1 = require("./Markup");
16
- const MarkupTool_1 = require("./MarkupTool");
17
- /** Base class for tools that place new Markup elements
18
- * @public
19
- */
20
- class RedlineTool extends MarkupTool_1.MarkupTool {
21
- constructor() {
22
- super(...arguments);
23
- this._minPoints = 1;
24
- this._nRequiredPoints = 2;
25
- this._points = [];
26
- }
27
- onAdded(el) {
28
- const markup = this.markup;
29
- const undo = markup.undo;
30
- undo.performOperation(this.keyin, () => undo.onAdded(el));
31
- markup.selected.restart(el);
32
- }
33
- isComplete(_ev) { return this._points.length >= this._nRequiredPoints; }
34
- setupAndPromptForNextAction() {
35
- super.setupAndPromptForNextAction();
36
- this.markup.disablePick();
37
- core_frontend_1.IModelApp.toolAdmin.setCursor(0 === this._points.length ? core_frontend_1.IModelApp.viewManager.crossHairCursor : core_frontend_1.IModelApp.viewManager.dynamicsCursor);
38
- }
39
- createMarkup(_svgMarkup, _ev, _isDynamics) { }
40
- clearDynamicsMarkup(_isDynamics) { this.markup.svgDynamics.clear(); }
41
- async onRestartTool() { return this.exitTool(); } // Default to single shot and return control to select tool...
42
- async onCleanup() { this.clearDynamicsMarkup(false); }
43
- async onReinitialize() {
44
- this.clearDynamicsMarkup(false);
45
- return super.onReinitialize();
46
- }
47
- async onUndoPreviousStep() {
48
- return (0 === this._points.length) ? false : (this.onReinitialize(), true);
49
- }
50
- async onMouseMotion(ev) {
51
- if (undefined === ev.viewport || this._points.length < this._minPoints)
52
- return;
53
- this.clearDynamicsMarkup(true);
54
- this.createMarkup(this.markup.svgDynamics, ev, true);
55
- }
56
- async onDataButtonDown(ev) {
57
- if (undefined === ev.viewport)
58
- return core_frontend_1.EventHandled.No;
59
- this._points.push(Markup_1.MarkupApp.convertVpToVb(ev.viewPoint));
60
- if (!this.isComplete(ev)) {
61
- this.setupAndPromptForNextAction();
62
- return core_frontend_1.EventHandled.No;
63
- }
64
- this.createMarkup(this.markup.svgMarkup, ev, false);
65
- await this.onReinitialize();
66
- return core_frontend_1.EventHandled.No;
67
- }
68
- async onResetButtonUp(_ev) {
69
- await this.onReinitialize();
70
- return core_frontend_1.EventHandled.No;
71
- }
72
- provideToolAssistance(mainInstrKey, singlePoint = false) {
73
- const mainInstruction = core_frontend_1.ToolAssistance.createInstruction(this.iconSpec, core_frontend_1.IModelApp.localization.getLocalizedString(mainInstrKey));
74
- const mouseInstructions = [];
75
- const touchInstructions = [];
76
- const acceptMsg = core_frontend_1.CoreTools.translate("ElementSet.Inputs.AcceptPoint");
77
- const rejectMsg = core_frontend_1.CoreTools.translate("ElementSet.Inputs.Exit");
78
- if (!core_frontend_1.ToolAssistance.createTouchCursorInstructions(touchInstructions))
79
- touchInstructions.push(core_frontend_1.ToolAssistance.createInstruction(singlePoint ? core_frontend_1.ToolAssistanceImage.OneTouchTap : core_frontend_1.ToolAssistanceImage.OneTouchDrag, acceptMsg, false, core_frontend_1.ToolAssistanceInputMethod.Touch));
80
- mouseInstructions.push(core_frontend_1.ToolAssistance.createInstruction(core_frontend_1.ToolAssistanceImage.LeftClick, acceptMsg, false, core_frontend_1.ToolAssistanceInputMethod.Mouse));
81
- touchInstructions.push(core_frontend_1.ToolAssistance.createInstruction(core_frontend_1.ToolAssistanceImage.TwoTouchTap, rejectMsg, false, core_frontend_1.ToolAssistanceInputMethod.Touch));
82
- mouseInstructions.push(core_frontend_1.ToolAssistance.createInstruction(core_frontend_1.ToolAssistanceImage.RightClick, rejectMsg, false, core_frontend_1.ToolAssistanceInputMethod.Mouse));
83
- const sections = [];
84
- sections.push(core_frontend_1.ToolAssistance.createSection(mouseInstructions, core_frontend_1.ToolAssistance.inputsLabel));
85
- sections.push(core_frontend_1.ToolAssistance.createSection(touchInstructions, core_frontend_1.ToolAssistance.inputsLabel));
86
- const instructions = core_frontend_1.ToolAssistance.createInstructions(mainInstruction, sections);
87
- core_frontend_1.IModelApp.notifications.setToolAssistance(instructions);
88
- }
89
- }
90
- exports.RedlineTool = RedlineTool;
91
- /** Tool for placing Markup Lines
92
- * @public
93
- */
94
- class LineTool extends RedlineTool {
95
- showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); }
96
- createMarkup(svgMarkup, ev, isDynamics) {
97
- if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
98
- return;
99
- const start = this._points[0];
100
- const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
101
- const element = svgMarkup.line(start.x, start.y, end.x, end.y);
102
- this.setCurrentStyle(element, false);
103
- if (!isDynamics)
104
- this.onAdded(element);
105
- }
106
- }
107
- exports.LineTool = LineTool;
108
- LineTool.toolId = "Markup.Line";
109
- LineTool.iconSpec = "icon-line";
110
- /** Tool for placing Markup Rectangles
111
- * @public
112
- */
113
- class RectangleTool extends RedlineTool {
114
- constructor(_cornerRadius) {
115
- super();
116
- this._cornerRadius = _cornerRadius;
117
- } // Specify radius to create a rectangle with rounded corners.
118
- showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner")); }
119
- createMarkup(svgMarkup, ev, isDynamics) {
120
- if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
121
- return;
122
- const start = this._points[0];
123
- const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
124
- const vec = start.vectorTo(end);
125
- const width = Math.abs(vec.x);
126
- const height = Math.abs(vec.y);
127
- if (width < 1 || height < 1)
128
- return;
129
- const offset = core_geometry_1.Point3d.create(vec.x < 0 ? end.x : start.x, vec.y < 0 ? end.y : start.y); // define location by corner points...
130
- const element = svgMarkup.rect(width, height).move(offset.x, offset.y);
131
- this.setCurrentStyle(element, true);
132
- if (undefined !== this._cornerRadius)
133
- element.radius(this._cornerRadius);
134
- if (!isDynamics)
135
- this.onAdded(element);
136
- }
137
- }
138
- exports.RectangleTool = RectangleTool;
139
- RectangleTool.toolId = "Markup.Rectangle";
140
- RectangleTool.iconSpec = "icon-rectangle";
141
- /** Tool for placing Markup Polygons
142
- * @public
143
- */
144
- class PolygonTool extends RedlineTool {
145
- constructor(_numSides) {
146
- super();
147
- this._numSides = _numSides;
148
- } // Specify number of polygon sides. Default if undefined is 5.
149
- showPrompt() { this.provideToolAssistance(MarkupTool_1.MarkupTool.toolKey + (0 === this._points.length ? "Polygon.Prompts.FirstPoint" : "Polygon.Prompts.NextPoint")); }
150
- getPoints(points, center, edge, numSides, inscribe) {
151
- if (numSides < 3 || numSides > 100)
152
- return false;
153
- let radius = center.distanceXY(edge);
154
- if (radius < 1)
155
- return false;
156
- const delta = (Math.PI * 2.0) / numSides;
157
- const vec = center.vectorTo(edge);
158
- let angle = core_geometry_1.Vector3d.unitX().planarRadiansTo(vec, core_geometry_1.Vector3d.unitZ());
159
- if (!inscribe) {
160
- const theta = delta * 0.5;
161
- angle -= theta;
162
- radius /= Math.cos(theta);
163
- }
164
- const rtmp = core_geometry_1.Point3d.create();
165
- const stmp = core_geometry_1.Point3d.create();
166
- for (let i = 0; i < numSides; i++, angle += delta) {
167
- rtmp.x = radius * Math.cos(angle);
168
- rtmp.y = radius * Math.sin(angle);
169
- rtmp.z = 0.0;
170
- center.plus(rtmp, stmp);
171
- points.push(stmp.x);
172
- points.push(stmp.y);
173
- }
174
- return true;
175
- }
176
- createMarkup(svgMarkup, ev, isDynamics) {
177
- if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
178
- return;
179
- const center = this._points[0];
180
- const edge = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
181
- const pts = [];
182
- if (!this.getPoints(pts, center, edge, undefined !== this._numSides ? this._numSides : 5, true))
183
- return;
184
- const element = svgMarkup.polygon(pts);
185
- this.setCurrentStyle(element, true);
186
- if (!isDynamics)
187
- this.onAdded(element);
188
- }
189
- }
190
- exports.PolygonTool = PolygonTool;
191
- PolygonTool.toolId = "Markup.Polygon";
192
- PolygonTool.iconSpec = "icon-polygon";
193
- /** Tool for placing Markup Clouds
194
- * @public
195
- */
196
- class CloudTool extends RedlineTool {
197
- showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner")); }
198
- createMarkup(svgMarkup, ev, isDynamics) {
199
- if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
200
- return;
201
- const start = this._points[0];
202
- const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
203
- const vec = start.vectorTo(end);
204
- const width = Math.abs(vec.x);
205
- const height = Math.abs(vec.y);
206
- if (width < 10 || height < 10)
207
- return;
208
- if (undefined === this._cloud) {
209
- this._cloud = svgMarkup.path(Markup_1.MarkupApp.props.active.cloud.path);
210
- }
211
- else if (!isDynamics) {
212
- svgMarkup.add(this._cloud);
213
- }
214
- const offset = core_geometry_1.Point3d.create(vec.x < 0 ? end.x : start.x, vec.y < 0 ? end.y : start.y); // define location by corner points...
215
- this._cloud.move(offset.x, offset.y);
216
- this._cloud.width(width);
217
- this._cloud.height(height);
218
- this.setCurrentStyle(this._cloud, true);
219
- if (!isDynamics)
220
- this.onAdded(this._cloud);
221
- }
222
- clearDynamicsMarkup(isDynamics) {
223
- if (!isDynamics)
224
- super.clearDynamicsMarkup(isDynamics); // For dynamics we don't create a new cloud each frame, we just set the width/height...
225
- }
226
- }
227
- exports.CloudTool = CloudTool;
228
- CloudTool.toolId = "Markup.Cloud";
229
- CloudTool.iconSpec = "icon-cloud";
230
- /** Tool for placing Markup Circles
231
- * @public
232
- */
233
- class CircleTool extends RedlineTool {
234
- showPrompt() { this.provideToolAssistance(MarkupTool_1.MarkupTool.toolKey + (0 === this._points.length ? "Circle.Prompts.FirstPoint" : "Circle.Prompts.NextPoint")); }
235
- createMarkup(svgMarkup, ev, isDynamics) {
236
- if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
237
- return;
238
- const start = this._points[0];
239
- const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
240
- const radius = start.distanceXY(end);
241
- if (radius < 1)
242
- return;
243
- const element = svgMarkup.circle(radius * 2.0).center(start.x, start.y);
244
- this.setCurrentStyle(element, true);
245
- if (!isDynamics)
246
- this.onAdded(element);
247
- }
248
- }
249
- exports.CircleTool = CircleTool;
250
- CircleTool.toolId = "Markup.Circle";
251
- CircleTool.iconSpec = "icon-circle";
252
- /** Tool for placing Markup Ellipses
253
- * @public
254
- */
255
- class EllipseTool extends RedlineTool {
256
- showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner")); }
257
- createMarkup(svgMarkup, ev, isDynamics) {
258
- if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
259
- return;
260
- const start = this._points[0];
261
- const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
262
- const vec = start.vectorTo(end);
263
- const width = Math.abs(vec.x);
264
- const height = Math.abs(vec.y);
265
- if (width < 1 || height < 1)
266
- return;
267
- const offset = core_geometry_1.Point3d.create(vec.x < 0 ? end.x : start.x, vec.y < 0 ? end.y : start.y); // define location by corner points...
268
- const element = svgMarkup.ellipse(width, height).move(offset.x, offset.y);
269
- this.setCurrentStyle(element, true);
270
- if (!isDynamics)
271
- this.onAdded(element);
272
- }
273
- }
274
- exports.EllipseTool = EllipseTool;
275
- EllipseTool.toolId = "Markup.Ellipse";
276
- EllipseTool.iconSpec = "icon-ellipse";
277
- /** Tool for placing Markup Arrows
278
- * @public
279
- */
280
- class ArrowTool extends RedlineTool {
281
- /** ctor for ArrowTool
282
- * @param _arrowPos "start", "end", or "both". If undefined = "end".
283
- */
284
- constructor(_arrowPos) {
285
- super();
286
- this._arrowPos = _arrowPos;
287
- }
288
- showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); }
289
- getOrCreateArrowMarker(color) {
290
- // NOTE: Flashing doesn't currently affect markers, need support for "context-stroke" and "context-fill". For now encode color in name...
291
- const arrowProps = Markup_1.MarkupApp.props.active.arrow;
292
- const arrowLength = arrowProps.length;
293
- const arrowWidth = arrowProps.width;
294
- const arrowMarkerId = `ArrowMarker${arrowLength}x${arrowWidth}-${color}`;
295
- let marker = (0, svg_js_1.SVG)(`#${arrowMarkerId}`);
296
- if (null === marker) {
297
- marker = this.markup.svgMarkup.marker(arrowLength, arrowWidth).id(arrowMarkerId);
298
- marker.polygon([0, 0, arrowLength, arrowWidth * 0.5, 0, arrowWidth]);
299
- marker.attr("orient", "auto-start-reverse");
300
- marker.attr("overflow", "visible"); // Don't clip the stroke that is being applied to allow the specified start/end to be used directly while hiding the arrow tail fully under the arrow head...
301
- marker.attr("refX", arrowLength);
302
- marker.css({ stroke: color, fill: color });
303
- }
304
- return marker;
305
- }
306
- createMarkup(svgMarkup, ev, isDynamics) {
307
- if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
308
- return;
309
- const start = this._points[0];
310
- const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
311
- const vec = start.vectorTo(end);
312
- if (!vec.normalizeInPlace())
313
- return;
314
- const element = svgMarkup.line(start.x, start.y, end.x, end.y);
315
- this.setCurrentStyle(element, false);
316
- const marker = this.getOrCreateArrowMarker(element.css("stroke"));
317
- const addToStart = ("start" === this._arrowPos || "both" === this._arrowPos);
318
- const addToEnd = ("end" === this._arrowPos || "both" === this._arrowPos);
319
- if (addToStart)
320
- element.marker("start", marker);
321
- if (addToEnd || !addToStart)
322
- element.marker("end", marker);
323
- if (!isDynamics)
324
- this.onAdded(element);
325
- }
326
- }
327
- exports.ArrowTool = ArrowTool;
328
- ArrowTool.toolId = "Markup.Arrow";
329
- ArrowTool.iconSpec = "icon-callout";
330
- /** Tool for measuring distances and placing Markups of them
331
- * @public
332
- */
333
- class DistanceTool extends ArrowTool {
334
- constructor() {
335
- super(...arguments);
336
- this._startPointWorld = new core_geometry_1.Point3d();
337
- }
338
- showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); }
339
- setupAndPromptForNextAction() {
340
- core_frontend_1.IModelApp.accuSnap.enableSnap(true);
341
- core_frontend_1.IModelApp.toolAdmin.toolState.coordLockOvr = core_frontend_1.CoordinateLockOverrides.None;
342
- super.setupAndPromptForNextAction();
343
- }
344
- getFormattedDistance(distance) {
345
- const formatterSpec = core_frontend_1.IModelApp.quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Length);
346
- if (undefined === formatterSpec)
347
- return undefined;
348
- return core_frontend_1.IModelApp.quantityFormatter.formatQuantity(distance, formatterSpec);
349
- }
350
- createMarkup(svgMarkup, ev, isDynamics) {
351
- if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
352
- return;
353
- const start = this._points[0];
354
- const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
355
- const vec = start.vectorTo(end);
356
- if (!vec.normalizeInPlace())
357
- return;
358
- const formatterSpec = core_frontend_1.IModelApp.quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Length);
359
- if (undefined === formatterSpec)
360
- return;
361
- const distanceLine = svgMarkup.line(start.x, start.y, end.x, end.y);
362
- this.setCurrentStyle(distanceLine, false);
363
- const marker = this.getOrCreateArrowMarker(distanceLine.css("stroke"));
364
- distanceLine.marker("start", marker);
365
- distanceLine.marker("end", marker);
366
- const loc = start.interpolate(0.5, end);
367
- const distance = core_frontend_1.IModelApp.quantityFormatter.formatQuantity(this._startPointWorld.distance(ev.point), formatterSpec);
368
- const text = svgMarkup.plain(distance).addClass(Markup_1.MarkupApp.textClass).attr("text-anchor", "middle").translate(loc.x, loc.y);
369
- this.setCurrentTextStyle(text);
370
- const textWithBg = this.createBoxedText(svgMarkup, text);
371
- if (!isDynamics) {
372
- const markup = this.markup;
373
- const undo = markup.undo;
374
- undo.performOperation(this.keyin, () => {
375
- undo.onAdded(distanceLine);
376
- undo.onAdded(textWithBg);
377
- });
378
- markup.selected.restart(textWithBg); // Select text+box so that user can freely position relative to distance line...
379
- }
380
- }
381
- async onDataButtonDown(ev) {
382
- if (undefined === await core_frontend_1.IModelApp.quantityFormatter.getFormatterSpecByQuantityType(core_frontend_1.QuantityType.Length)) {
383
- await this.onReinitialize();
384
- return core_frontend_1.EventHandled.No;
385
- }
386
- if (0 === this._points.length)
387
- this._startPointWorld.setFrom(ev.point);
388
- return super.onDataButtonDown(ev);
389
- }
390
- }
391
- exports.DistanceTool = DistanceTool;
392
- DistanceTool.toolId = "Markup.Distance";
393
- DistanceTool.iconSpec = "icon-distance";
394
- /** Tool for placing Markup freehand sketches
395
- * @public
396
- */
397
- class SketchTool extends RedlineTool {
398
- constructor() {
399
- super(...arguments);
400
- this._minDistSquared = 100;
401
- }
402
- showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); }
403
- createMarkup(svgMarkup, ev, isDynamics) {
404
- if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
405
- return;
406
- const pts = [];
407
- const evPt = Markup_1.MarkupApp.convertVpToVb(ev.viewPoint);
408
- this._points.forEach((pt) => {
409
- pts.push(pt.x);
410
- pts.push(pt.y);
411
- });
412
- if (isDynamics && !evPt.isAlmostEqualXY(this._points[this._points.length - 1])) {
413
- pts.push(evPt.x);
414
- pts.push(evPt.y);
415
- }
416
- const isClosed = (this._points.length > 2 && (this._points[0].distanceSquaredXY(isDynamics ? evPt : this._points[this._points.length - 1]) < this._minDistSquared * 2));
417
- const element = isClosed ? svgMarkup.polygon(pts) : svgMarkup.polyline(pts);
418
- this.setCurrentStyle(element, isClosed);
419
- if (!isDynamics)
420
- this.onAdded(element);
421
- }
422
- async onMouseMotion(ev) {
423
- const evPt = Markup_1.MarkupApp.convertVpToVb(ev.viewPoint);
424
- if (undefined !== ev.viewport && this._points.length > 0 && evPt.distanceSquaredXY(this._points[this._points.length - 1]) > this._minDistSquared)
425
- this._points.push(evPt);
426
- return super.onMouseMotion(ev);
427
- }
428
- }
429
- exports.SketchTool = SketchTool;
430
- SketchTool.toolId = "Markup.Sketch";
431
- SketchTool.iconSpec = "icon-draw";
432
- /** Tool for placing SVG symbols on a Markup
433
- * @public
434
- */
435
- class SymbolTool extends RedlineTool {
436
- constructor(_symbolData, _applyCurrentStyle) {
437
- super();
438
- this._symbolData = _symbolData;
439
- this._applyCurrentStyle = _applyCurrentStyle;
440
- }
441
- async onInstall() {
442
- if (undefined === this._symbolData)
443
- return false;
444
- return super.onInstall();
445
- }
446
- showPrompt() {
447
- this.provideToolAssistance(0 === this._points.length ? (`${MarkupTool_1.MarkupTool.toolKey}Symbol.Prompts.FirstPoint`) : `${core_frontend_1.CoreTools.tools}ElementSet.Prompts.OppositeCorner`, true);
448
- }
449
- createMarkup(svgMarkup, ev, isDynamics) {
450
- if (undefined === this._symbolData)
451
- return;
452
- if (this._points.length < this._minPoints)
453
- return;
454
- const start = this._points[0];
455
- const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[this._points.length - 1];
456
- const vec = start.vectorTo(end);
457
- const width = Math.abs(vec.x);
458
- const height = Math.abs(vec.y);
459
- if ((width < 10 || height < 10) && (isDynamics || this._points.length !== this._minPoints))
460
- return;
461
- if (undefined === this._symbol) {
462
- const symbol = svgMarkup.group().svg(this._symbolData); // creating group instead of using symbol because of inability to flash/hilite multi-color symbol instance...
463
- if (0 === symbol.children().length) {
464
- symbol.remove();
465
- this._symbolData = undefined;
466
- }
467
- try {
468
- symbol.flatten(symbol);
469
- }
470
- catch { }
471
- this._symbol = symbol;
472
- }
473
- else if (!isDynamics) {
474
- svgMarkup.add(this._symbol);
475
- }
476
- const offset = core_geometry_1.Point3d.create(vec.x < 0 ? end.x : start.x, vec.y < 0 ? end.y : start.y); // define location by corner points...
477
- if (!isDynamics && this._points.length === this._minPoints)
478
- this._symbol.size(ev.viewport.viewRect.width * 0.1).center(offset.x, offset.y);
479
- else if (!ev.isShiftKey)
480
- this._symbol.size(width).move(offset.x, offset.y);
481
- else
482
- this._symbol.size(width, height).move(offset.x, offset.y);
483
- if (this._applyCurrentStyle) {
484
- const active = Markup_1.MarkupApp.props.active; // Apply color and transparency only; using active stroke-width, etc. for pre-defined symbols is likely undesirable...
485
- this._symbol.forElementsOfGroup((child) => {
486
- const css = window.getComputedStyle(child.node);
487
- const toValue = (val, newVal) => (!val || val === "none") ? "none" : newVal;
488
- child.css({ "fill": toValue(css.fill, active.element.fill), "stroke": toValue(css.stroke, active.element.stroke), "fill-opacity": active.element["fill-opacity"], "stroke-opacity": active.element["stroke-opacity"] });
489
- });
490
- }
491
- if (!isDynamics)
492
- this.onAdded(this._symbol);
493
- }
494
- async onDataButtonUp(ev) {
495
- if (undefined === ev.viewport || this._points.length !== this._minPoints)
496
- return core_frontend_1.EventHandled.No;
497
- this.createMarkup(this.markup.svgMarkup, ev, false);
498
- await this.onReinitialize();
499
- return core_frontend_1.EventHandled.No;
500
- }
501
- async onResetButtonUp(_ev) {
502
- await this.onReinitialize();
503
- return core_frontend_1.EventHandled.No;
504
- }
505
- clearDynamicsMarkup(isDynamics) {
506
- if (!isDynamics)
507
- super.clearDynamicsMarkup(isDynamics); // For dynamics we don't create a new symbol each frame, we just set the width/height...
508
- }
509
- }
510
- exports.SymbolTool = SymbolTool;
511
- SymbolTool.toolId = "Markup.Symbol";
512
- SymbolTool.iconSpec = "icon-symbol";
1
+ "use strict";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
+ /** @packageDocumentation
7
+ * @module MarkupTools
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.SymbolTool = exports.SketchTool = exports.DistanceTool = exports.ArrowTool = exports.EllipseTool = exports.CircleTool = exports.CloudTool = exports.PolygonTool = exports.RectangleTool = exports.LineTool = exports.RedlineTool = void 0;
11
+ // cspell:ignore rtmp stmp
12
+ const core_geometry_1 = require("@itwin/core-geometry");
13
+ const core_frontend_1 = require("@itwin/core-frontend");
14
+ const Markup_1 = require("./Markup");
15
+ const MarkupTool_1 = require("./MarkupTool");
16
+ /** Base class for tools that place new Markup elements
17
+ * @public
18
+ */
19
+ class RedlineTool extends MarkupTool_1.MarkupTool {
20
+ constructor() {
21
+ super(...arguments);
22
+ this._minPoints = 1;
23
+ this._nRequiredPoints = 2;
24
+ this._points = [];
25
+ }
26
+ onAdded(el) {
27
+ const markup = this.markup;
28
+ const undo = markup.undo;
29
+ undo.performOperation(this.keyin, () => undo.onAdded(el));
30
+ markup.selected.restart(el);
31
+ }
32
+ isComplete(_ev) { return this._points.length >= this._nRequiredPoints; }
33
+ setupAndPromptForNextAction() {
34
+ super.setupAndPromptForNextAction();
35
+ this.markup.disablePick();
36
+ core_frontend_1.IModelApp.toolAdmin.setCursor(0 === this._points.length ? core_frontend_1.IModelApp.viewManager.crossHairCursor : core_frontend_1.IModelApp.viewManager.dynamicsCursor);
37
+ }
38
+ createMarkup(_svgMarkup, _ev, _isDynamics) { }
39
+ clearDynamicsMarkup(_isDynamics) { this.markup.svgDynamics.clear(); }
40
+ async onRestartTool() { return this.exitTool(); } // Default to single shot and return control to select tool...
41
+ async onCleanup() { this.clearDynamicsMarkup(false); }
42
+ async onReinitialize() {
43
+ this.clearDynamicsMarkup(false);
44
+ return super.onReinitialize();
45
+ }
46
+ async onUndoPreviousStep() {
47
+ return (0 === this._points.length) ? false : (this.onReinitialize(), true);
48
+ }
49
+ async onMouseMotion(ev) {
50
+ if (undefined === ev.viewport || this._points.length < this._minPoints)
51
+ return;
52
+ this.clearDynamicsMarkup(true);
53
+ this.createMarkup(this.markup.svgDynamics, ev, true);
54
+ }
55
+ async onDataButtonDown(ev) {
56
+ if (undefined === ev.viewport)
57
+ return core_frontend_1.EventHandled.No;
58
+ this._points.push(Markup_1.MarkupApp.convertVpToVb(ev.viewPoint));
59
+ if (!this.isComplete(ev)) {
60
+ this.setupAndPromptForNextAction();
61
+ return core_frontend_1.EventHandled.No;
62
+ }
63
+ this.createMarkup(this.markup.svgMarkup, ev, false);
64
+ await this.onReinitialize();
65
+ return core_frontend_1.EventHandled.No;
66
+ }
67
+ async onResetButtonUp(_ev) {
68
+ await this.onReinitialize();
69
+ return core_frontend_1.EventHandled.No;
70
+ }
71
+ provideToolAssistance(mainInstrKey, singlePoint = false) {
72
+ const mainInstruction = core_frontend_1.ToolAssistance.createInstruction(this.iconSpec, core_frontend_1.IModelApp.localization.getLocalizedString(mainInstrKey));
73
+ const mouseInstructions = [];
74
+ const touchInstructions = [];
75
+ const acceptMsg = core_frontend_1.CoreTools.translate("ElementSet.Inputs.AcceptPoint");
76
+ const rejectMsg = core_frontend_1.CoreTools.translate("ElementSet.Inputs.Exit");
77
+ if (!core_frontend_1.ToolAssistance.createTouchCursorInstructions(touchInstructions))
78
+ touchInstructions.push(core_frontend_1.ToolAssistance.createInstruction(singlePoint ? core_frontend_1.ToolAssistanceImage.OneTouchTap : core_frontend_1.ToolAssistanceImage.OneTouchDrag, acceptMsg, false, core_frontend_1.ToolAssistanceInputMethod.Touch));
79
+ mouseInstructions.push(core_frontend_1.ToolAssistance.createInstruction(core_frontend_1.ToolAssistanceImage.LeftClick, acceptMsg, false, core_frontend_1.ToolAssistanceInputMethod.Mouse));
80
+ touchInstructions.push(core_frontend_1.ToolAssistance.createInstruction(core_frontend_1.ToolAssistanceImage.TwoTouchTap, rejectMsg, false, core_frontend_1.ToolAssistanceInputMethod.Touch));
81
+ mouseInstructions.push(core_frontend_1.ToolAssistance.createInstruction(core_frontend_1.ToolAssistanceImage.RightClick, rejectMsg, false, core_frontend_1.ToolAssistanceInputMethod.Mouse));
82
+ const sections = [];
83
+ sections.push(core_frontend_1.ToolAssistance.createSection(mouseInstructions, core_frontend_1.ToolAssistance.inputsLabel));
84
+ sections.push(core_frontend_1.ToolAssistance.createSection(touchInstructions, core_frontend_1.ToolAssistance.inputsLabel));
85
+ const instructions = core_frontend_1.ToolAssistance.createInstructions(mainInstruction, sections);
86
+ core_frontend_1.IModelApp.notifications.setToolAssistance(instructions);
87
+ }
88
+ }
89
+ exports.RedlineTool = RedlineTool;
90
+ /** Tool for placing Markup Lines
91
+ * @public
92
+ */
93
+ class LineTool extends RedlineTool {
94
+ showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); }
95
+ createMarkup(svgMarkup, ev, isDynamics) {
96
+ if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
97
+ return;
98
+ const start = this._points[0];
99
+ const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
100
+ const element = svgMarkup.line(start.x, start.y, end.x, end.y);
101
+ this.setCurrentStyle(element, false);
102
+ if (!isDynamics)
103
+ this.onAdded(element);
104
+ }
105
+ }
106
+ LineTool.toolId = "Markup.Line";
107
+ LineTool.iconSpec = "icon-line";
108
+ exports.LineTool = LineTool;
109
+ /** Tool for placing Markup Rectangles
110
+ * @public
111
+ */
112
+ class RectangleTool extends RedlineTool {
113
+ constructor(_cornerRadius) {
114
+ super();
115
+ this._cornerRadius = _cornerRadius;
116
+ } // Specify radius to create a rectangle with rounded corners.
117
+ showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner")); }
118
+ createMarkup(svgMarkup, ev, isDynamics) {
119
+ if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
120
+ return;
121
+ const start = this._points[0];
122
+ const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
123
+ const vec = start.vectorTo(end);
124
+ const width = Math.abs(vec.x);
125
+ const height = Math.abs(vec.y);
126
+ if (width < 1 || height < 1)
127
+ return;
128
+ const offset = core_geometry_1.Point3d.create(vec.x < 0 ? end.x : start.x, vec.y < 0 ? end.y : start.y); // define location by corner points...
129
+ const element = svgMarkup.rect(width, height).move(offset.x, offset.y);
130
+ this.setCurrentStyle(element, true);
131
+ if (undefined !== this._cornerRadius)
132
+ element.radius(this._cornerRadius);
133
+ if (!isDynamics)
134
+ this.onAdded(element);
135
+ }
136
+ }
137
+ RectangleTool.toolId = "Markup.Rectangle";
138
+ RectangleTool.iconSpec = "icon-rectangle";
139
+ exports.RectangleTool = RectangleTool;
140
+ /** Tool for placing Markup Polygons
141
+ * @public
142
+ */
143
+ class PolygonTool extends RedlineTool {
144
+ constructor(_numSides) {
145
+ super();
146
+ this._numSides = _numSides;
147
+ } // Specify number of polygon sides. Default if undefined is 5.
148
+ showPrompt() { this.provideToolAssistance(MarkupTool_1.MarkupTool.toolKey + (0 === this._points.length ? "Polygon.Prompts.FirstPoint" : "Polygon.Prompts.NextPoint")); }
149
+ getPoints(points, center, edge, numSides, inscribe) {
150
+ if (numSides < 3 || numSides > 100)
151
+ return false;
152
+ let radius = center.distanceXY(edge);
153
+ if (radius < 1)
154
+ return false;
155
+ const delta = (Math.PI * 2.0) / numSides;
156
+ const vec = center.vectorTo(edge);
157
+ let angle = core_geometry_1.Vector3d.unitX().planarRadiansTo(vec, core_geometry_1.Vector3d.unitZ());
158
+ if (!inscribe) {
159
+ const theta = delta * 0.5;
160
+ angle -= theta;
161
+ radius /= Math.cos(theta);
162
+ }
163
+ const rtmp = core_geometry_1.Point3d.create();
164
+ const stmp = core_geometry_1.Point3d.create();
165
+ for (let i = 0; i < numSides; i++, angle += delta) {
166
+ rtmp.x = radius * Math.cos(angle);
167
+ rtmp.y = radius * Math.sin(angle);
168
+ rtmp.z = 0.0;
169
+ center.plus(rtmp, stmp);
170
+ points.push(stmp.x);
171
+ points.push(stmp.y);
172
+ }
173
+ return true;
174
+ }
175
+ createMarkup(svgMarkup, ev, isDynamics) {
176
+ if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
177
+ return;
178
+ const center = this._points[0];
179
+ const edge = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
180
+ const pts = [];
181
+ if (!this.getPoints(pts, center, edge, undefined !== this._numSides ? this._numSides : 5, true))
182
+ return;
183
+ const element = svgMarkup.polygon(pts);
184
+ this.setCurrentStyle(element, true);
185
+ if (!isDynamics)
186
+ this.onAdded(element);
187
+ }
188
+ }
189
+ PolygonTool.toolId = "Markup.Polygon";
190
+ PolygonTool.iconSpec = "icon-polygon";
191
+ exports.PolygonTool = PolygonTool;
192
+ /** Tool for placing Markup Clouds
193
+ * @public
194
+ */
195
+ class CloudTool extends RedlineTool {
196
+ showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner")); }
197
+ createMarkup(svgMarkup, ev, isDynamics) {
198
+ if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
199
+ return;
200
+ const start = this._points[0];
201
+ const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
202
+ const vec = start.vectorTo(end);
203
+ const width = Math.abs(vec.x);
204
+ const height = Math.abs(vec.y);
205
+ if (width < 10 || height < 10)
206
+ return;
207
+ if (undefined === this._cloud) {
208
+ this._cloud = svgMarkup.path(Markup_1.MarkupApp.props.active.cloud.path);
209
+ }
210
+ else if (!isDynamics) {
211
+ svgMarkup.add(this._cloud);
212
+ }
213
+ const offset = core_geometry_1.Point3d.create(vec.x < 0 ? end.x : start.x, vec.y < 0 ? end.y : start.y); // define location by corner points...
214
+ this._cloud.move(offset.x, offset.y);
215
+ this._cloud.width(width);
216
+ this._cloud.height(height);
217
+ this.setCurrentStyle(this._cloud, true);
218
+ if (!isDynamics)
219
+ this.onAdded(this._cloud);
220
+ }
221
+ clearDynamicsMarkup(isDynamics) {
222
+ if (!isDynamics)
223
+ super.clearDynamicsMarkup(isDynamics); // For dynamics we don't create a new cloud each frame, we just set the width/height...
224
+ }
225
+ }
226
+ CloudTool.toolId = "Markup.Cloud";
227
+ CloudTool.iconSpec = "icon-cloud";
228
+ exports.CloudTool = CloudTool;
229
+ /** Tool for placing Markup Circles
230
+ * @public
231
+ */
232
+ class CircleTool extends RedlineTool {
233
+ showPrompt() { this.provideToolAssistance(MarkupTool_1.MarkupTool.toolKey + (0 === this._points.length ? "Circle.Prompts.FirstPoint" : "Circle.Prompts.NextPoint")); }
234
+ createMarkup(svgMarkup, ev, isDynamics) {
235
+ if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
236
+ return;
237
+ const start = this._points[0];
238
+ const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
239
+ const radius = start.distanceXY(end);
240
+ if (radius < 1)
241
+ return;
242
+ const element = svgMarkup.circle(radius * 2.0).center(start.x, start.y);
243
+ this.setCurrentStyle(element, true);
244
+ if (!isDynamics)
245
+ this.onAdded(element);
246
+ }
247
+ }
248
+ CircleTool.toolId = "Markup.Circle";
249
+ CircleTool.iconSpec = "icon-circle";
250
+ exports.CircleTool = CircleTool;
251
+ /** Tool for placing Markup Ellipses
252
+ * @public
253
+ */
254
+ class EllipseTool extends RedlineTool {
255
+ showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner")); }
256
+ createMarkup(svgMarkup, ev, isDynamics) {
257
+ if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
258
+ return;
259
+ const start = this._points[0];
260
+ const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
261
+ const vec = start.vectorTo(end);
262
+ const width = Math.abs(vec.x);
263
+ const height = Math.abs(vec.y);
264
+ if (width < 1 || height < 1)
265
+ return;
266
+ const offset = core_geometry_1.Point3d.create(vec.x < 0 ? end.x : start.x, vec.y < 0 ? end.y : start.y); // define location by corner points...
267
+ const element = svgMarkup.ellipse(width, height).move(offset.x, offset.y);
268
+ this.setCurrentStyle(element, true);
269
+ if (!isDynamics)
270
+ this.onAdded(element);
271
+ }
272
+ }
273
+ EllipseTool.toolId = "Markup.Ellipse";
274
+ EllipseTool.iconSpec = "icon-ellipse";
275
+ exports.EllipseTool = EllipseTool;
276
+ /** Tool for placing Markup Arrows
277
+ * @public
278
+ */
279
+ class ArrowTool extends RedlineTool {
280
+ /** ctor for ArrowTool
281
+ * @param _arrowPos "start", "end", or "both". If undefined = "end".
282
+ */
283
+ constructor(_arrowPos) {
284
+ super();
285
+ this._arrowPos = _arrowPos;
286
+ }
287
+ showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); }
288
+ getOrCreateArrowMarker(color) {
289
+ const arrowProps = Markup_1.MarkupApp.props.active.arrow;
290
+ return this.markup.createArrowMarker(color, arrowProps.length, arrowProps.width);
291
+ }
292
+ createMarkup(svgMarkup, ev, isDynamics) {
293
+ if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
294
+ return;
295
+ const start = this._points[0];
296
+ const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
297
+ const vec = start.vectorTo(end);
298
+ if (!vec.normalizeInPlace())
299
+ return;
300
+ const element = svgMarkup.line(start.x, start.y, end.x, end.y);
301
+ this.setCurrentStyle(element, false);
302
+ const marker = this.getOrCreateArrowMarker(element.css("stroke"));
303
+ const addToStart = ("start" === this._arrowPos || "both" === this._arrowPos);
304
+ const addToEnd = ("end" === this._arrowPos || "both" === this._arrowPos);
305
+ if (addToStart)
306
+ element.marker("start", marker);
307
+ if (addToEnd || !addToStart)
308
+ element.marker("end", marker);
309
+ if (!isDynamics)
310
+ this.onAdded(element);
311
+ }
312
+ }
313
+ ArrowTool.toolId = "Markup.Arrow";
314
+ ArrowTool.iconSpec = "icon-callout";
315
+ exports.ArrowTool = ArrowTool;
316
+ /** Tool for measuring distances and placing Markups of them
317
+ * @public
318
+ */
319
+ class DistanceTool extends ArrowTool {
320
+ constructor() {
321
+ super(...arguments);
322
+ this._startPointWorld = new core_geometry_1.Point3d();
323
+ }
324
+ showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); }
325
+ setupAndPromptForNextAction() {
326
+ core_frontend_1.IModelApp.accuSnap.enableSnap(true);
327
+ core_frontend_1.IModelApp.toolAdmin.toolState.coordLockOvr = core_frontend_1.CoordinateLockOverrides.None;
328
+ super.setupAndPromptForNextAction();
329
+ }
330
+ getFormattedDistance(distance) {
331
+ const formatterSpec = core_frontend_1.IModelApp.quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Length);
332
+ if (undefined === formatterSpec)
333
+ return undefined;
334
+ return core_frontend_1.IModelApp.quantityFormatter.formatQuantity(distance, formatterSpec);
335
+ }
336
+ createMarkup(svgMarkup, ev, isDynamics) {
337
+ if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
338
+ return;
339
+ const start = this._points[0];
340
+ const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[1];
341
+ const vec = start.vectorTo(end);
342
+ if (!vec.normalizeInPlace())
343
+ return;
344
+ const formatterSpec = core_frontend_1.IModelApp.quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Length);
345
+ if (undefined === formatterSpec)
346
+ return;
347
+ const distanceLine = svgMarkup.line(start.x, start.y, end.x, end.y);
348
+ this.setCurrentStyle(distanceLine, false);
349
+ const marker = this.getOrCreateArrowMarker(distanceLine.css("stroke"));
350
+ distanceLine.marker("start", marker);
351
+ distanceLine.marker("end", marker);
352
+ const loc = start.interpolate(0.5, end);
353
+ const distance = core_frontend_1.IModelApp.quantityFormatter.formatQuantity(this._startPointWorld.distance(ev.point), formatterSpec);
354
+ const text = svgMarkup.plain(distance).addClass(Markup_1.MarkupApp.textClass).attr("text-anchor", "middle").translate(loc.x, loc.y);
355
+ this.setCurrentTextStyle(text);
356
+ const textWithBg = this.createBoxedText(svgMarkup, text);
357
+ if (!isDynamics) {
358
+ const markup = this.markup;
359
+ const undo = markup.undo;
360
+ undo.performOperation(this.keyin, () => {
361
+ undo.onAdded(distanceLine);
362
+ undo.onAdded(textWithBg);
363
+ });
364
+ markup.selected.restart(textWithBg); // Select text+box so that user can freely position relative to distance line...
365
+ }
366
+ }
367
+ async onDataButtonDown(ev) {
368
+ if (undefined === await core_frontend_1.IModelApp.quantityFormatter.getFormatterSpecByQuantityType(core_frontend_1.QuantityType.Length)) {
369
+ await this.onReinitialize();
370
+ return core_frontend_1.EventHandled.No;
371
+ }
372
+ if (0 === this._points.length)
373
+ this._startPointWorld.setFrom(ev.point);
374
+ return super.onDataButtonDown(ev);
375
+ }
376
+ }
377
+ DistanceTool.toolId = "Markup.Distance";
378
+ DistanceTool.iconSpec = "icon-distance";
379
+ exports.DistanceTool = DistanceTool;
380
+ /** Tool for placing Markup freehand sketches
381
+ * @public
382
+ */
383
+ class SketchTool extends RedlineTool {
384
+ constructor() {
385
+ super(...arguments);
386
+ this._minDistSquared = 100;
387
+ }
388
+ showPrompt() { this.provideToolAssistance(core_frontend_1.CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); }
389
+ createMarkup(svgMarkup, ev, isDynamics) {
390
+ if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints))
391
+ return;
392
+ const pts = [];
393
+ const evPt = Markup_1.MarkupApp.convertVpToVb(ev.viewPoint);
394
+ this._points.forEach((pt) => {
395
+ pts.push(pt.x);
396
+ pts.push(pt.y);
397
+ });
398
+ if (isDynamics && !evPt.isAlmostEqualXY(this._points[this._points.length - 1])) {
399
+ pts.push(evPt.x);
400
+ pts.push(evPt.y);
401
+ }
402
+ const isClosed = (this._points.length > 2 && (this._points[0].distanceSquaredXY(isDynamics ? evPt : this._points[this._points.length - 1]) < this._minDistSquared * 2));
403
+ const element = isClosed ? svgMarkup.polygon(pts) : svgMarkup.polyline(pts);
404
+ this.setCurrentStyle(element, isClosed);
405
+ if (!isDynamics)
406
+ this.onAdded(element);
407
+ }
408
+ async onMouseMotion(ev) {
409
+ const evPt = Markup_1.MarkupApp.convertVpToVb(ev.viewPoint);
410
+ if (undefined !== ev.viewport && this._points.length > 0 && evPt.distanceSquaredXY(this._points[this._points.length - 1]) > this._minDistSquared)
411
+ this._points.push(evPt);
412
+ return super.onMouseMotion(ev);
413
+ }
414
+ }
415
+ SketchTool.toolId = "Markup.Sketch";
416
+ SketchTool.iconSpec = "icon-draw";
417
+ exports.SketchTool = SketchTool;
418
+ /** Tool for placing SVG symbols on a Markup
419
+ * @public
420
+ */
421
+ class SymbolTool extends RedlineTool {
422
+ constructor(_symbolData, _applyCurrentStyle) {
423
+ super();
424
+ this._symbolData = _symbolData;
425
+ this._applyCurrentStyle = _applyCurrentStyle;
426
+ }
427
+ async onInstall() {
428
+ if (undefined === this._symbolData)
429
+ return false;
430
+ return super.onInstall();
431
+ }
432
+ showPrompt() {
433
+ this.provideToolAssistance(0 === this._points.length ? (`${MarkupTool_1.MarkupTool.toolKey}Symbol.Prompts.FirstPoint`) : `${core_frontend_1.CoreTools.tools}ElementSet.Prompts.OppositeCorner`, true);
434
+ }
435
+ createMarkup(svgMarkup, ev, isDynamics) {
436
+ if (undefined === this._symbolData)
437
+ return;
438
+ if (this._points.length < this._minPoints)
439
+ return;
440
+ const start = this._points[0];
441
+ const end = isDynamics ? Markup_1.MarkupApp.convertVpToVb(ev.viewPoint) : this._points[this._points.length - 1];
442
+ const vec = start.vectorTo(end);
443
+ const width = Math.abs(vec.x);
444
+ const height = Math.abs(vec.y);
445
+ if ((width < 10 || height < 10) && (isDynamics || this._points.length !== this._minPoints))
446
+ return;
447
+ if (undefined === this._symbol) {
448
+ const symbol = svgMarkup.group().svg(this._symbolData); // creating group instead of using symbol because of inability to flash/hilite multi-color symbol instance...
449
+ if (0 === symbol.children().length) {
450
+ symbol.remove();
451
+ this._symbolData = undefined;
452
+ }
453
+ try {
454
+ symbol.flatten(symbol);
455
+ }
456
+ catch { }
457
+ this._symbol = symbol;
458
+ }
459
+ else if (!isDynamics) {
460
+ svgMarkup.add(this._symbol);
461
+ }
462
+ const offset = core_geometry_1.Point3d.create(vec.x < 0 ? end.x : start.x, vec.y < 0 ? end.y : start.y); // define location by corner points...
463
+ if (!isDynamics && this._points.length === this._minPoints)
464
+ this._symbol.size(ev.viewport.viewRect.width * 0.1).center(offset.x, offset.y);
465
+ else if (!ev.isShiftKey)
466
+ this._symbol.size(width).move(offset.x, offset.y);
467
+ else
468
+ this._symbol.size(width, height).move(offset.x, offset.y);
469
+ if (this._applyCurrentStyle) {
470
+ const active = Markup_1.MarkupApp.props.active; // Apply color and transparency only; using active stroke-width, etc. for pre-defined symbols is likely undesirable...
471
+ this._symbol.forElementsOfGroup((child) => {
472
+ const css = window.getComputedStyle(child.node);
473
+ const toValue = (val, newVal) => (!val || val === "none") ? "none" : newVal;
474
+ child.css({ "fill": toValue(css.fill, active.element.fill), "stroke": toValue(css.stroke, active.element.stroke), "fill-opacity": active.element["fill-opacity"], "stroke-opacity": active.element["stroke-opacity"] });
475
+ });
476
+ }
477
+ if (!isDynamics)
478
+ this.onAdded(this._symbol);
479
+ }
480
+ async onDataButtonUp(ev) {
481
+ if (undefined === ev.viewport || this._points.length !== this._minPoints)
482
+ return core_frontend_1.EventHandled.No;
483
+ this.createMarkup(this.markup.svgMarkup, ev, false);
484
+ await this.onReinitialize();
485
+ return core_frontend_1.EventHandled.No;
486
+ }
487
+ async onResetButtonUp(_ev) {
488
+ await this.onReinitialize();
489
+ return core_frontend_1.EventHandled.No;
490
+ }
491
+ clearDynamicsMarkup(isDynamics) {
492
+ if (!isDynamics)
493
+ super.clearDynamicsMarkup(isDynamics); // For dynamics we don't create a new symbol each frame, we just set the width/height...
494
+ }
495
+ }
496
+ SymbolTool.toolId = "Markup.Symbol";
497
+ SymbolTool.iconSpec = "icon-symbol";
498
+ exports.SymbolTool = SymbolTool;
513
499
  //# sourceMappingURL=RedlineTool.js.map