@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.
Files changed (113) hide show
  1. package/.github/workflows/DesignCoreQA.yml +3 -0
  2. package/core/designCore.js +1 -1
  3. package/core/dimensions/alignedDimension.js +7 -7
  4. package/core/dimensions/angularDimension.js +32 -32
  5. package/core/dimensions/{baseCircularDimension.js → circularDimensionBase.js} +19 -19
  6. package/core/dimensions/diametricDimension.js +10 -10
  7. package/core/dimensions/dimension.js +42 -42
  8. package/core/dimensions/{baseDimension.js → dimensionBase.js} +17 -17
  9. package/core/dimensions/{baseLinearDimension.js → linearDimensionBase.js} +9 -9
  10. package/core/dimensions/radialDimension.js +8 -8
  11. package/core/dimensions/rotatedDimension.js +8 -8
  12. package/core/entities/arc.js +22 -22
  13. package/core/entities/arctext.js +13 -13
  14. package/core/entities/circle.js +7 -7
  15. package/core/entities/hatch.js +28 -28
  16. package/core/entities/insert.js +5 -5
  17. package/core/entities/point.js +19 -19
  18. package/core/entities/polyline.js +3 -3
  19. package/core/entities/{basePolyline.js → polylineBase.js} +18 -18
  20. package/core/entities/text.js +4 -4
  21. package/core/lib/boundingBox.js +11 -11
  22. package/core/lib/canvas.js +6 -4
  23. package/core/lib/clipboard.js +2 -2
  24. package/core/lib/dxf/dxf.js +11 -11
  25. package/core/lib/dxf/dxfIterator.js +2 -2
  26. package/core/lib/entityManager.js +19 -19
  27. package/core/lib/inputManager.js +1 -1
  28. package/core/lib/matrix.js +1 -1
  29. package/core/lib/patterns.js +1 -1
  30. package/core/lib/polylineUtils.js +9 -9
  31. package/core/lib/renderers/cairoRenderer.js +5 -5
  32. package/core/lib/renderers/canvasRenderer.js +4 -4
  33. package/core/lib/renderers/pdfRenderer.js +7 -7
  34. package/core/lib/renderers/rendererBase.js +1 -1
  35. package/core/lib/scene.js +1 -1
  36. package/core/lib/selectionManager.js +18 -18
  37. package/core/lib/utils.js +5 -5
  38. package/core/properties/property.js +1 -1
  39. package/core/properties/propertyManager.js +37 -37
  40. package/core/tables/block.js +48 -46
  41. package/core/tables/dimStyle.js +5 -5
  42. package/core/tables/ltypeManager.js +1 -1
  43. package/core/tables/vport.js +2 -2
  44. package/core/tools/chamfer.js +6 -6
  45. package/core/tools/chamferFilletBase.js +4 -4
  46. package/core/tools/copy.js +8 -8
  47. package/core/tools/copybase.js +3 -3
  48. package/core/tools/copyclip.js +3 -3
  49. package/core/tools/cornerEntity.js +2 -2
  50. package/core/tools/cutclip.js +3 -3
  51. package/core/tools/explode.js +6 -6
  52. package/core/tools/extend.js +13 -13
  53. package/core/tools/fillet.js +6 -6
  54. package/core/tools/matchProp.js +1 -1
  55. package/core/tools/mirror.js +11 -11
  56. package/core/tools/move.js +5 -5
  57. package/core/tools/offset.js +29 -29
  58. package/core/tools/purge.js +10 -10
  59. package/core/tools/rotate.js +16 -16
  60. package/core/tools/scale.js +6 -6
  61. package/core/tools/trim.js +15 -15
  62. package/cspell.json +321 -0
  63. package/package.json +1 -1
  64. package/test/dimensions/alignedDimension.test.js +3 -3
  65. package/test/dimensions/angularDimension.test.js +7 -7
  66. package/test/dimensions/diametricDimension.test.js +9 -9
  67. package/test/dimensions/dimension.test.js +12 -12
  68. package/test/dimensions/{baseDimension.test.js → dimensionBase.test.js} +12 -12
  69. package/test/dimensions/{baseLinearDimension.test.js → linearDimensionBase.test.js} +7 -7
  70. package/test/dimensions/radialDimension.test.js +9 -9
  71. package/test/dimensions/rotatedDimension.test.js +4 -4
  72. package/test/entities/arc.test.js +10 -10
  73. package/test/entities/arctext.test.js +6 -6
  74. package/test/entities/circle.test.js +18 -18
  75. package/test/entities/hatch.test.js +39 -39
  76. package/test/entities/insert.test.js +9 -9
  77. package/test/entities/point.test.js +3 -3
  78. package/test/entities/{basePolyline.test.js → polylineBase.test.js} +131 -62
  79. package/test/entities/text.test.js +19 -19
  80. package/test/integration/exportIntegration.test.js +3 -3
  81. package/test/integration/userInputIntegration.test.js +5 -5
  82. package/test/lib/boundingBox.test.js +3 -3
  83. package/test/lib/canvas.test.js +9 -9
  84. package/test/lib/inputManager.test.js +4 -4
  85. package/test/lib/scene.test.js +9 -9
  86. package/test/lib/selectionManager.test.js +3 -3
  87. package/test/lib/snapping.test.js +1 -1
  88. package/test/properties/propertyManager.test.js +22 -22
  89. package/test/renderers/pdfRenderer.test.js +2 -2
  90. package/test/tables/block.test.js +63 -14
  91. package/test/tables/layerManager.test.js +2 -2
  92. package/test/test-helpers/hatchGridRenderer.js +3 -3
  93. package/test/test-helpers/test-helpers.js +6 -6
  94. package/test/tools/chamfer.test.js +60 -60
  95. package/test/tools/chamferFilletBase.test.js +36 -36
  96. package/test/tools/copy.test.js +6 -6
  97. package/test/tools/copybase.test.js +2 -2
  98. package/test/tools/copyclip.test.js +2 -2
  99. package/test/tools/cornerEntity.test.js +8 -8
  100. package/test/tools/cutclip.test.js +2 -2
  101. package/test/tools/erase.test.js +6 -6
  102. package/test/tools/explode.test.js +2 -2
  103. package/test/tools/extend.test.js +84 -84
  104. package/test/tools/fillet.test.js +62 -62
  105. package/test/tools/matchProp.test.js +6 -6
  106. package/test/tools/mirror.test.js +26 -26
  107. package/test/tools/move.test.js +7 -7
  108. package/test/tools/offset.test.js +65 -65
  109. package/test/tools/purge.test.js +4 -4
  110. package/test/tools/rotate.test.js +10 -10
  111. package/test/tools/scale.test.js +28 -28
  112. package/test/tools/trim.test.js +109 -109
  113. 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 { BasePolyline } from '../../core/entities/basePolyline.js';
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 BasePolyline({
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
- items: [blockLine],
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, center (250,50) r=30 → idx 1
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, center (450,50), start (480,50), 270° CCW → idx 2
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 origSelectedItems = DesignCore.Scene.selectionManager.selectedItems;
153
- DesignCore.Scene.selectionManager.selectedItems = [hatchBoundary];
152
+ const origSelectedEntities = DesignCore.Scene.selectionManager.selectedEntities;
153
+ DesignCore.Scene.selectionManager.selectedEntities = [hatchBoundary];
154
154
  await executeWithInputs(new Hatch(), ['accept']);
155
- DesignCore.Scene.selectionManager.selectedItems = origSelectedItems;
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.centerPoint', () => {
33
- expect(bb.centerPoint.x).toBe(151);
34
- expect(bb.centerPoint.y).toBe(152);
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', () => {
@@ -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.addItem('Line', { points: [new Point(0, 0), new Point(500, 500)] });
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.addItem('Line', { points: [new Point(0, 0), new Point(500, 500)] });
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.addItem('Line', { points: [new Point(0, 0), new Point(100, 100)] });
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.addItem('Line', { points: [new Point(0, 0), new Point(100, 100)] });
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.addItem('Line', { points: [new Point(0, 0), new Point(100, 100)] });
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.addItem('Line', { points: [new Point(0, 0), new Point(100, 100)] });
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.addItem('Line', { points: [new Point(0, 0), new Point(500, 500)] });
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.addItem('Line', { points: [new Point(0, 0), new Point(500, 500)] });
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.addItem('Line', { points: [new Point(0, 0), new Point(100, 100)] });
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.addItem('Line', { points: [new Point(0, 0), new Point(10, 0)] });
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.addItem('Line', { points: [new Point(0, 0), new Point(10, 0)] });
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 = { selectedItemIndex: 0 };
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.addItem('Line', { points: [new Point(0, 0), new Point(10, 0)] });
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));
@@ -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 (bypass scene.addItem())
15
- scene.addItem('Line', line1);
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 (bypass scene.addItem())
23
- scene.addItem('Line', line2);
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.addItem', () => {
31
+ test('Test Scene.addEntity', () => {
32
32
  // Throw error on missing data
33
33
  expect(() => {
34
- scene.addItem('Line');
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.addItem('FakeItem', {});
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.addItem('Line', { points: [new Point(), new Point(10, 10)] });
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.addItem('Line', { points: [new Point(123, 123), new Point(321, 321)] }, index);
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.addItem('Line', { points: [new Point(10, 10), new Point(100, 10)] });
9
- core.scene.addItem('Line', { points: [new Point(10, 20), new Point(100, 20)] });
10
- core.scene.addItem('Circle', { points: [new Point(), new Point(5, 0)] });
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.addItem('Line', { points: [new Point(10, 10), new Point(100, 10)] });
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.addItem('Line', data);
18
- DesignCore.Scene.addItem('Circle', data);
19
- DesignCore.Scene.addItem('Text', data);
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.addItem('Arc', { points: [point1, point2], colour: { r: 130, g: 130, b: 130 } });
21
+ DesignCore.Scene.addEntity('Arc', { points: [point1, point2], colour: { r: 130, g: 130, b: 130 } });
22
22
 
23
- test('Test propertyManager.getItemTypes', () => {
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.getItemTypes();
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.getItemTypes();
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.getItemTypes();
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.setItemProperties', () => {
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.setItemProperties('string', string);
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.setItemProperties('faux-prop', string);
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.setItemProperties('radius', string);
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.getItemProperties', () => {
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.getItemProperties();
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.getItemProperties('Line');
81
+ properties = propertiesManager.getEntityProperties('Line');
82
82
  expect(properties.length).toBeGreaterThan(0);
83
83
 
84
84
  // check properties for All itemTypes
85
- properties = propertiesManager.getItemProperties('All');
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.getItemProperties('Circle');
89
+ properties = propertiesManager.getEntityProperties('Circle');
90
90
  expect(properties.length).toBe(0);
91
91
  });
92
92
 
93
- test('Test propertyManager.getItemPropertyValue', () => {
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.getItemPropertyValue();
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.getItemPropertyValue('Line', 'colour');
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.getItemPropertyValue('Circle', 'colour');
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.getItemPropertyValue('All', 'colour');
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), center=(100,50), r=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 center=(50,50) r=50 — mirrors Circle.toPolylinePoints() output
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({ items: [line], flags: flags });
31
+ const block = new Block({ entities: [line], flags: flags });
19
32
 
20
- expect(block.items.length).toBe(1);
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({ items: [line] });
27
- expect(block.items.length).toBe(1);
39
+ const block = new Block({ entities: [line] });
40
+ expect(block.entities.length).toBe(1);
28
41
 
29
- block.clearItems();
30
- expect(block.items.length).toBe(0);
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.addItem(line);
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({ items: [line], flags: flags });
61
+ const block = new Block({ entities: [line], flags: flags });
49
62
 
50
- expect(block.items.length).toBe(1);
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.addItem(line);
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.addItem(line);
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.addItem(line);
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.addItem(clone);
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.addItem(clone);
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.addItem('Line', data);
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.addItem('Line', data);
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 { BasePolyline } from '../../core/entities/basePolyline.js';
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 BasePolyline({ points: [
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 BasePolyline({ points: [
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.selectedItems] - sequential values returned by entities.get
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 = {}, selectedItems } = options;
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 (selectedItems) {
50
+ if (selectedEntities) {
51
51
  origGetItem = scene.entities.get;
52
- let selectedItemsCallCount = 0;
52
+ let selectedEntitiesCallCount = 0;
53
53
  scene.entities.get = () => {
54
- return selectedItems[selectedItemsCallCount++];
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 (selectedItems) {
62
+ if (selectedEntities) {
63
63
  scene.entities.get = origGetItem;
64
64
  }
65
65
  }