@design-core/core 51.1.0 → 52.0.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.
- package/.github/workflows/publish.yml +40 -0
- package/README.md +14 -1
- package/core/dimensions/alignedDimension.js +3 -1
- package/core/dimensions/angularDimension.js +118 -36
- package/core/dimensions/circularDimensionBase.js +32 -12
- package/core/dimensions/diametricDimension.js +29 -1
- package/core/dimensions/dimension.js +58 -5
- package/core/dimensions/dimensionBase.js +107 -4
- package/core/dimensions/linearDimensionBase.js +75 -37
- package/core/dimensions/radialDimension.js +26 -1
- package/core/dimensions/rotatedDimension.js +6 -3
- package/core/entities/entity.js +9 -0
- package/core/lib/auxiliary/snapPoint.js +9 -0
- package/core/lib/canvas.js +26 -1
- package/core/lib/commandManager.js +9 -4
- package/core/lib/dxf/dxf.js +8 -2
- package/core/lib/inputManager.js +24 -3
- package/core/lib/mouse.js +10 -0
- package/core/lib/plotOptions.js +17 -0
- package/core/lib/renderers/pdfRenderer.js +17 -1
- package/core/lib/scene.js +2 -0
- package/core/lib/selectionManager.js +28 -0
- package/core/lib/strings.js +3 -0
- package/core/properties/dimType.js +14 -0
- package/core/properties/property.js +1 -0
- package/core/tables/dimStyle.js +32 -2
- package/core/tools/gripStretch.js +97 -0
- package/core/tools/offset.js +7 -1
- package/core/tools/tool.js +10 -0
- package/core/tools/windowPick.js +75 -0
- package/cspell.json +5 -0
- package/package.json +7 -2
- package/test/dimensions/alignedDimension.test.js +165 -0
- package/test/dimensions/angularDimension.test.js +149 -0
- package/test/dimensions/diametricDimension.test.js +76 -4
- package/test/dimensions/dimension.test.js +130 -0
- package/test/dimensions/dimensionBase.test.js +97 -4
- package/test/dimensions/radialDimension.test.js +33 -0
- package/test/dimensions/rotatedDimension.test.js +80 -0
- package/test/integration/exportIntegration.reference.dxf +3 -9
- package/test/integration/plotPageSizeIntegration.test.js +113 -0
- package/test/integration/userInputIntegration.reference.dxf +3 -9
- package/test/lib/inputManager.test.js +316 -1
- package/test/lib/plotOptions.test.js +58 -1
- package/test/lib/selectionManager.test.js +42 -0
- package/test/renderers/pdfRenderer.test.js +26 -0
- package/test/tables/dimstyle.test.js +32 -0
- package/test/tools/gripStretch.test.js +108 -0
- package/test/tools/offset.test.js +2 -0
- package/test/tools/tool.test.js +25 -0
- package/test/tools/windowPick.test.js +129 -0
package/core/lib/plotOptions.js
CHANGED
|
@@ -9,6 +9,7 @@ export class PlotOptions {
|
|
|
9
9
|
static Area = {
|
|
10
10
|
EXTENTS: 'Extents',
|
|
11
11
|
DISPLAY: 'Display',
|
|
12
|
+
WINDOW: 'Window',
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
static #fileTypes = ['pdf', 'svg'];
|
|
@@ -22,6 +23,8 @@ export class PlotOptions {
|
|
|
22
23
|
this.setOption('pageHeight', pageHeight);
|
|
23
24
|
this.plotScale = null;
|
|
24
25
|
this.plotArea = PlotOptions.Area.EXTENTS;
|
|
26
|
+
this.windowArea = null;
|
|
27
|
+
this.margin = 40;
|
|
25
28
|
this.style = RendererBase.Styles.NONE;
|
|
26
29
|
this.fileType = 'pdf';
|
|
27
30
|
}
|
|
@@ -49,6 +52,20 @@ export class PlotOptions {
|
|
|
49
52
|
throw new Error(`PlotOptions: plotArea must be one of: ${Object.values(PlotOptions.Area).join(', ')}`);
|
|
50
53
|
}
|
|
51
54
|
break;
|
|
55
|
+
case 'windowArea':
|
|
56
|
+
// required when plotArea is WINDOW - two points defining the plot window, e.g. { point1, point2 }
|
|
57
|
+
if (value !== null && (!value || value.point1 === undefined || value.point2 === undefined)) {
|
|
58
|
+
throw new Error('PlotOptions: windowArea must be null or an object with point1 and point2');
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
case 'margin':
|
|
62
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
63
|
+
throw new Error('PlotOptions: margin must be a non-negative finite number');
|
|
64
|
+
}
|
|
65
|
+
if (this.pageWidth - 2 * value <= 0 || this.pageHeight - 2 * value <= 0) {
|
|
66
|
+
throw new Error('PlotOptions: margin leaves no usable page area');
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
52
69
|
case 'style':
|
|
53
70
|
if (typeof value !== 'function') {
|
|
54
71
|
throw new Error('PlotOptions: style must be a function');
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { RendererBase } from './rendererBase.js';
|
|
2
2
|
import { Text } from '../../entities/text.js';
|
|
3
3
|
|
|
4
|
+
// Unicode code points mapped to WinAnsi bytes 0x80-0x9F (the range where WinAnsi differs from Latin-1)
|
|
5
|
+
const WIN_ANSI_EXTRAS = new Map([
|
|
6
|
+
[0x20ac, 0x80], [0x201a, 0x82], [0x0192, 0x83], [0x201e, 0x84], [0x2026, 0x85],
|
|
7
|
+
[0x2020, 0x86], [0x2021, 0x87], [0x02c6, 0x88], [0x2030, 0x89], [0x0160, 0x8a],
|
|
8
|
+
[0x2039, 0x8b], [0x0152, 0x8c], [0x017d, 0x8e], [0x2018, 0x91], [0x2019, 0x92],
|
|
9
|
+
[0x201c, 0x93], [0x201d, 0x94], [0x2022, 0x95], [0x2013, 0x96], [0x2014, 0x97],
|
|
10
|
+
[0x02dc, 0x98], [0x2122, 0x99], [0x0161, 0x9a], [0x203a, 0x9b], [0x0153, 0x9c],
|
|
11
|
+
[0x017e, 0x9e], [0x0178, 0x9f],
|
|
12
|
+
]);
|
|
13
|
+
|
|
4
14
|
/**
|
|
5
15
|
* Pure-JS PDF renderer.
|
|
6
16
|
* Implements the RendererBase interface by accumulating a PDF content stream in memory.
|
|
@@ -361,6 +371,12 @@ export class PdfRenderer extends RendererBase {
|
|
|
361
371
|
return str
|
|
362
372
|
.replace(/\\/g, '\\\\')
|
|
363
373
|
.replace(/\(/g, '\\(')
|
|
364
|
-
.replace(/\)/g, '\\)')
|
|
374
|
+
.replace(/\)/g, '\\)')
|
|
375
|
+
// Keep output ASCII: map Unicode to WinAnsi (Windows-1252) bytes, unsupported characters become '?'
|
|
376
|
+
.replace(/[^\x00-\x7f]/g, (c) => {
|
|
377
|
+
const code = c.charCodeAt(0);
|
|
378
|
+
const byte = WIN_ANSI_EXTRAS.get(code) ?? (code >= 0xa0 && code <= 0xff ? code : 0x3f);
|
|
379
|
+
return '\\' + byte.toString(8).padStart(3, '0');
|
|
380
|
+
});
|
|
365
381
|
}
|
|
366
382
|
}
|
package/core/lib/scene.js
CHANGED
|
@@ -139,6 +139,7 @@ export class Scene {
|
|
|
139
139
|
undo() {
|
|
140
140
|
if (this.stateManager.canUndo()) {
|
|
141
141
|
this.stateManager.undo();
|
|
142
|
+
this.selectionManager.reloadSelectedEntities();
|
|
142
143
|
DesignCore.Canvas.requestPaint();
|
|
143
144
|
} else {
|
|
144
145
|
DesignCore.Core.notify(Strings.Message.NOUNDO);
|
|
@@ -151,6 +152,7 @@ export class Scene {
|
|
|
151
152
|
redo() {
|
|
152
153
|
if (this.stateManager.canRedo()) {
|
|
153
154
|
this.stateManager.redo();
|
|
155
|
+
this.selectionManager.reloadSelectedEntities();
|
|
154
156
|
DesignCore.Canvas.requestPaint();
|
|
155
157
|
} else {
|
|
156
158
|
DesignCore.Core.notify(Strings.Message.NOREDO);
|
|
@@ -156,6 +156,34 @@ export class SelectionManager {
|
|
|
156
156
|
return DesignCore.Scene.entities.findClosest(point);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Find the grip closest to point, within tolerance, across all selected entities.
|
|
161
|
+
* Hit-tests against the real scene entities (not the selectedEntities preview clones) so a
|
|
162
|
+
* grip's apply() always recomputes from the last-committed geometry.
|
|
163
|
+
* @param {Point} point
|
|
164
|
+
* @return {Object|undefined} { entityIndex, grip } or undefined if no grip is close enough
|
|
165
|
+
*/
|
|
166
|
+
findGripUnderMouse(point) {
|
|
167
|
+
const gripAperture = 25; // capture radius in pixels (screen space), matches Snapping's snapAperture
|
|
168
|
+
const delta = gripAperture / DesignCore.Canvas.getScale();
|
|
169
|
+
|
|
170
|
+
let closestGrip;
|
|
171
|
+
let closestDistance = delta;
|
|
172
|
+
|
|
173
|
+
for (const entityIndex of this.selectionSet.selectionSet) {
|
|
174
|
+
const entity = DesignCore.Scene.entities.get(entityIndex);
|
|
175
|
+
for (const grip of entity.getGrips()) {
|
|
176
|
+
const distance = grip.point.distance(point);
|
|
177
|
+
if (distance < closestDistance) {
|
|
178
|
+
closestDistance = distance;
|
|
179
|
+
closestGrip = { entityIndex, grip };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return closestGrip;
|
|
185
|
+
}
|
|
186
|
+
|
|
159
187
|
/**
|
|
160
188
|
* Remove the item at index from the selectionSet and selectedEntities
|
|
161
189
|
* @param {number} index - index of the item
|
package/core/lib/strings.js
CHANGED
|
@@ -110,9 +110,12 @@ export class Strings {
|
|
|
110
110
|
DESTINATIONSET: 'Select destination object(s)',
|
|
111
111
|
MIRRORFIRST: 'Specify first point of mirror line',
|
|
112
112
|
MIRRORSECOND: 'Specify second point of mirror line',
|
|
113
|
+
FIRSTCORNER: 'Specify first corner',
|
|
114
|
+
SECONDCORNER: 'Specify second corner',
|
|
113
115
|
ERASESOURCE: 'Erase source objects?',
|
|
114
116
|
SCALEFACTOR: 'Specify scale factor',
|
|
115
117
|
REFERENCELENGTH: 'Specify reference length',
|
|
116
118
|
NEWLENGTH: 'Specify new length',
|
|
119
|
+
STRETCHPOINT: 'Specify stretch point',
|
|
117
120
|
};
|
|
118
121
|
};
|
|
@@ -99,6 +99,20 @@ export class DimType {
|
|
|
99
99
|
this.userPositionedText = (dimType & 128) !== 0;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Set only the base dimension type (0-6), leaving the block reference, ordinate and
|
|
104
|
+
* user-positioned-text flags untouched - used by subclass constructors to pin their type
|
|
105
|
+
* without clobbering flags already loaded from a DXF group 70 value
|
|
106
|
+
* @param {number} baseType
|
|
107
|
+
*/
|
|
108
|
+
setBaseType(baseType) {
|
|
109
|
+
if (!DimType.isValidDimensionType(baseType)) {
|
|
110
|
+
baseType = 0;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
this.dimType = DimType.getBaseType(baseType);
|
|
114
|
+
}
|
|
115
|
+
|
|
102
116
|
/**
|
|
103
117
|
* Check if the dimension has a block reference
|
|
104
118
|
* @return {boolean} true if the dimension has a block reference
|
package/core/tables/dimStyle.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { DXFFile } from '../lib/dxf/dxfFile.js';
|
|
3
|
+
import { DesignCore } from '../designCore.js';
|
|
3
4
|
import { Logging } from '../lib/logging.js';
|
|
4
5
|
import { Flags } from '../properties/flags.js';
|
|
5
6
|
import { Property } from '../properties/property.js';
|
|
@@ -383,6 +384,8 @@ export class DimStyle {
|
|
|
383
384
|
|
|
384
385
|
// DXF Groupcode 340 - (handle of referenced STYLE)
|
|
385
386
|
this.DIMTXSTY = Property.loadValue([data.DIMTXSTY, data[340]], 'Standard');
|
|
387
|
+
// internal - true when DIMTXSTY holds a style handle (loaded from group 340) rather than a style name
|
|
388
|
+
this.DIMTXSTYISHANDLE = Property.loadValue([data.DIMTXSTYISHANDLE, data.DIMTXSTY === undefined && data[340] !== undefined], false);
|
|
386
389
|
|
|
387
390
|
// DXF Groupcode 341 - (handle of referenced BLOCK)
|
|
388
391
|
this.DIMLDRBLK = Property.loadValue([data.DIMLDRBLK, data[341]], 'ClosedFilled');
|
|
@@ -475,6 +478,9 @@ export class DimStyle {
|
|
|
475
478
|
|
|
476
479
|
if (this.hasOwnProperty(valueName)) {
|
|
477
480
|
this[valueName] = value;
|
|
481
|
+
if (valueName === 'DIMTXSTY') {
|
|
482
|
+
this.DIMTXSTYISHANDLE = false;
|
|
483
|
+
}
|
|
478
484
|
} else {
|
|
479
485
|
const err = `Setting Value - Property does not exist: ${valueName}`;
|
|
480
486
|
Logging.instance.warn(`${this.type} - ${err}`);
|
|
@@ -544,6 +550,23 @@ export class DimStyle {
|
|
|
544
550
|
this.DIMCENVALUE = Math.abs(value);
|
|
545
551
|
}
|
|
546
552
|
|
|
553
|
+
/**
|
|
554
|
+
* Get the handle of the text style referenced by DIMTXSTY
|
|
555
|
+
* DIMTXSTY holds a style name, or a style handle when DIMTXSTYISHANDLE is set (loaded from a dxf file)
|
|
556
|
+
* @return {string} handle or undefined if no matching style exists
|
|
557
|
+
*/
|
|
558
|
+
getTextStyleHandle() {
|
|
559
|
+
const styles = DesignCore.StyleManager.getItems();
|
|
560
|
+
const reference = String(this.DIMTXSTY).toUpperCase();
|
|
561
|
+
|
|
562
|
+
const style = styles.find((item) => this.DIMTXSTYISHANDLE ?
|
|
563
|
+
String(item.handle).toUpperCase() === reference :
|
|
564
|
+
item.name.toUpperCase() === reference) ??
|
|
565
|
+
styles.find((item) => item.name.toUpperCase() === 'STANDARD');
|
|
566
|
+
|
|
567
|
+
return style?.handle;
|
|
568
|
+
}
|
|
569
|
+
|
|
547
570
|
/**
|
|
548
571
|
* Write the entity to file in the dxf format
|
|
549
572
|
* @param {DXFFile} file
|
|
@@ -616,8 +639,15 @@ export class DimStyle {
|
|
|
616
639
|
file.writeGroupCode('287', this.DIMFIT);
|
|
617
640
|
file.writeGroupCode('288', this.DIMUPT, DXFFile.Version.R13);
|
|
618
641
|
file.writeGroupCode('289', this.DIMATFIT, DXFFile.Version.R2000);
|
|
619
|
-
|
|
620
|
-
|
|
642
|
+
// 340 and 341 are handles - writing a name leaves AutoCAD unable to resolve the text style (dimension text is not shown)
|
|
643
|
+
const textStyleHandle = this.getTextStyleHandle();
|
|
644
|
+
if (textStyleHandle !== undefined) {
|
|
645
|
+
file.writeGroupCode('340', textStyleHandle, DXFFile.Version.R13);
|
|
646
|
+
}
|
|
647
|
+
// 'ClosedFilled' is the default leader arrowhead and has no block handle, omitting the group selects it
|
|
648
|
+
if (this.DIMLDRBLK !== 'ClosedFilled') {
|
|
649
|
+
file.writeGroupCode('341', this.DIMLDRBLK, DXFFile.Version.R2000);
|
|
650
|
+
}
|
|
621
651
|
// file.writeGroupCode('342', this.DIMBLK);
|
|
622
652
|
// file.writeGroupCode('343', this.DIMBLK1);
|
|
623
653
|
// file.writeGroupCode('344', this.DIMBLK2);
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Tool } from './tool.js';
|
|
2
|
+
import { Strings } from '../lib/strings.js';
|
|
3
|
+
import { Input } from '../lib/input.js';
|
|
4
|
+
import { PromptOptions } from '../lib/promptOptions.js';
|
|
5
|
+
import { Logging } from '../lib/logging.js';
|
|
6
|
+
import { UpdateState } from '../lib/stateManager.js';
|
|
7
|
+
|
|
8
|
+
import { DesignCore } from '../designCore.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* GripStretch Command Class
|
|
12
|
+
* Not shown in any toolbar and never started via the command line - only InputManager creates it.
|
|
13
|
+
* @extends Tool
|
|
14
|
+
*/
|
|
15
|
+
export class GripStretch extends Tool {
|
|
16
|
+
static type = 'GripStretch';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create a GripStretch command
|
|
20
|
+
* @param {number} entityIndex - index of the entity in the selection set that owns the grip
|
|
21
|
+
* @param {Object} grip - { point, apply } descriptor returned by Entity.getGrips()
|
|
22
|
+
*/
|
|
23
|
+
constructor(entityIndex, grip) {
|
|
24
|
+
super();
|
|
25
|
+
this.entityIndex = entityIndex;
|
|
26
|
+
this.grip = grip;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Execute method
|
|
31
|
+
* requests the stretch point, then commits it - keeping the entity selected afterwards
|
|
32
|
+
* (with its grips still visible), unlike most commands which deselect on completion
|
|
33
|
+
*/
|
|
34
|
+
async execute() {
|
|
35
|
+
try {
|
|
36
|
+
const op = new PromptOptions(Strings.Input.STRETCHPOINT, [Input.Type.POINT]);
|
|
37
|
+
const newPoint = await DesignCore.Scene.inputManager.requestInput(op);
|
|
38
|
+
if (newPoint === undefined) return;
|
|
39
|
+
this.points.push(newPoint);
|
|
40
|
+
|
|
41
|
+
const inputManager = DesignCore.Scene.inputManager;
|
|
42
|
+
inputManager.actionCommand();
|
|
43
|
+
|
|
44
|
+
// finish without the standard executeCommand()/reset() combo, which would deselect the
|
|
45
|
+
// entity via Scene.reset() - grip editing must leave it selected (grips still visible)
|
|
46
|
+
inputManager.activeCommand = undefined;
|
|
47
|
+
inputManager.promptOption = undefined;
|
|
48
|
+
// reset() normally clears this - without it the next command's first point (or the next
|
|
49
|
+
// grip drag's tracking line) would stay anchored to this drop, not start fresh
|
|
50
|
+
inputManager.inputPoint = null;
|
|
51
|
+
DesignCore.CommandLine.resetPrompt();
|
|
52
|
+
DesignCore.Scene.selectionManager.reloadSelectedEntities();
|
|
53
|
+
DesignCore.Canvas.requestPaint();
|
|
54
|
+
} catch (err) {
|
|
55
|
+
Logging.instance.error(`${this.type} - ${err}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Preview the live grip position while dragging
|
|
61
|
+
*/
|
|
62
|
+
preview() {
|
|
63
|
+
const newPoints = this.grip.apply(DesignCore.Mouse.pointOnScene());
|
|
64
|
+
const previewIndex = DesignCore.Scene.selectionManager.selectionSet.selectionSet.indexOf(this.entityIndex);
|
|
65
|
+
if (previewIndex !== -1) {
|
|
66
|
+
DesignCore.Scene.selectionManager.selectedEntities[previewIndex].setProperty('points', newPoints);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Perform the command - commits the grip's new (dropped) position
|
|
72
|
+
*/
|
|
73
|
+
action() {
|
|
74
|
+
const entity = DesignCore.Scene.entities.get(this.entityIndex);
|
|
75
|
+
const newPoints = this.grip.apply(this.points[0]);
|
|
76
|
+
const properties = { points: newPoints };
|
|
77
|
+
// all grips currently implemented reposition dimension text - record the flag
|
|
78
|
+
// explicitly so its pre-drag value is captured by the UpdateState undo snapshot too
|
|
79
|
+
if (entity.dimType) {
|
|
80
|
+
properties.userPositionedText = true;
|
|
81
|
+
}
|
|
82
|
+
DesignCore.Scene.commit([new UpdateState(entity, properties)]);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Cancel the in-progress stretch - unlike Tool's default (full reset), this must not deselect
|
|
87
|
+
* the entity, and must resolve the suspended execute()'s pending requestInput() promise so it
|
|
88
|
+
* doesn't stay forever awaiting a prompt nobody can respond to or cancel again
|
|
89
|
+
*/
|
|
90
|
+
cancel() {
|
|
91
|
+
const inputManager = DesignCore.Scene.inputManager;
|
|
92
|
+
inputManager.promptOption?.cancel();
|
|
93
|
+
inputManager.promptOption = undefined;
|
|
94
|
+
inputManager.activeCommand = undefined;
|
|
95
|
+
DesignCore.Scene.selectionManager.reloadSelectedEntities();
|
|
96
|
+
}
|
|
97
|
+
}
|
package/core/tools/offset.js
CHANGED
|
@@ -151,7 +151,13 @@ export class Offset extends Tool {
|
|
|
151
151
|
const isClosed = polyPts.length >= 3 && polyPts[0].isSame(polyPts.at(-1));
|
|
152
152
|
const points = isClosed ? polyPts.slice(0, -1) : polyPts;
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
const offsetPoints = this.getOffsetPolylinePoints(points, isClosed, sidePoint, distance);
|
|
155
|
+
if (offsetPoints && isClosed) {
|
|
156
|
+
// restore the closing point so closed entities (e.g. Circle) are rebuilt as closed, not as an Arc
|
|
157
|
+
offsetPoints.push(new Point(offsetPoints[0].x, offsetPoints[0].y));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return offsetPoints;
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
/**
|
package/core/tools/tool.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { DesignCore } from '../designCore.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Tool Class
|
|
3
5
|
*/
|
|
@@ -28,5 +30,13 @@ export class Tool {
|
|
|
28
30
|
action() {
|
|
29
31
|
// action function to be overridden by implementation
|
|
30
32
|
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Cancel this command while it is active - overridden by implementations that need to
|
|
36
|
+
* clean up differently to the default full reset (e.g. GripStretch, which must not deselect)
|
|
37
|
+
*/
|
|
38
|
+
cancel() {
|
|
39
|
+
DesignCore.Scene.inputManager.reset();
|
|
40
|
+
};
|
|
31
41
|
}
|
|
32
42
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Tool } from './tool.js';
|
|
2
|
+
import { Input, PromptOptions } from '../lib/inputManager.js';
|
|
3
|
+
import { Strings } from '../lib/strings.js';
|
|
4
|
+
import { Logging } from '../lib/logging.js';
|
|
5
|
+
import { Point } from '../entities/point.js';
|
|
6
|
+
|
|
7
|
+
import { DesignCore } from '../designCore.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* WindowPick Command Class
|
|
11
|
+
* Internal tool used to interactively pick two corner points defining a rectangular window (e.g. for the plot window area).
|
|
12
|
+
* Not shown in any toolbar; invoked programmatically.
|
|
13
|
+
* @extends Tool
|
|
14
|
+
*/
|
|
15
|
+
export class WindowPick extends Tool {
|
|
16
|
+
static type = 'WindowPick';
|
|
17
|
+
|
|
18
|
+
/** Create a WindowPick command */
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Register the command
|
|
25
|
+
* @return {Object}
|
|
26
|
+
* command = name of the command
|
|
27
|
+
*/
|
|
28
|
+
static register() {
|
|
29
|
+
const command = { command: 'WindowPick' };
|
|
30
|
+
return command;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Execute method
|
|
35
|
+
* requests the two corner points defining the plot window
|
|
36
|
+
*/
|
|
37
|
+
async execute() {
|
|
38
|
+
try {
|
|
39
|
+
const op1 = new PromptOptions(Strings.Input.FIRSTCORNER, [Input.Type.POINT]);
|
|
40
|
+
const pt1 = await DesignCore.Scene.inputManager.requestInput(op1);
|
|
41
|
+
if (pt1 === undefined) return;
|
|
42
|
+
this.points.push(pt1);
|
|
43
|
+
|
|
44
|
+
const op2 = new PromptOptions(Strings.Input.SECONDCORNER, [Input.Type.POINT]);
|
|
45
|
+
const pt2 = await DesignCore.Scene.inputManager.requestInput(op2);
|
|
46
|
+
if (pt2 === undefined) return;
|
|
47
|
+
this.points.push(pt2);
|
|
48
|
+
|
|
49
|
+
DesignCore.Scene.inputManager.executeCommand();
|
|
50
|
+
} catch (err) {
|
|
51
|
+
Logging.instance.error(`${this.type} - ${err}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Preview the command during execution
|
|
57
|
+
*/
|
|
58
|
+
preview() {
|
|
59
|
+
if (this.points.length === 1) {
|
|
60
|
+
const mousePoint = DesignCore.Mouse.pointOnScene();
|
|
61
|
+
const p1 = this.points[0];
|
|
62
|
+
const p2 = mousePoint;
|
|
63
|
+
|
|
64
|
+
const points = [
|
|
65
|
+
new Point(p1.x, p1.y),
|
|
66
|
+
new Point(p2.x, p1.y),
|
|
67
|
+
new Point(p2.x, p2.y),
|
|
68
|
+
new Point(p1.x, p2.y),
|
|
69
|
+
new Point(p1.x, p1.y),
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
DesignCore.Scene.previewEntities.create('Polyline', { points: points });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
package/cspell.json
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"dimstyles",
|
|
46
46
|
"dimline",
|
|
47
47
|
"DIMENSIONSTYLE",
|
|
48
|
+
"USERPOSITIONEDTEXT",
|
|
48
49
|
"DIMADEC",
|
|
49
50
|
"DIMALI",
|
|
50
51
|
"DIMALT",
|
|
@@ -127,6 +128,7 @@
|
|
|
127
128
|
"DIMTSZ",
|
|
128
129
|
"DIMTVP",
|
|
129
130
|
"DIMTXSTY",
|
|
131
|
+
"DIMTXSTYISHANDLE",
|
|
130
132
|
"DIMTXT",
|
|
131
133
|
"DIMTXTDIRECTION",
|
|
132
134
|
"DIMTZIN",
|
|
@@ -195,7 +197,9 @@
|
|
|
195
197
|
"RRGGBB",
|
|
196
198
|
"rubberbandcolour",
|
|
197
199
|
"SCALEFACTOR",
|
|
200
|
+
"SECONDCORNER",
|
|
198
201
|
"selectedchild",
|
|
202
|
+
"STRETCHPOINT",
|
|
199
203
|
"SELECTIONSET",
|
|
200
204
|
"SEQEND",
|
|
201
205
|
"SINGLESELECTION",
|
|
@@ -277,6 +281,7 @@
|
|
|
277
281
|
"INVALIDFILE",
|
|
278
282
|
"INVALIDGROUPCODE",
|
|
279
283
|
"INVALIDINTERSECTTYPE",
|
|
284
|
+
"FIRSTCORNER",
|
|
280
285
|
"INVALIDNUMBER",
|
|
281
286
|
"INVALIDPOINT",
|
|
282
287
|
"INVALIDTYPE",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@design-core/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "52.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
|
|
@@ -19,7 +19,12 @@
|
|
|
19
19
|
".": "./core/core/core.js",
|
|
20
20
|
"./designCore.js": "./core/designCore.js",
|
|
21
21
|
"./property.js": "./core/properties/property.js",
|
|
22
|
-
"./canvasRenderer.js": "./core/lib/renderers/canvasRenderer.js"
|
|
22
|
+
"./canvasRenderer.js": "./core/lib/renderers/canvasRenderer.js",
|
|
23
|
+
"./constants.js": "./core/lib/constants.js",
|
|
24
|
+
"./plotOptions.js": "./core/lib/plotOptions.js",
|
|
25
|
+
"./rendererBase.js": "./core/lib/renderers/rendererBase.js",
|
|
26
|
+
"./svgRenderer.js": "./core/lib/renderers/svgRenderer.js",
|
|
27
|
+
"./pdfRenderer.js": "./core/lib/renderers/pdfRenderer.js"
|
|
23
28
|
},
|
|
24
29
|
"directories": {
|
|
25
30
|
"test": "test"
|