@design-core/core 0.0.7 → 50.1.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/DesignCoreQA.yml +3 -0
- package/core/designCore.js +1 -1
- package/core/dimensions/alignedDimension.js +7 -7
- package/core/dimensions/angularDimension.js +32 -32
- package/core/dimensions/{baseCircularDimension.js → circularDimensionBase.js} +19 -19
- package/core/dimensions/diametricDimension.js +10 -10
- package/core/dimensions/dimension.js +42 -42
- package/core/dimensions/{baseDimension.js → dimensionBase.js} +17 -17
- package/core/dimensions/{baseLinearDimension.js → linearDimensionBase.js} +9 -9
- package/core/dimensions/radialDimension.js +8 -8
- package/core/dimensions/rotatedDimension.js +8 -8
- package/core/entities/arc.js +22 -22
- package/core/entities/arctext.js +13 -13
- package/core/entities/circle.js +7 -7
- package/core/entities/hatch.js +28 -28
- package/core/entities/insert.js +5 -5
- package/core/entities/point.js +19 -19
- package/core/entities/polyline.js +3 -3
- package/core/entities/{basePolyline.js → polylineBase.js} +18 -18
- package/core/entities/text.js +4 -4
- package/core/lib/boundingBox.js +11 -11
- package/core/lib/canvas.js +6 -4
- package/core/lib/clipboard.js +2 -2
- package/core/lib/dxf/dxf.js +11 -11
- package/core/lib/dxf/dxfIterator.js +2 -2
- package/core/lib/entityManager.js +19 -19
- package/core/lib/inputManager.js +1 -1
- package/core/lib/matrix.js +1 -1
- package/core/lib/patterns.js +1 -1
- package/core/lib/polylineUtils.js +9 -9
- package/core/lib/renderers/cairoRenderer.js +5 -5
- package/core/lib/renderers/canvasRenderer.js +4 -4
- package/core/lib/renderers/pdfRenderer.js +7 -7
- package/core/lib/renderers/rendererBase.js +1 -1
- package/core/lib/scene.js +1 -1
- package/core/lib/selectionManager.js +18 -18
- package/core/lib/utils.js +5 -5
- package/core/properties/property.js +1 -1
- package/core/properties/propertyManager.js +37 -37
- package/core/tables/block.js +48 -46
- package/core/tables/dimStyle.js +5 -5
- package/core/tables/ltypeManager.js +1 -1
- package/core/tables/vport.js +2 -2
- package/core/tools/chamfer.js +6 -6
- package/core/tools/chamferFilletBase.js +4 -4
- package/core/tools/copy.js +8 -8
- package/core/tools/copybase.js +3 -3
- package/core/tools/copyclip.js +3 -3
- package/core/tools/cornerEntity.js +2 -2
- package/core/tools/cutclip.js +3 -3
- package/core/tools/explode.js +6 -6
- package/core/tools/extend.js +13 -13
- package/core/tools/fillet.js +6 -6
- package/core/tools/matchProp.js +1 -1
- package/core/tools/mirror.js +11 -11
- package/core/tools/move.js +5 -5
- package/core/tools/offset.js +29 -29
- package/core/tools/purge.js +10 -10
- package/core/tools/rotate.js +16 -16
- package/core/tools/scale.js +6 -6
- package/core/tools/trim.js +15 -15
- package/cspell.json +321 -0
- package/package.json +1 -1
- package/test/dimensions/alignedDimension.test.js +3 -3
- package/test/dimensions/angularDimension.test.js +7 -7
- package/test/dimensions/diametricDimension.test.js +9 -9
- package/test/dimensions/dimension.test.js +12 -12
- package/test/dimensions/{baseDimension.test.js → dimensionBase.test.js} +12 -12
- package/test/dimensions/{baseLinearDimension.test.js → linearDimensionBase.test.js} +7 -7
- package/test/dimensions/radialDimension.test.js +9 -9
- package/test/dimensions/rotatedDimension.test.js +4 -4
- package/test/entities/arc.test.js +10 -10
- package/test/entities/arctext.test.js +6 -6
- package/test/entities/circle.test.js +18 -18
- package/test/entities/hatch.test.js +39 -39
- package/test/entities/insert.test.js +9 -9
- package/test/entities/point.test.js +3 -3
- package/test/entities/{basePolyline.test.js → polylineBase.test.js} +131 -62
- package/test/entities/text.test.js +19 -19
- package/test/integration/exportIntegration.test.js +3 -3
- package/test/integration/userInputIntegration.test.js +5 -5
- package/test/lib/boundingBox.test.js +3 -3
- package/test/lib/canvas.test.js +9 -9
- package/test/lib/inputManager.test.js +4 -4
- package/test/lib/scene.test.js +9 -9
- package/test/lib/selectionManager.test.js +3 -3
- package/test/lib/snapping.test.js +1 -1
- package/test/properties/propertyManager.test.js +22 -22
- package/test/renderers/pdfRenderer.test.js +2 -2
- package/test/tables/block.test.js +63 -14
- package/test/tables/layerManager.test.js +2 -2
- package/test/test-helpers/hatchGridRenderer.js +3 -3
- package/test/test-helpers/test-helpers.js +6 -6
- package/test/tools/chamfer.test.js +60 -60
- package/test/tools/chamferFilletBase.test.js +36 -36
- package/test/tools/copy.test.js +6 -6
- package/test/tools/copybase.test.js +2 -2
- package/test/tools/copyclip.test.js +2 -2
- package/test/tools/cornerEntity.test.js +8 -8
- package/test/tools/cutclip.test.js +2 -2
- package/test/tools/erase.test.js +6 -6
- package/test/tools/explode.test.js +2 -2
- package/test/tools/extend.test.js +84 -84
- package/test/tools/fillet.test.js +62 -62
- package/test/tools/matchProp.test.js +6 -6
- package/test/tools/mirror.test.js +26 -26
- package/test/tools/move.test.js +7 -7
- package/test/tools/offset.test.js +65 -65
- package/test/tools/purge.test.js +4 -4
- package/test/tools/rotate.test.js +10 -10
- package/test/tools/scale.test.js +28 -28
- package/test/tools/trim.test.js +109 -109
- package/test/tools/zoom.test.js +5 -5
|
@@ -11,7 +11,7 @@ import { Lwpolyline } from '../../core/entities/lwpolyline.js';
|
|
|
11
11
|
import { Hatch } from '../../core/entities/hatch.js';
|
|
12
12
|
import { Insert } from '../../core/entities/insert.js';
|
|
13
13
|
// import { ArcAlignedText } from '../../core/entities/arctext.js';
|
|
14
|
-
import {
|
|
14
|
+
import { PolylineBase } from '../../core/entities/polylineBase.js';
|
|
15
15
|
|
|
16
16
|
import { readFileSync } from 'fs';
|
|
17
17
|
import { fileURLToPath } from 'url';
|
|
@@ -106,7 +106,7 @@ beforeAll(() => {
|
|
|
106
106
|
// core.scene.entities.add(new Text({ points: [new Point(15, 205)], string: 'Solid', height: 4 }));
|
|
107
107
|
|
|
108
108
|
// Row 2, Col 0: Hatch
|
|
109
|
-
const boundary = new
|
|
109
|
+
const boundary = new PolylineBase({
|
|
110
110
|
points: [new Point(25, 230), new Point(75, 230), new Point(75, 280), new Point(25, 280)],
|
|
111
111
|
});
|
|
112
112
|
const hatch = new Hatch({
|
|
@@ -122,7 +122,7 @@ beforeAll(() => {
|
|
|
122
122
|
blockLine.setProperty('handle', DesignCore.HandleManager.next());
|
|
123
123
|
const block = DesignCore.Scene.blockManager.addItem({
|
|
124
124
|
name: 'TEST_BLOCK',
|
|
125
|
-
|
|
125
|
+
entities: [blockLine],
|
|
126
126
|
});
|
|
127
127
|
const insert = new Insert({
|
|
128
128
|
points: [new Point(130, 235)],
|
|
@@ -106,13 +106,13 @@ beforeAll(async () => {
|
|
|
106
106
|
new Point(90, 50),
|
|
107
107
|
]);
|
|
108
108
|
|
|
109
|
-
// col 1, row 0 — Circle,
|
|
109
|
+
// col 1, row 0 — Circle, centre (250,50) r=30 → idx 1
|
|
110
110
|
await executeWithInputs(new Circle(), [
|
|
111
111
|
new Point(250, 50),
|
|
112
112
|
30,
|
|
113
113
|
]);
|
|
114
114
|
|
|
115
|
-
// col 2, row 0 — Arc,
|
|
115
|
+
// col 2, row 0 — Arc, centre (450,50), start (480,50), 270° CCW → idx 2
|
|
116
116
|
await executeWithInputs(new Arc(), [
|
|
117
117
|
new Point(450, 50),
|
|
118
118
|
new Point(480, 50),
|
|
@@ -149,10 +149,10 @@ beforeAll(async () => {
|
|
|
149
149
|
// col 0, row 1 — Hatch using the rectangle boundary (idx 6) → idx 7
|
|
150
150
|
{
|
|
151
151
|
const hatchBoundary = DesignCore.Scene.entities.get(6);
|
|
152
|
-
const
|
|
153
|
-
DesignCore.Scene.selectionManager.
|
|
152
|
+
const origSelectedEntities = DesignCore.Scene.selectionManager.selectedEntities;
|
|
153
|
+
DesignCore.Scene.selectionManager.selectedEntities = [hatchBoundary];
|
|
154
154
|
await executeWithInputs(new Hatch(), ['accept']);
|
|
155
|
-
DesignCore.Scene.selectionManager.
|
|
155
|
+
DesignCore.Scene.selectionManager.selectedEntities = origSelectedEntities;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
// col 1, row 1 — Arc for ArcAlignedText, in its own cell → idx 8
|
|
@@ -29,9 +29,9 @@ test('Test BoundingBox.yLength', () => {
|
|
|
29
29
|
expect(bb.yLength).toBe(100);
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
test('Test BoundingBox.
|
|
33
|
-
expect(bb.
|
|
34
|
-
expect(bb.
|
|
32
|
+
test('Test BoundingBox.centrePoint', () => {
|
|
33
|
+
expect(bb.centrePoint.x).toBe(151);
|
|
34
|
+
expect(bb.centrePoint.y).toBe(152);
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
test('Test BoundingBox.isInside', () => {
|
package/test/lib/canvas.test.js
CHANGED
|
@@ -169,7 +169,7 @@ test('Test Canvas.getSceneOffset returns extents', () => {
|
|
|
169
169
|
});
|
|
170
170
|
|
|
171
171
|
test('Test Canvas.zoomExtents with entities', () => {
|
|
172
|
-
core.scene.
|
|
172
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(500, 500)] });
|
|
173
173
|
canvas.matrix = new Matrix();
|
|
174
174
|
canvas.width = 800;
|
|
175
175
|
canvas.height = 600;
|
|
@@ -496,7 +496,7 @@ test('Test Canvas.doubleClick left and right buttons do not throw', () => {
|
|
|
496
496
|
test('Test Canvas.doubleClick middle button triggers zoomExtents', () => {
|
|
497
497
|
const testCore = new Core();
|
|
498
498
|
testCore.activate();
|
|
499
|
-
testCore.scene.
|
|
499
|
+
testCore.scene.addEntity('Line', { points: [new Point(0, 0), new Point(500, 500)] });
|
|
500
500
|
testCore.canvas.width = 800;
|
|
501
501
|
testCore.canvas.height = 600;
|
|
502
502
|
testCore.canvas.matrix = new Matrix();
|
|
@@ -1138,13 +1138,13 @@ describe('Canvas.exportTo', () => {
|
|
|
1138
1138
|
});
|
|
1139
1139
|
|
|
1140
1140
|
test('returns true when scene has entities', () => {
|
|
1141
|
-
exportCore.scene.
|
|
1141
|
+
exportCore.scene.addEntity('Line', { points: [new Point(0, 0), new Point(100, 100)] });
|
|
1142
1142
|
const options = new PlotOptions(595, 842);
|
|
1143
1143
|
expect(exportCanvas.exportTo(renderer, options)).toBe(true);
|
|
1144
1144
|
});
|
|
1145
1145
|
|
|
1146
1146
|
test('calls renderer.setTransform with a valid matrix', () => {
|
|
1147
|
-
exportCore.scene.
|
|
1147
|
+
exportCore.scene.addEntity('Line', { points: [new Point(0, 0), new Point(100, 100)] });
|
|
1148
1148
|
let receivedMatrix;
|
|
1149
1149
|
renderer.setTransform = (m) => {
|
|
1150
1150
|
receivedMatrix = m;
|
|
@@ -1157,7 +1157,7 @@ describe('Canvas.exportTo', () => {
|
|
|
1157
1157
|
});
|
|
1158
1158
|
|
|
1159
1159
|
test('calls renderer.setBackgroundColour with white', () => {
|
|
1160
|
-
exportCore.scene.
|
|
1160
|
+
exportCore.scene.addEntity('Line', { points: [new Point(0, 0), new Point(100, 100)] });
|
|
1161
1161
|
let bgColour;
|
|
1162
1162
|
renderer.setBackgroundColour = (c) => {
|
|
1163
1163
|
bgColour = c;
|
|
@@ -1168,7 +1168,7 @@ describe('Canvas.exportTo', () => {
|
|
|
1168
1168
|
});
|
|
1169
1169
|
|
|
1170
1170
|
test('calls renderer.setStyle with the plotOptions style', () => {
|
|
1171
|
-
exportCore.scene.
|
|
1171
|
+
exportCore.scene.addEntity('Line', { points: [new Point(0, 0), new Point(100, 100)] });
|
|
1172
1172
|
const options = new PlotOptions(595, 842);
|
|
1173
1173
|
const spyCalls = [];
|
|
1174
1174
|
renderer.setStyle = (fn) => {
|
|
@@ -1179,7 +1179,7 @@ describe('Canvas.exportTo', () => {
|
|
|
1179
1179
|
});
|
|
1180
1180
|
|
|
1181
1181
|
test('EXTENTS uses Scene.boundingBox regardless of viewport', () => {
|
|
1182
|
-
exportCore.scene.
|
|
1182
|
+
exportCore.scene.addEntity('Line', { points: [new Point(0, 0), new Point(500, 500)] });
|
|
1183
1183
|
// Pan far away so viewport does not contain the entity
|
|
1184
1184
|
exportCanvas.matrix.translate(-10000, -10000);
|
|
1185
1185
|
let receivedMatrix;
|
|
@@ -1195,7 +1195,7 @@ describe('Canvas.exportTo', () => {
|
|
|
1195
1195
|
});
|
|
1196
1196
|
|
|
1197
1197
|
test('DISPLAY uses current viewport instead of entity extents', () => {
|
|
1198
|
-
exportCore.scene.
|
|
1198
|
+
exportCore.scene.addEntity('Line', { points: [new Point(0, 0), new Point(500, 500)] });
|
|
1199
1199
|
let extentsMatrix;
|
|
1200
1200
|
let displayMatrix;
|
|
1201
1201
|
|
|
@@ -1222,7 +1222,7 @@ describe('Canvas.exportTo', () => {
|
|
|
1222
1222
|
});
|
|
1223
1223
|
|
|
1224
1224
|
test('explicit plotScale is forwarded to buildExportMatrix', () => {
|
|
1225
|
-
exportCore.scene.
|
|
1225
|
+
exportCore.scene.addEntity('Line', { points: [new Point(0, 0), new Point(100, 100)] });
|
|
1226
1226
|
let receivedMatrix;
|
|
1227
1227
|
renderer.setTransform = (m) => {
|
|
1228
1228
|
receivedMatrix = m;
|
|
@@ -241,7 +241,7 @@ test('onCommandButton with no active command - starts command', () => {
|
|
|
241
241
|
|
|
242
242
|
test('starting an entity command from idle clears the selection', () => {
|
|
243
243
|
inputManager.reset();
|
|
244
|
-
core.scene.
|
|
244
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
245
245
|
core.scene.selectionManager.addToSelectionSet(0);
|
|
246
246
|
expect(core.scene.selectionManager.selectionSet.selectionSet.length).toBe(1);
|
|
247
247
|
|
|
@@ -252,7 +252,7 @@ test('starting an entity command from idle clears the selection', () => {
|
|
|
252
252
|
|
|
253
253
|
test('starting a tool command from idle preserves the selection', () => {
|
|
254
254
|
inputManager.reset();
|
|
255
|
-
core.scene.
|
|
255
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
256
256
|
core.scene.selectionManager.addToSelectionSet(0);
|
|
257
257
|
expect(core.scene.selectionManager.selectionSet.selectionSet.length).toBe(1);
|
|
258
258
|
|
|
@@ -388,7 +388,7 @@ test('onLeftClick with POINT prompt and no nearby entity - responds with the giv
|
|
|
388
388
|
|
|
389
389
|
test('onLeftClick with entity found and no active command - delegates to onSelection', () => {
|
|
390
390
|
inputManager.reset();
|
|
391
|
-
const mockSelection = {
|
|
391
|
+
const mockSelection = { selectedEntityIndex: 0 };
|
|
392
392
|
jest.spyOn(core.scene.selectionManager, 'findClosestItem').mockReturnValue(0);
|
|
393
393
|
jest.spyOn(core.scene.selectionManager, 'singleSelect').mockReturnValue(mockSelection);
|
|
394
394
|
const onSelectionSpy = jest.spyOn(inputManager, 'onSelection').mockImplementation(() => {});
|
|
@@ -1183,7 +1183,7 @@ test('highlightEntityUnderMouse returns false when buttonThreeDown is true', ()
|
|
|
1183
1183
|
|
|
1184
1184
|
test('refreshPreview clears hoverEntities in addition to previewEntities and auxiliaryEntities', () => {
|
|
1185
1185
|
core.scene.clear();
|
|
1186
|
-
core.scene.
|
|
1186
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
1187
1187
|
|
|
1188
1188
|
// Simulate a stale hover glow left by the previous mouseMoved()
|
|
1189
1189
|
DesignCore.Scene.hoverEntities.add(core.scene.entities.get(0));
|
package/test/lib/scene.test.js
CHANGED
|
@@ -11,16 +11,16 @@ test('Test Scene.boundingBox', () => {
|
|
|
11
11
|
expect(scene.boundingBox()).toBeUndefined();
|
|
12
12
|
|
|
13
13
|
const line1 = new Line({ points: [new Point(-102, -102), new Point(201, 202)] });
|
|
14
|
-
// add to scene
|
|
15
|
-
scene.
|
|
14
|
+
// add to scene
|
|
15
|
+
scene.addEntity('Line', line1);
|
|
16
16
|
expect(scene.boundingBox().xMin).toBeCloseTo(-102);
|
|
17
17
|
expect(scene.boundingBox().xMax).toBeCloseTo(201);
|
|
18
18
|
expect(scene.boundingBox().yMin).toBeCloseTo(-102);
|
|
19
19
|
expect(scene.boundingBox().yMax).toBeCloseTo(202);
|
|
20
20
|
|
|
21
21
|
const line2 = new Line({ points: [new Point(1001, -2002), new Point(-2001, 2002)] });
|
|
22
|
-
// add to scene
|
|
23
|
-
scene.
|
|
22
|
+
// add to scene
|
|
23
|
+
scene.addEntity('Line', line2);
|
|
24
24
|
expect(scene.boundingBox().xMin).toBeCloseTo(-2001);
|
|
25
25
|
expect(scene.boundingBox().xMax).toBeCloseTo(1001);
|
|
26
26
|
expect(scene.boundingBox().yMin).toBeCloseTo(-2002);
|
|
@@ -28,26 +28,26 @@ test('Test Scene.boundingBox', () => {
|
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
test('Test Scene.
|
|
31
|
+
test('Test Scene.addEntity', () => {
|
|
32
32
|
// Throw error on missing data
|
|
33
33
|
expect(() => {
|
|
34
|
-
scene.
|
|
34
|
+
scene.addEntity('Line');
|
|
35
35
|
}).toThrow();
|
|
36
36
|
|
|
37
37
|
// Add a invalid item type
|
|
38
38
|
const itemCnt = scene.entities.count();
|
|
39
|
-
const returnIndex = scene.
|
|
39
|
+
const returnIndex = scene.addEntity('FakeItem', {});
|
|
40
40
|
expect(scene.entities.count()).toBe(itemCnt);
|
|
41
41
|
expect(returnIndex).toBeUndefined();
|
|
42
42
|
|
|
43
43
|
// Add a valid item with data
|
|
44
44
|
const itemCount = scene.entities.count();
|
|
45
|
-
const index = scene.
|
|
45
|
+
const index = scene.addEntity('Line', { points: [new Point(), new Point(10, 10)] });
|
|
46
46
|
expect(scene.entities.count()).toBe(itemCount + 1);
|
|
47
47
|
expect(index).toBe(itemCount);
|
|
48
48
|
|
|
49
49
|
// Add a valid item with data at index - item count should not increase
|
|
50
|
-
scene.
|
|
50
|
+
scene.addEntity('Line', { points: [new Point(123, 123), new Point(321, 321)] }, index);
|
|
51
51
|
expect(scene.entities.count()).toBe(itemCount + 1);
|
|
52
52
|
// check the items points to make sure index was replaced
|
|
53
53
|
expect(scene.entities.get(index).points[0].x).toBe(123);
|
|
@@ -5,9 +5,9 @@ const core = new Core();
|
|
|
5
5
|
const selectionManager = core.scene.selectionManager;
|
|
6
6
|
|
|
7
7
|
// Add a valid item to scene
|
|
8
|
-
core.scene.
|
|
9
|
-
core.scene.
|
|
10
|
-
core.scene.
|
|
8
|
+
core.scene.addEntity('Line', { points: [new Point(10, 10), new Point(100, 10)] });
|
|
9
|
+
core.scene.addEntity('Line', { points: [new Point(10, 20), new Point(100, 20)] });
|
|
10
|
+
core.scene.addEntity('Circle', { points: [new Point(), new Point(5, 0)] });
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
test('Test SelectionManager.findClosestItem', () => {
|
|
@@ -9,7 +9,7 @@ const core = new Core();
|
|
|
9
9
|
const snapping = new Snapping();
|
|
10
10
|
|
|
11
11
|
// Add a valid item to scene
|
|
12
|
-
core.scene.
|
|
12
|
+
core.scene.addEntity('Line', { points: [new Point(10, 10), new Point(100, 10)] });
|
|
13
13
|
|
|
14
14
|
afterEach(() => {
|
|
15
15
|
// Reset all mouse button states so tests don't affect each other via
|
|
@@ -14,45 +14,45 @@ const data = {
|
|
|
14
14
|
colour: { r: 100, g: 100, b: 100 },
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
DesignCore.Scene.
|
|
18
|
-
DesignCore.Scene.
|
|
19
|
-
DesignCore.Scene.
|
|
17
|
+
DesignCore.Scene.addEntity('Line', data);
|
|
18
|
+
DesignCore.Scene.addEntity('Circle', data);
|
|
19
|
+
DesignCore.Scene.addEntity('Text', data);
|
|
20
20
|
// Add Arc with a different Colour
|
|
21
|
-
DesignCore.Scene.
|
|
21
|
+
DesignCore.Scene.addEntity('Arc', { points: [point1, point2], colour: { r: 130, g: 130, b: 130 } });
|
|
22
22
|
|
|
23
|
-
test('Test propertyManager.
|
|
23
|
+
test('Test propertyManager.getEntityTypes', () => {
|
|
24
24
|
// Add an item to the selectionSet
|
|
25
25
|
DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(0);
|
|
26
|
-
let types = propertiesManager.
|
|
26
|
+
let types = propertiesManager.getEntityTypes();
|
|
27
27
|
expect(types.length).toBe(1);
|
|
28
28
|
|
|
29
29
|
// Add the same item to the selectionSet - shouldn't change the count
|
|
30
30
|
DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(0);
|
|
31
|
-
types = propertiesManager.
|
|
31
|
+
types = propertiesManager.getEntityTypes();
|
|
32
32
|
expect(types.length).toBe(1);
|
|
33
33
|
|
|
34
34
|
// Add a new item to the selectionSet - result should include 'All'
|
|
35
35
|
DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(1);
|
|
36
|
-
types = propertiesManager.
|
|
36
|
+
types = propertiesManager.getEntityTypes();
|
|
37
37
|
expect(types.length).toBe(3);
|
|
38
38
|
expect(types[0]).toBe('All');
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
test('Test propertyManager.
|
|
41
|
+
test('Test propertyManager.setEntityProperties', () => {
|
|
42
42
|
// clear the selection set
|
|
43
43
|
DesignCore.Scene.reset();
|
|
44
44
|
// add the text entity
|
|
45
45
|
DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(2);
|
|
46
46
|
// set the string attribute of the text entity
|
|
47
47
|
const string = 'test text';
|
|
48
|
-
propertiesManager.
|
|
48
|
+
propertiesManager.setEntityProperties('string', string);
|
|
49
49
|
|
|
50
50
|
let text = DesignCore.Scene.entities.get(2);
|
|
51
51
|
expect(text.type).toBe('Text');
|
|
52
52
|
expect(text.getProperty('string')).toBe(string);
|
|
53
53
|
|
|
54
54
|
// try and set a non-existent property
|
|
55
|
-
propertiesManager.
|
|
55
|
+
propertiesManager.setEntityProperties('faux-prop', string);
|
|
56
56
|
text = DesignCore.Scene.entities.get(2);
|
|
57
57
|
expect(text['faux-prop']).toBeUndefined();
|
|
58
58
|
|
|
@@ -63,53 +63,53 @@ test('Test propertyManager.setItemProperties', () => {
|
|
|
63
63
|
// get the current radius
|
|
64
64
|
const radius = DesignCore.Scene.entities.get(1).getProperty('radius');
|
|
65
65
|
// try and set an incorrect value
|
|
66
|
-
propertiesManager.
|
|
66
|
+
propertiesManager.setEntityProperties('radius', string);
|
|
67
67
|
const circle = DesignCore.Scene.entities.get(1);
|
|
68
68
|
expect(circle.getProperty('radius')).toBe(radius);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
test('Test propertyManager.
|
|
71
|
+
test('Test propertyManager.getEntityProperties', () => {
|
|
72
72
|
// clear the selection set
|
|
73
73
|
DesignCore.Scene.reset();
|
|
74
74
|
|
|
75
75
|
// get props with nothing selected - should be undefined
|
|
76
|
-
let properties = propertiesManager.
|
|
76
|
+
let properties = propertiesManager.getEntityProperties();
|
|
77
77
|
expect(properties).toBeUndefined();
|
|
78
78
|
|
|
79
79
|
// Add the line entity to the selectionSet
|
|
80
80
|
DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(0);
|
|
81
|
-
properties = propertiesManager.
|
|
81
|
+
properties = propertiesManager.getEntityProperties('Line');
|
|
82
82
|
expect(properties.length).toBeGreaterThan(0);
|
|
83
83
|
|
|
84
84
|
// check properties for All itemTypes
|
|
85
|
-
properties = propertiesManager.
|
|
85
|
+
properties = propertiesManager.getEntityProperties('All');
|
|
86
86
|
expect(properties.length).toBeGreaterThan(0);
|
|
87
87
|
|
|
88
88
|
// get circle props with a line selected - should be 0
|
|
89
|
-
properties = propertiesManager.
|
|
89
|
+
properties = propertiesManager.getEntityProperties('Circle');
|
|
90
90
|
expect(properties.length).toBe(0);
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
-
test('Test propertyManager.
|
|
93
|
+
test('Test propertyManager.getEntityPropertyValue', () => {
|
|
94
94
|
// clear the selection set
|
|
95
95
|
DesignCore.Scene.reset();
|
|
96
96
|
|
|
97
97
|
// get props with nothing selected - should be undefined
|
|
98
|
-
let propertyValues = propertiesManager.
|
|
98
|
+
let propertyValues = propertiesManager.getEntityPropertyValue();
|
|
99
99
|
expect(propertyValues).toBeUndefined();
|
|
100
100
|
|
|
101
101
|
// Add the line entity to the selectionSet
|
|
102
102
|
DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(0);
|
|
103
103
|
// get the line colour
|
|
104
|
-
propertyValues = propertiesManager.
|
|
104
|
+
propertyValues = propertiesManager.getEntityPropertyValue('Line', 'colour');
|
|
105
105
|
expect(propertyValues).toEqual(data.colour);
|
|
106
106
|
|
|
107
107
|
// get circle props with a line selected - should be undefined
|
|
108
|
-
propertyValues = propertiesManager.
|
|
108
|
+
propertyValues = propertiesManager.getEntityPropertyValue('Circle', 'colour');
|
|
109
109
|
expect(propertyValues).toBeUndefined();
|
|
110
110
|
|
|
111
111
|
// get props for all selected types - index 0 and 3 colour should be Varies
|
|
112
112
|
DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(3);
|
|
113
|
-
propertyValues = propertiesManager.
|
|
113
|
+
propertyValues = propertiesManager.getEntityPropertyValue('All', 'colour');
|
|
114
114
|
expect(propertyValues).toBe('Varies');
|
|
115
115
|
});
|
|
@@ -110,7 +110,7 @@ describe('PdfRenderer — drawing', () => {
|
|
|
110
110
|
|
|
111
111
|
test('90° arc splits into 1 Bézier curve', () => {
|
|
112
112
|
const renderer = new PdfRenderer(100, 100);
|
|
113
|
-
// start=(100,0) bulge=tan(π/8)≈0.4142 → 90° arc, end=(150,50),
|
|
113
|
+
// start=(100,0) bulge=tan(π/8)≈0.4142 → 90° arc, end=(150,50), centre=(100,50), r=50
|
|
114
114
|
const start = new Point(100, 0, Math.tan(Math.PI / 8));
|
|
115
115
|
const end = new Point(150, 50);
|
|
116
116
|
renderer.drawShape([start, end], {});
|
|
@@ -121,7 +121,7 @@ describe('PdfRenderer — drawing', () => {
|
|
|
121
121
|
|
|
122
122
|
test('full circle (two 180° arcs) emits 4 Bézier curves', () => {
|
|
123
123
|
const renderer = new PdfRenderer(100, 100);
|
|
124
|
-
// Circle
|
|
124
|
+
// Circle centre=(50,50) r=50 — mirrors Circle.toPolylinePoints() output
|
|
125
125
|
const p1 = new Point(100, 50, 1);
|
|
126
126
|
const p2 = new Point(0, 50, 1);
|
|
127
127
|
const p3 = new Point(100, 50);
|
|
@@ -9,25 +9,38 @@ import { DesignCore } from '../../core/designCore.js';
|
|
|
9
9
|
import { Utils } from '../../core/lib/utils.js';
|
|
10
10
|
import { DXFFile } from '../../core/lib/dxf/dxfFile.js';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Create a mock requestInput function that returns values from the provided array in order.
|
|
14
|
+
* @param {Array} inputs
|
|
15
|
+
* @return {Function}
|
|
16
|
+
*/
|
|
17
|
+
function mockRequestInput(inputs) {
|
|
18
|
+
let i = 0;
|
|
19
|
+
return async () => {
|
|
20
|
+
if (i < inputs.length) return inputs[i++];
|
|
21
|
+
throw new Error('cancelled');
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
12
25
|
new Core();
|
|
13
26
|
|
|
14
27
|
test('Test Block', () => {
|
|
15
28
|
const line = new Line({ points: [new Point(101, 102), new Point(201, 202)] });
|
|
16
29
|
const flags = new Flags();
|
|
17
30
|
flags.addValue(1);
|
|
18
|
-
const block = new Block({
|
|
31
|
+
const block = new Block({ entities: [line], flags: flags });
|
|
19
32
|
|
|
20
|
-
expect(block.
|
|
33
|
+
expect(block.entities.length).toBe(1);
|
|
21
34
|
expect(block.flags.getFlagValue()).toBe(1);
|
|
22
35
|
});
|
|
23
36
|
|
|
24
37
|
test('Test Block.clearItems', () => {
|
|
25
38
|
const line = new Line({ points: [new Point(101, 102), new Point(201, 202)] });
|
|
26
|
-
const block = new Block({
|
|
27
|
-
expect(block.
|
|
39
|
+
const block = new Block({ entities: [line] });
|
|
40
|
+
expect(block.entities.length).toBe(1);
|
|
28
41
|
|
|
29
|
-
block.
|
|
30
|
-
expect(block.
|
|
42
|
+
block.clearEntities();
|
|
43
|
+
expect(block.entities.length).toBe(0);
|
|
31
44
|
});
|
|
32
45
|
|
|
33
46
|
test('Test Block.snaps', () => {
|
|
@@ -36,7 +49,7 @@ test('Test Block.snaps', () => {
|
|
|
36
49
|
expect(block.snaps()).toHaveLength(0);
|
|
37
50
|
|
|
38
51
|
const line = new Line({ points: [new Point(101, 102), new Point(201, 202)] });
|
|
39
|
-
block.
|
|
52
|
+
block.addEntity(line);
|
|
40
53
|
expect(block.snaps()).toBeInstanceOf(Array);
|
|
41
54
|
expect(block.snaps()).not.toHaveLength(0);
|
|
42
55
|
});
|
|
@@ -45,9 +58,9 @@ test('Test Block', () => {
|
|
|
45
58
|
const line = new Line({ points: [new Point(101, 102), new Point(201, 202)] });
|
|
46
59
|
const flags = new Flags();
|
|
47
60
|
flags.addValue(1);
|
|
48
|
-
const block = new Block({
|
|
61
|
+
const block = new Block({ entities: [line], flags: flags });
|
|
49
62
|
|
|
50
|
-
expect(block.
|
|
63
|
+
expect(block.entities.length).toBe(1);
|
|
51
64
|
expect(block.flags.getFlagValue()).toBe(1);
|
|
52
65
|
});
|
|
53
66
|
|
|
@@ -63,7 +76,7 @@ test('Test Block.closestPoint', () => {
|
|
|
63
76
|
expect(block.closestPoint(point)[1]).toBe(Infinity);
|
|
64
77
|
|
|
65
78
|
const line = new Line({ points: [new Point(101, 102), new Point(201, 202)] });
|
|
66
|
-
block.
|
|
79
|
+
block.addEntity(line);
|
|
67
80
|
expect(block.closestPoint(point)).toBeInstanceOf(Array);
|
|
68
81
|
expect(block.closestPoint(point)).toHaveLength(2);
|
|
69
82
|
expect(block.closestPoint(point)[0]).toBeInstanceOf(Point);
|
|
@@ -75,7 +88,7 @@ test('Test Block.closestPoint', () => {
|
|
|
75
88
|
test('Test Block.dxf', () => {
|
|
76
89
|
const block = new Block({ handle: '1', endblkHandle: '1' });
|
|
77
90
|
const line = new Line({ handle: '1', points: [new Point(101, 102), new Point(201, 202)] });
|
|
78
|
-
block.
|
|
91
|
+
block.addEntity(line);
|
|
79
92
|
|
|
80
93
|
const file = new File();
|
|
81
94
|
block.dxf(file);
|
|
@@ -154,7 +167,7 @@ test('Test Block.touched', () => {
|
|
|
154
167
|
expect(block.touched(selectionExtremesTrue)).toBe(false);
|
|
155
168
|
|
|
156
169
|
const line = new Line({ points: [new Point(101, 102), new Point(201, 202)] });
|
|
157
|
-
block.
|
|
170
|
+
block.addEntity(line);
|
|
158
171
|
expect(block.touched(selectionExtremesTrue)).toBe(true);
|
|
159
172
|
expect(block.touched(selectionExtremesFalse)).toBe(false);
|
|
160
173
|
});
|
|
@@ -165,7 +178,7 @@ test('Test Block.dxf throws when a block item has an undefined handle', () => {
|
|
|
165
178
|
const line = new Line({ handle: '3', points: [new Point(0, 0), new Point(1, 1)] });
|
|
166
179
|
const clone = Utils.cloneObject(line);
|
|
167
180
|
expect(clone.getProperty('handle')).toBeUndefined();
|
|
168
|
-
block.
|
|
181
|
+
block.addEntity(clone);
|
|
169
182
|
|
|
170
183
|
// Use a real DXFFile (R2000+) so the version-gated handle validation fires
|
|
171
184
|
const file = new DXFFile('R2000');
|
|
@@ -179,9 +192,45 @@ test('Test Block.dxf succeeds when block items have valid handles', () => {
|
|
|
179
192
|
// simulate the handle assignment done in Block.execute()
|
|
180
193
|
clone.setProperty('handle', DesignCore.HandleManager.next());
|
|
181
194
|
expect(clone.getProperty('handle')).toMatch(/^[0-9A-F]+$/i);
|
|
182
|
-
block.
|
|
195
|
+
block.addEntity(clone);
|
|
183
196
|
|
|
184
197
|
const file = new DXFFile('R2000');
|
|
185
198
|
expect(() => block.dxf(file)).not.toThrow();
|
|
186
199
|
expect(file.contents).toContain(clone.getProperty('handle'));
|
|
187
200
|
});
|
|
201
|
+
|
|
202
|
+
test('Test Block.execute offsets entity points by the insert point', async () => {
|
|
203
|
+
new Core();
|
|
204
|
+
|
|
205
|
+
// Add a line to the scene at world coordinates (100,200) → (300,400)
|
|
206
|
+
const line = new Line({ points: [new Point(100, 200), new Point(300, 400)] });
|
|
207
|
+
DesignCore.Scene.entities.add(line);
|
|
208
|
+
const lineIndex = DesignCore.Scene.entities.count() - 1;
|
|
209
|
+
|
|
210
|
+
// Pre-select the line so Block.execute() skips the selection-set prompt
|
|
211
|
+
DesignCore.Scene.selectionManager.reset();
|
|
212
|
+
DesignCore.Scene.selectionManager.addToSelectionSet(lineIndex);
|
|
213
|
+
|
|
214
|
+
// Feed: block name, then insert point (50, 75)
|
|
215
|
+
const insertPoint = new Point(50, 75);
|
|
216
|
+
const origRequestInput = DesignCore.Scene.inputManager.requestInput.bind(DesignCore.Scene.inputManager);
|
|
217
|
+
DesignCore.Scene.inputManager.requestInput = mockRequestInput(['TestBlock', insertPoint]);
|
|
218
|
+
|
|
219
|
+
await new Block().execute();
|
|
220
|
+
|
|
221
|
+
DesignCore.Scene.inputManager.requestInput = origRequestInput;
|
|
222
|
+
|
|
223
|
+
// The block should exist in the block manager
|
|
224
|
+
const block = DesignCore.Scene.blockManager.getItemByName('TestBlock');
|
|
225
|
+
expect(block).toBeDefined();
|
|
226
|
+
expect(block.entities).toHaveLength(1);
|
|
227
|
+
|
|
228
|
+
// Points inside the block must be offset by -insertPoint so that
|
|
229
|
+
// when Insert renders them via applyTransform(+insertPoint) they land
|
|
230
|
+
// back at their original world coordinates.
|
|
231
|
+
const blockLine = block.entities[0];
|
|
232
|
+
expect(blockLine.points[0].x).toBeCloseTo(100 - insertPoint.x);
|
|
233
|
+
expect(blockLine.points[0].y).toBeCloseTo(200 - insertPoint.y);
|
|
234
|
+
expect(blockLine.points[1].x).toBeCloseTo(300 - insertPoint.x);
|
|
235
|
+
expect(blockLine.points[1].y).toBeCloseTo(400 - insertPoint.y);
|
|
236
|
+
});
|
|
@@ -91,7 +91,7 @@ test('Test LayerManager.checkStyles', () => {
|
|
|
91
91
|
layer: newItemName,
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
-
core.scene.
|
|
94
|
+
core.scene.addEntity('Line', data);
|
|
95
95
|
|
|
96
96
|
layerManager.checkStyles();
|
|
97
97
|
const layers = layerManager.getItems();
|
|
@@ -115,7 +115,7 @@ test('Test LayerManager.checkItems', () => {
|
|
|
115
115
|
layer: newItemName,
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
-
core.scene.
|
|
118
|
+
core.scene.addEntity('Line', data);
|
|
119
119
|
|
|
120
120
|
layerManager.checkItems();
|
|
121
121
|
const layers = layerManager.getItems();
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
import { Core } from '../../core/core/core.js';
|
|
17
17
|
import { Hatch } from '../../core/entities/hatch.js';
|
|
18
|
-
import {
|
|
18
|
+
import { PolylineBase } from '../../core/entities/polylineBase.js';
|
|
19
19
|
import { Point } from '../../core/entities/point.js';
|
|
20
20
|
import { Text } from '../../core/entities/text.js';
|
|
21
21
|
|
|
@@ -136,7 +136,7 @@ export function buildHatchGrid(renderer) {
|
|
|
136
136
|
let outlinePoints;
|
|
137
137
|
|
|
138
138
|
if (i % 2 === 0) {
|
|
139
|
-
hatchBoundary = new
|
|
139
|
+
hatchBoundary = new PolylineBase({ points: [
|
|
140
140
|
new Point(cx - SHAPE_R, cy - SHAPE_R),
|
|
141
141
|
new Point(cx + SHAPE_R, cy - SHAPE_R),
|
|
142
142
|
new Point(cx + SHAPE_R, cy + SHAPE_R),
|
|
@@ -145,7 +145,7 @@ export function buildHatchGrid(renderer) {
|
|
|
145
145
|
outlinePoints = hatchBoundary.toPolylinePoints();
|
|
146
146
|
} else {
|
|
147
147
|
// Two exact semicircle arcs (bulge = 1) for clipping; polygon for visible outline
|
|
148
|
-
hatchBoundary = new
|
|
148
|
+
hatchBoundary = new PolylineBase({ points: [
|
|
149
149
|
new Point(cx + SHAPE_R, cy, 1),
|
|
150
150
|
new Point(cx - SHAPE_R, cy, 1),
|
|
151
151
|
] });
|
|
@@ -27,10 +27,10 @@ export class File {
|
|
|
27
27
|
* @param {Function} testFn - async function to run with the mock active
|
|
28
28
|
* @param {object} [options] - optional configuration
|
|
29
29
|
* @param {object} [options.extraMethods] - additional methods to add to the mock inputManager
|
|
30
|
-
* @param {Array} [options.
|
|
30
|
+
* @param {Array} [options.selectedEntities] - sequential values returned by entities.get
|
|
31
31
|
*/
|
|
32
32
|
export async function withMockInput(scene, inputs, testFn, options = {}) {
|
|
33
|
-
const { extraMethods = {},
|
|
33
|
+
const { extraMethods = {}, selectedEntities } = options;
|
|
34
34
|
const origInputManager = scene.inputManager;
|
|
35
35
|
let callCount = 0;
|
|
36
36
|
|
|
@@ -47,11 +47,11 @@ export async function withMockInput(scene, inputs, testFn, options = {}) {
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
let origGetItem;
|
|
50
|
-
if (
|
|
50
|
+
if (selectedEntities) {
|
|
51
51
|
origGetItem = scene.entities.get;
|
|
52
|
-
let
|
|
52
|
+
let selectedEntitiesCallCount = 0;
|
|
53
53
|
scene.entities.get = () => {
|
|
54
|
-
return
|
|
54
|
+
return selectedEntities[selectedEntitiesCallCount++];
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -59,7 +59,7 @@ export async function withMockInput(scene, inputs, testFn, options = {}) {
|
|
|
59
59
|
await testFn();
|
|
60
60
|
} finally {
|
|
61
61
|
scene.inputManager = origInputManager;
|
|
62
|
-
if (
|
|
62
|
+
if (selectedEntities) {
|
|
63
63
|
scene.entities.get = origGetItem;
|
|
64
64
|
}
|
|
65
65
|
}
|