@design-core/core 0.0.1 → 0.0.3

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 (254) hide show
  1. package/.eslintrc.json +14 -7
  2. package/.github/workflows/DesignCoreQA.yml +3 -1
  3. package/README.md +11 -4
  4. package/TODO.md +19 -0
  5. package/core/core/core.js +49 -42
  6. package/core/designCore.js +61 -2
  7. package/core/dimensions/alignedDimension.js +142 -0
  8. package/core/dimensions/angularDimension.js +550 -0
  9. package/core/dimensions/baseCircularDimension.js +244 -0
  10. package/core/dimensions/baseDimension.js +558 -0
  11. package/core/dimensions/baseLinearDimension.js +371 -0
  12. package/core/dimensions/diametricDimension.js +82 -0
  13. package/core/dimensions/dimension.js +298 -0
  14. package/core/dimensions/linearDimension.js +29 -0
  15. package/core/dimensions/radialDimension.js +78 -0
  16. package/core/dimensions/rotatedDimension.js +167 -0
  17. package/core/entities/arc.js +314 -60
  18. package/core/entities/arctext.js +642 -0
  19. package/core/entities/basePolyline.js +553 -94
  20. package/core/entities/circle.js +181 -54
  21. package/core/entities/entity.js +154 -74
  22. package/core/entities/hatch.js +807 -0
  23. package/core/entities/insert.js +200 -39
  24. package/core/entities/line.js +196 -134
  25. package/core/entities/lwpolyline.js +21 -44
  26. package/core/entities/point.js +194 -29
  27. package/core/entities/polyline.js +54 -7
  28. package/core/entities/rectangle.js +43 -13
  29. package/core/entities/solid.js +43 -6
  30. package/core/entities/text.js +324 -181
  31. package/core/lib/boundingBox.js +73 -13
  32. package/core/lib/canvas.js +256 -65
  33. package/core/lib/clipboard.js +198 -0
  34. package/core/lib/colour.js +144 -0
  35. package/core/lib/colours.js +367 -301
  36. package/core/lib/commandLine.js +16 -28
  37. package/core/lib/commandManager.js +115 -58
  38. package/core/lib/constants.js +23 -0
  39. package/core/lib/dxf/dxf.js +249 -34
  40. package/core/lib/dxf/dxfFile.js +23 -38
  41. package/core/lib/dxf/dxfIterator.js +17 -5
  42. package/core/lib/dxf/dxfRead.js +23 -7
  43. package/core/lib/dxf/dxfWrite.js +39 -129
  44. package/core/lib/dxf/handleManager.js +97 -0
  45. package/core/lib/dxf/sections/blocks.js +16 -2
  46. package/core/lib/dxf/sections/entities.js +17 -3
  47. package/core/lib/dxf/sections/header.js +10 -1
  48. package/core/lib/dxf/sections/objects.js +36 -0
  49. package/core/lib/dxf/sections/section.js +43 -5
  50. package/core/lib/dxf/sections/tables.js +17 -3
  51. package/core/lib/entityManager.js +178 -0
  52. package/core/lib/fileio.js +14 -4
  53. package/core/lib/headers.js +229 -0
  54. package/core/lib/input.js +46 -0
  55. package/core/lib/inputManager.js +199 -194
  56. package/core/lib/intersect.js +341 -468
  57. package/core/lib/logging.js +25 -1
  58. package/core/lib/matrix.js +6 -8
  59. package/core/lib/mouse.js +24 -79
  60. package/core/lib/patterns.js +690 -0
  61. package/core/lib/promptOptions.js +133 -0
  62. package/core/lib/scene.js +71 -174
  63. package/core/lib/selectionManager.js +74 -48
  64. package/core/lib/selectionWindow.js +24 -10
  65. package/core/lib/settings.js +18 -11
  66. package/core/lib/snapping.js +129 -21
  67. package/core/lib/stateManager.js +288 -0
  68. package/core/lib/strings.js +57 -5
  69. package/core/lib/utils.js +95 -11
  70. package/core/objects/dictionary.js +43 -0
  71. package/core/objects/dictionaryManager.js +80 -0
  72. package/core/properties/dimType.js +117 -0
  73. package/core/properties/flags.js +66 -0
  74. package/core/properties/property.js +26 -0
  75. package/core/properties/propertyManager.js +65 -19
  76. package/core/tables/appId.js +31 -0
  77. package/core/tables/appIdManager.js +44 -0
  78. package/core/tables/block.js +323 -0
  79. package/core/tables/blockManager.js +48 -0
  80. package/core/tables/blockRecord.js +29 -0
  81. package/core/tables/blockRecordManager.js +37 -0
  82. package/core/tables/dimStyle.js +627 -0
  83. package/core/tables/dimStyleManager.js +187 -0
  84. package/core/tables/endblk.js +28 -0
  85. package/core/tables/layer.js +219 -0
  86. package/core/tables/layerManager.js +47 -0
  87. package/core/tables/ltype.js +85 -0
  88. package/core/tables/ltypeManager.js +65 -0
  89. package/core/tables/style.js +145 -0
  90. package/core/tables/styleManager.js +55 -0
  91. package/core/tables/styleManagerBase.js +110 -0
  92. package/core/tables/tableManagerBase.js +354 -0
  93. package/core/tables/ucs.js +28 -0
  94. package/core/tables/ucsManager.js +44 -0
  95. package/core/tables/view.js +28 -0
  96. package/core/tables/viewManager.js +44 -0
  97. package/core/tables/vport.js +70 -0
  98. package/core/tables/vportManager.js +65 -0
  99. package/core/tools/chamfer.js +343 -0
  100. package/core/tools/chamferFilletBase.js +162 -0
  101. package/core/tools/copy.js +68 -40
  102. package/core/tools/copybase.js +65 -0
  103. package/core/tools/copyclip.js +59 -0
  104. package/core/tools/cornerEntity.js +138 -0
  105. package/core/tools/cutclip.js +72 -0
  106. package/core/tools/distance.js +37 -9
  107. package/core/tools/erase.js +43 -13
  108. package/core/tools/explode.js +117 -0
  109. package/core/tools/extend.js +71 -32
  110. package/core/tools/fillet.js +336 -0
  111. package/core/tools/identify.js +33 -6
  112. package/core/tools/matchProp.js +106 -0
  113. package/core/tools/mirror.js +141 -0
  114. package/core/tools/move.js +65 -32
  115. package/core/tools/offset.js +321 -0
  116. package/core/tools/pan.js +54 -0
  117. package/core/tools/pasteclip.js +93 -0
  118. package/core/tools/purge.js +90 -0
  119. package/core/tools/rotate.js +105 -70
  120. package/core/tools/scale.js +166 -0
  121. package/core/tools/tool.js +14 -4
  122. package/core/tools/trim.js +71 -32
  123. package/core/tools/zoom.js +152 -0
  124. package/package.json +3 -305
  125. package/test/dimensions/alignedDimension.test.js +211 -0
  126. package/test/dimensions/angularDimension.test.js +243 -0
  127. package/test/dimensions/baseDimension.test.js +239 -0
  128. package/test/dimensions/diametricDimension.test.js +203 -0
  129. package/test/dimensions/dimension.test.js +102 -0
  130. package/test/dimensions/radialDimension.test.js +203 -0
  131. package/test/dimensions/rotatedDimension.test.js +224 -0
  132. package/test/entities/arc.test.js +463 -41
  133. package/test/entities/arctext.test.js +329 -0
  134. package/test/entities/basePolyline.test.js +459 -10
  135. package/test/entities/circle.test.js +312 -7
  136. package/test/entities/entity.test.js +28 -9
  137. package/test/entities/hatch.test.js +606 -0
  138. package/test/entities/insert.test.js +90 -0
  139. package/test/entities/line.test.js +182 -6
  140. package/test/entities/point.test.js +375 -37
  141. package/test/entities/solid.test.js +156 -0
  142. package/test/entities/text.test.js +533 -7
  143. package/test/integration/exportIntegration.reference.dxf +1706 -0
  144. package/test/integration/exportIntegration.test.js +186 -0
  145. package/test/integration/importExportIntegration.test.js +126 -0
  146. package/test/integration/intersectionIntegration.test.js +880 -0
  147. package/test/integration/userInputIntegration.reference.dxf +1410 -0
  148. package/test/integration/userInputIntegration.test.js +269 -0
  149. package/test/lib/boundingBox.test.js +26 -2
  150. package/test/lib/canvas.test.js +613 -5
  151. package/test/lib/clipboard.test.js +70 -0
  152. package/test/lib/colour.test.js +114 -0
  153. package/test/lib/colours.test.js +63 -18
  154. package/test/lib/commandLine.test.js +159 -22
  155. package/test/lib/commandManager.test.js +4 -4
  156. package/test/lib/constants.test.js +9 -0
  157. package/test/lib/dxf/dxfFile.test.js +6 -2
  158. package/test/lib/dxf/dxfIterator.test.js +1 -1
  159. package/test/lib/dxf/dxfWrite.test.js +173 -0
  160. package/test/lib/dxf/handleManager.test.js +137 -0
  161. package/test/lib/dxf/sections/blocks.test.js +5 -5
  162. package/test/lib/dxf/sections/entities.test.js +4 -4
  163. package/test/lib/dxf/sections/header.test.js +18 -4
  164. package/test/lib/dxf/sections/objects.test.js +132 -0
  165. package/test/lib/dxf/sections/section.test.js +29 -29
  166. package/test/lib/dxf/sections/tables.test.js +3 -3
  167. package/test/lib/entityManager.test.js +163 -0
  168. package/test/lib/headers.test.js +233 -0
  169. package/test/lib/inputManager.test.js +1144 -5
  170. package/test/lib/intersect.test.js +454 -331
  171. package/test/lib/logging.test.js +1 -1
  172. package/test/lib/matrix.test.js +1 -1
  173. package/test/lib/mouse.test.js +327 -4
  174. package/test/lib/patterns.test.js +105 -0
  175. package/test/lib/promptOptions.test.js +179 -0
  176. package/test/lib/scene.test.js +16 -52
  177. package/test/lib/selectionManager.test.js +17 -5
  178. package/test/lib/settings.test.js +111 -5
  179. package/test/lib/snapping.test.js +142 -4
  180. package/test/lib/stateManager.test.js +155 -0
  181. package/test/lib/utils.test.js +81 -1
  182. package/test/objects/dictionary.test.js +81 -0
  183. package/test/objects/dictionaryManager.test.js +34 -0
  184. package/test/properties/dimType.test.js +62 -0
  185. package/test/properties/flags.test.js +164 -0
  186. package/test/properties/property.test.js +13 -0
  187. package/test/properties/propertyManager.test.js +10 -11
  188. package/test/tables/appId.test.js +46 -0
  189. package/test/tables/appIdManager.test.js +72 -0
  190. package/test/tables/block.test.js +157 -0
  191. package/test/tables/blockManager.test.js +52 -0
  192. package/test/tables/blockRecord.test.js +39 -0
  193. package/test/tables/blockRecordManager.test.js +60 -0
  194. package/test/tables/dimstyle.test.js +72 -0
  195. package/test/tables/endblk.test.js +30 -0
  196. package/test/tables/layer.test.js +95 -0
  197. package/test/tables/layerManager.test.js +172 -0
  198. package/test/{styles → tables}/ltype.test.js +7 -7
  199. package/test/{styles → tables}/ltypeManager.test.js +2 -2
  200. package/test/tables/style.test.js +44 -0
  201. package/test/tables/stylemanagerbase.test.js +220 -0
  202. package/test/tables/tableManagerBase.test.js +194 -0
  203. package/test/tables/ucs.test.js +37 -0
  204. package/test/tables/ucsManager.test.js +48 -0
  205. package/test/tables/view.test.js +37 -0
  206. package/test/tables/viewManager.test.js +48 -0
  207. package/test/tables/vport.test.js +117 -0
  208. package/test/tables/vportManager.test.js +54 -0
  209. package/test/test-helpers/test-helpers.js +66 -0
  210. package/test/tools/chamfer.test.js +970 -0
  211. package/test/tools/chamferFilletBase.test.js +446 -0
  212. package/test/tools/copy.test.js +22 -14
  213. package/test/tools/copybase.test.js +93 -0
  214. package/test/tools/copyclip.test.js +92 -0
  215. package/test/tools/cornerEntity.test.js +201 -0
  216. package/test/tools/cutclip.test.js +94 -0
  217. package/test/tools/distance.test.js +140 -18
  218. package/test/tools/erase.test.js +12 -12
  219. package/test/tools/explode.test.js +45 -0
  220. package/test/tools/extend.test.js +326 -44
  221. package/test/tools/fillet.test.js +831 -0
  222. package/test/tools/identify.test.js +115 -16
  223. package/test/tools/matchProp.test.js +84 -0
  224. package/test/tools/mirror.test.js +475 -0
  225. package/test/tools/move.test.js +75 -19
  226. package/test/tools/offset.test.js +748 -0
  227. package/test/tools/pan.test.js +72 -0
  228. package/test/tools/pasteclip.test.js +100 -0
  229. package/test/tools/purge.test.js +89 -0
  230. package/test/tools/rotate.test.js +89 -23
  231. package/test/tools/scale.test.js +529 -0
  232. package/test/tools/trim.test.js +419 -84
  233. package/test/tools/zoom.test.js +504 -0
  234. package/core/entities/alignedDimension.js +0 -279
  235. package/core/entities/angularDimension.js +0 -194
  236. package/core/entities/baseDimension.js +0 -227
  237. package/core/entities/block.js +0 -247
  238. package/core/entities/diametricDimension.js +0 -133
  239. package/core/entities/dimension.js +0 -202
  240. package/core/entities/radialDimension.js +0 -126
  241. package/core/styles/dimStyle.js +0 -719
  242. package/core/styles/dimStyleManager.js +0 -47
  243. package/core/styles/layer.js +0 -133
  244. package/core/styles/layerManager.js +0 -40
  245. package/core/styles/ltype.js +0 -86
  246. package/core/styles/ltypeManager.js +0 -50
  247. package/core/styles/style.js +0 -158
  248. package/core/styles/styleManager.js +0 -43
  249. package/core/styles/styleManagerBase.js +0 -299
  250. package/test/entities/block.test.js +0 -22
  251. package/test/styles/dimstyle.test.js +0 -19
  252. package/test/styles/layerManager.test.js +0 -150
  253. package/test/styles/style.test.js +0 -33
  254. package/test/styles/stylemanagerbase.test.js +0 -219
@@ -0,0 +1,145 @@
1
+ import { DXFFile } from '../lib/dxf/dxfFile.js';
2
+ import { Flags } from '../properties/flags.js';
3
+ import { Property } from '../properties/property.js';
4
+
5
+ /** Style Class */
6
+ export class Style {
7
+ /**
8
+ * Create Style
9
+ * @param {Object} data
10
+ */
11
+ constructor(data) {
12
+ // Define Properties
13
+ this.type = this.constructor.name;
14
+ this.name = '';
15
+ this.font = 'Arial'; // TODO: how to set the font to one that's available. See style.js also.
16
+ this.textHeight = 0;
17
+ this.widthFactor = 1;
18
+ this.obliqueAngle = 0;
19
+ this.lastTextHeight = this.textHeight;
20
+ this.flags = new Flags();
21
+ this.standardFlags = new Flags();
22
+
23
+ // DXF Groupcode 5 - Handle
24
+ this.handle = Property.loadValue([data?.handle, data?.[5]]);
25
+ // DXF Groupcode 2 - ltype name
26
+ this.name = Property.loadValue([data?.name, data?.[2]], '');
27
+ // DXF Groupcode 3 - style font
28
+ this.font = Property.loadValue([data?.font, data?.[3]], 'Arial');
29
+ // DXF Groupcode 4 - big font
30
+ this.bigFont = Property.loadValue([data?.bigFont, data?.[4]]);
31
+ // DXF Groupcode 40 - Text height
32
+ this.textHeight = Property.loadValue([data?.textHeight, data?.[40]], 0);
33
+ // DXF Groupcode 41 - width factor
34
+ this.widthFactor = Property.loadValue([data?.widthFactor, data?.[41]], 1);
35
+ // DXF Groupcode 42 - Last text height
36
+ this.lastTextHeight = Property.loadValue([data?.lastTextHeight, data?.[42]], this.textHeight);
37
+ // DXF Groupcode 50 - test height
38
+ this.obliqueAngle = Property.loadValue([data?.obliqueAngle, data?.[50]], 0);
39
+
40
+ // DXF Groupcode 70 - standard flags
41
+ /*
42
+ 1 = If set, this entry describes a shape
43
+ 4 = Vertical text
44
+ 16 = If set, table entry is externally dependent on an xref
45
+ 32 = If this bit and bit 16 are both set, the externally dependent xref has been successfully resolved
46
+ 64 = If set, the table entry was referenced by at least one entity in the drawing the last time the drawing was edited.
47
+ (This flag is for the benefit of AutoCAD commands. It can be ignored.
48
+ */
49
+ this.standardFlags.setFlagValue(Property.loadValue([data?.standardFlags, data?.[70]], 0));
50
+
51
+ // DXF Groupcode 71 - flags (bit-coded values):
52
+ // 2 = Text is backward (mirrored in X).
53
+ // 4 = Text is upside down (mirrored in Y).
54
+ this.flags.setFlagValue(Property.loadValue([data?.flags, data?.[71]], 0));
55
+ }
56
+
57
+ /**
58
+ * Get the vertical value
59
+ * @return {bool}
60
+ */
61
+ get vertical() {
62
+ // Vertical value is bitmasked in standardflags as value 4
63
+ return this.standardFlags.hasFlag(4);
64
+ }
65
+
66
+ /**
67
+ * Set the vertical value
68
+ * @param {boolean} bool
69
+ */
70
+ set vertical(bool) {
71
+ if (bool) {
72
+ // Add flag
73
+ this.standardFlags.addValue(4);
74
+ } else {
75
+ // remove flag
76
+ this.standardFlags.removeValue(4);
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Get the backwards value
82
+ * @return {bool}
83
+ */
84
+ get backwards() {
85
+ // Upside down value is bitmasked in flags as value 2
86
+ return this.flags.hasFlag(2);
87
+ }
88
+
89
+ /**
90
+ * set the backwards value
91
+ * @param {boolean} bool
92
+ */
93
+ set backwards(bool) {
94
+ if (bool) {
95
+ // Add flag
96
+ this.flags.addValue(2);
97
+ } else {
98
+ // remove flag
99
+ this.flags.removeValue(2);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Get the upside down value
105
+ * @return {bool}
106
+ */
107
+ get upsideDown() {
108
+ // Upside down value is bitmasked in flags as value 4
109
+ return this.flags.hasFlag(4);
110
+ }
111
+
112
+ /**
113
+ * Set the upside down value
114
+ * @param {boolean} bool
115
+ */
116
+ set upsideDown(bool) {
117
+ if (bool) {
118
+ // Add flag
119
+ this.flags.addValue(4);
120
+ } else {
121
+ // remove flag
122
+ this.flags.removeValue(4);
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Write the table to file in the dxf format
128
+ * @param {DXFFile} file
129
+ */
130
+ dxf(file) {
131
+ file.writeGroupCode('0', 'STYLE');
132
+ file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
133
+ file.writeGroupCode('100', 'AcDbSymbolTableRecord', DXFFile.Version.R2000);
134
+ file.writeGroupCode('100', 'AcDbTextStyleTableRecord', DXFFile.Version.R2000);
135
+ file.writeGroupCode('2', this.name); // Stylename
136
+ file.writeGroupCode('3', this.font); // Font
137
+ file.writeGroupCode('4', ''); // Big font name blank is none
138
+ file.writeGroupCode('40', this.textHeight); // Text Height
139
+ file.writeGroupCode('41', this.widthFactor); // Width Factor
140
+ file.writeGroupCode('42', this.textHeight); // Last Text Height
141
+ file.writeGroupCode('50', this.obliqueAngle);
142
+ file.writeGroupCode('70', this.standardFlags.getFlagValue()); // Standard Flags
143
+ file.writeGroupCode('71', this.flags.getFlagValue()); // Flags
144
+ }
145
+ }
@@ -0,0 +1,55 @@
1
+ import { DXFFile } from '../lib/dxf/dxfFile.js';
2
+ import { StyleManagerBase } from './styleManagerBase.js';
3
+ import { Style } from './style.js';
4
+
5
+ /**
6
+ * StyleManager Class
7
+ * Manages text styles
8
+ * @extends StyleManagerBase
9
+ */
10
+ export class StyleManager extends StyleManagerBase {
11
+ /** Create Style Manager */
12
+ constructor() {
13
+ super();
14
+
15
+ this.indelibleItems.push('STANDARD');
16
+ this.itemProperty = 'style';
17
+ }
18
+
19
+ /** Get the item class */
20
+ get itemClass() {
21
+ return Style;
22
+ }
23
+
24
+ /** Add standard text styles */
25
+ addStandardItems() {
26
+ this.addItem({
27
+ 'name': 'STANDARD',
28
+ });
29
+
30
+ this.addItem({
31
+ 'name': 'ANNOTATIVE',
32
+ });
33
+
34
+ // DesignCore.scene.saveRequired();
35
+ }
36
+
37
+ /**
38
+ * Write the entity to file in the dxf format
39
+ * @param {DXFFile} file
40
+ */
41
+ dxf(file) {
42
+ // Create table data for text styles
43
+ file.writeGroupCode('0', 'TABLE');
44
+ file.writeGroupCode('2', 'STYLE');
45
+ file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
46
+ file.writeGroupCode('100', 'AcDbSymbolTable', DXFFile.Version.R2000);
47
+ file.writeGroupCode('70', this.itemCount());
48
+
49
+ for (let i = 0; i < this.itemCount(); i++) {
50
+ this.getItemByIndex(i).dxf(file);
51
+ }
52
+
53
+ file.writeGroupCode('0', 'ENDTAB');
54
+ }
55
+ }
@@ -0,0 +1,110 @@
1
+ import { DesignCore } from '../designCore.js';
2
+ // import {Strings} from '../lib/strings.js';
3
+ import { TableManagerBase } from './tableManagerBase.js';
4
+
5
+ /**
6
+ * StyleManagerBase Class
7
+ * @extends TableManagerBase
8
+ */
9
+ export class StyleManagerBase extends TableManagerBase {
10
+ /**
11
+ * Create Style Manager
12
+ */
13
+ constructor() {
14
+ super();
15
+
16
+ // set the current style to the first available style
17
+ this.currentstyle = this.items[0].name;
18
+ }
19
+
20
+ /**
21
+ * Delete a style using the style index
22
+ * @param {number} itemIndex
23
+ * @param {boolean} showWarning
24
+ */
25
+ deleteStyle(itemIndex, showWarning = true) {
26
+ // call the super class delete
27
+ const deletedItem = this.deleteItem(itemIndex, showWarning);
28
+
29
+ if (deletedItem) {
30
+ // delete all item using the selected style
31
+ this.deleteStyleFromScene(deletedItem.name);
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Delete all items that use style
37
+ * @param {string} style
38
+ */
39
+ deleteStyleFromScene(style) {
40
+ const selectionSet = [];
41
+
42
+ for (let i = 0; i < DesignCore.Scene.entities.count(); i++) {
43
+ if (DesignCore.Scene.entities.get(i)[this.itemProperty] === style) {
44
+ selectionSet.push(i);
45
+ }
46
+ }
47
+
48
+ // sort the selection in descending order
49
+ selectionSet.sort((a, b) => b - a);
50
+
51
+ for (let j = 0; j < selectionSet.length; j++) {
52
+ DesignCore.Scene.entities.remove((selectionSet[j]));
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Get the name of the current style
58
+ * @return {Object}
59
+ */
60
+ getCstyle() {
61
+ return this.currentstyle;
62
+ }
63
+
64
+ /**
65
+ * Set the current style
66
+ * @param {string} cstyle
67
+ */
68
+ setCstyle(cstyle) {
69
+ if (this.getItemByName(cstyle) !== undefined) {
70
+ this.currentstyle = cstyle;
71
+ }
72
+ }
73
+
74
+
75
+ /**
76
+ * Ensure that used styles and default styles exist
77
+ */
78
+ checkStyles() {
79
+ this.addStandardItems();
80
+
81
+ for (let i = 0; i < DesignCore.Scene.entities.count(); i++) {
82
+ const style = (DesignCore.Scene.entities.get(i)[this.itemProperty]);
83
+ this.addItem({
84
+ 'name': style,
85
+ });
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Rename the style at index with newName
91
+ * @param {number} styleIndex
92
+ * @param {string} newName
93
+ */
94
+ renameStyle(styleIndex, newName) {
95
+ // get the existing name
96
+ const currentStyleName = this.items[styleIndex].name;
97
+
98
+ // call the super class rename
99
+ const newUniqueName = this.renameItem(styleIndex, newName);
100
+
101
+ if (newUniqueName === undefined) {
102
+ return;
103
+ }
104
+
105
+ // if the style to change is the current style, update the currentstyle property
106
+ if (currentStyleName === this.currentstyle) {
107
+ this.setCstyle(newUniqueName);
108
+ }
109
+ }
110
+ }
@@ -0,0 +1,354 @@
1
+ import { DesignCore } from '../designCore.js';
2
+ import { Strings } from '../lib/strings.js';
3
+ import { Logging } from '../lib/logging.js';
4
+
5
+ /**
6
+ * Table Manager Base Class
7
+ */
8
+ export class TableManagerBase {
9
+ // Cached Map<string, item> for O(1) lookups by name.
10
+ // Lazily built on first getItemByName() call and
11
+ // invalidated when items are added, deleted, or cleared.
12
+ #lookupMap = null;
13
+ #items = [];
14
+
15
+ /**
16
+ * Get the list of items
17
+ * @return {Array}
18
+ */
19
+ get items() {
20
+ return this.#items;
21
+ }
22
+
23
+ /**
24
+ * Set the list of items and invalidate the lookup cache
25
+ * @param {Array} value
26
+ */
27
+ set items(value) {
28
+ this.#items = value;
29
+ this.#invalidateLookup();
30
+ }
31
+
32
+ /**
33
+ * Create a Table Manager
34
+ */
35
+ constructor() {
36
+ this.handle = DesignCore.HandleManager.next();
37
+ this.addStandardItems();
38
+
39
+ // list of mandatory items that cannot be deleted
40
+ this.indelibleItems = [];
41
+ }
42
+
43
+ /**
44
+ * Invalidate the lookup map cache.
45
+ * Must be called whenever the items array is mutated.
46
+ */
47
+ #invalidateLookup() {
48
+ this.#lookupMap = null;
49
+ }
50
+
51
+ /**
52
+ * Create a new typed item
53
+ * @param {Object} data
54
+ * @return {Object}
55
+ */
56
+ createItem(data) {
57
+ const ItemClass = this.itemClass;
58
+ return new ItemClass(data);
59
+ }
60
+
61
+ /**
62
+ * Get items
63
+ * @return {Array} list of items
64
+ */
65
+ getItems() {
66
+ return this.items;
67
+ }
68
+
69
+ /**
70
+ * Get item count
71
+ * @return {number} number of items
72
+ */
73
+ itemCount() {
74
+ return this.items.length;
75
+ }
76
+
77
+ /**
78
+ * Adds a new item to the list of active items
79
+ */
80
+ newItem() {
81
+ this.addItem({
82
+ 'name': this.getUniqueName(`NEW_${this.itemProperty}`.toUpperCase()),
83
+ });
84
+ }
85
+
86
+ /**
87
+ * Generate a unique name
88
+ * @param {string} name
89
+ * @return {string} unique name
90
+ */
91
+ getUniqueName(name) {
92
+ let count = 0;
93
+ let styStr = name.replace(/ /g, '_'); // .toUpperCase();
94
+ for (let i = 0; i < this.itemCount(); i++) {
95
+ const itemName = this.items[i].name.toUpperCase();
96
+ if (itemName.includes(styStr.toUpperCase())) {
97
+ count = count + 1;
98
+ }
99
+ }
100
+ if (count > 0) {
101
+ styStr = styStr + '_' + count;
102
+ }
103
+
104
+ return styStr;
105
+ };
106
+
107
+ /**
108
+ * Add a item to the list of items
109
+ * @param {item} item
110
+ * @param {boolean} overwrite
111
+ * @return {Objects}
112
+ */
113
+ addItem(item, overwrite = false) {
114
+ // Call the subclass to create a new typed item object
115
+ const newItem = this.createItem(item);
116
+ const newItemName = newItem.name;
117
+
118
+ const exists = this.itemExists(newItemName);
119
+
120
+ // Return the existing item if it already exists and overwrite is not requested
121
+ if (exists && !overwrite) {
122
+ return this.getItemByName(newItemName);
123
+ }
124
+
125
+ if (newItem.handle === undefined) {
126
+ newItem.handle = DesignCore.HandleManager.next();
127
+ } else {
128
+ DesignCore.HandleManager.checkHandle(newItem.handle);
129
+ }
130
+
131
+ if (!exists) {
132
+ this.items.push(newItem);
133
+ } else {
134
+ // Overwrite the existing item
135
+ // This is used when loading files;
136
+ // Standard items already exist but should be overwritten by the incoming item
137
+ this.items.splice(this.getItemIndex(newItemName), 1, newItem);
138
+ }
139
+
140
+ this.#invalidateLookup();
141
+ // DesignCore.Scene.saveRequired();
142
+ return newItem;
143
+ }
144
+
145
+ /**
146
+ * Delete a item using the item index
147
+ * @param {number} itemIndex
148
+ * @param {boolean} showWarning
149
+ * @return {Array} array containing deleted item or undefined
150
+ */
151
+ deleteItem(itemIndex, showWarning = true) {
152
+ if (this.items[itemIndex] === undefined) {
153
+ return;
154
+ }
155
+
156
+ const itemToDelete = this.getItemByIndex(itemIndex).name;
157
+
158
+ // Can't delete indelible items (Standard Text Item, Layer 0)
159
+ if (this.indelibleItems.some((item) => item.toUpperCase() === itemToDelete.toUpperCase())) {
160
+ if (showWarning) {
161
+ DesignCore.Core.notify(`${itemToDelete} - ${Strings.Message.CANNOTBEDELETED}`);
162
+ }
163
+ return;
164
+ }
165
+
166
+ // Delete The item
167
+ const deleted = this.items.splice(itemIndex, 1);
168
+ this.#invalidateLookup();
169
+ return deleted;
170
+ }
171
+
172
+
173
+ /**
174
+ * Check if a item with itemName exists
175
+ * @param {string} itemName
176
+ * @return {boolean}
177
+ */
178
+ itemExists(itemName) {
179
+ const itemExists = this.items.some((el) => el.name.toUpperCase() === itemName.toUpperCase());
180
+ return itemExists;
181
+ }
182
+
183
+ /**
184
+ * Ensure that used items and default items exist
185
+ */
186
+ checkItems() {
187
+ this.addStandardItems();
188
+
189
+ for (let i = 0; i < DesignCore.Scene.entities.count(); i++) {
190
+ const item = (DesignCore.Scene.entities.get(i));
191
+
192
+ // check the item has the required property
193
+ if (Object.hasOwn(item, this.itemProperty) === false) {
194
+ continue;
195
+ }
196
+
197
+ // get the property value
198
+ const propertyValue = (item[this.itemProperty]);
199
+
200
+ // create missing items
201
+ // example if an entity uses a missing layer, create the layer.
202
+ if (!this.itemExists(propertyValue)) {
203
+ this.addItem({
204
+ 'name': propertyValue,
205
+ });
206
+ }
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Clear all existing items
212
+ */
213
+ clearItems() {
214
+ this.items = [];
215
+ }
216
+
217
+ /**
218
+ * Find the index of itemName
219
+ * @param {string} itemName
220
+ * @return {number} index of the item or -1 if item doesn't exist
221
+ */
222
+ getItemIndex(itemName) {
223
+ return this.items.findIndex((item) => item.name.toUpperCase() === itemName.toUpperCase());
224
+ }
225
+
226
+ /**
227
+ * get a item matching itemname
228
+ * @param {string} itemName
229
+ * @return {Object}
230
+ */
231
+ getItemByName(itemName) {
232
+ if (!this.#lookupMap) {
233
+ this.#lookupMap = new Map();
234
+ for (let i = 0; i < this.items.length; i++) {
235
+ this.#lookupMap.set(this.items[i].name.toUpperCase(), this.items[i]);
236
+ }
237
+ }
238
+
239
+ const item = this.#lookupMap.get(itemName.toUpperCase());
240
+
241
+ if (item === undefined) {
242
+ // Log warning if item doesn't exist
243
+ // Consider nested blocks where block may not exist yet
244
+ const msg = 'Invalid Item Name';
245
+ const err = (`${this.constructor.name} - ${msg}: ${itemName}`);
246
+ Logging.instance.warn(`${err}`);
247
+ }
248
+
249
+ return item;
250
+ }
251
+
252
+ /**
253
+ * Get the item from an index
254
+ * @param {number} itemIndex
255
+ * @return {Object}
256
+ */
257
+ getItemByIndex(itemIndex) {
258
+ return this.items[itemIndex];
259
+ }
260
+
261
+
262
+ /**
263
+ * Rename the item at index with newName
264
+ * @param {number} itemIndex
265
+ * @param {string} newName
266
+ * @return {string} new name or undefined
267
+ */
268
+ renameItem(itemIndex, newName) {
269
+ const itemToRename = this.getItemByIndex(itemIndex).name;
270
+
271
+ // make sure it is a new name
272
+ if (itemToRename.toUpperCase() === newName.toUpperCase()) {
273
+ return;
274
+ }
275
+
276
+ // Can't rename indelible items (Standard Text Item, Layer 0)
277
+ if (this.indelibleItems.some((item) => item.toUpperCase() === itemToRename.toUpperCase())) {
278
+ DesignCore.Core.notify(`${itemToRename} - ${Strings.Message.CANNOTBERENAMED}`);
279
+ return;
280
+ }
281
+
282
+ // Can't use the name of indelible items (Standard Text Item, Layer 0)
283
+ if (this.indelibleItems.some((item) => item.toUpperCase() === newName.toUpperCase())) {
284
+ DesignCore.Core.notify(`${newName} - ${Strings.Message.CANNOTBERENAMED}`);
285
+ return;
286
+ }
287
+
288
+ const newUniqueName = this.getUniqueName(newName);
289
+ const currentItemName = this.items[itemIndex].name;
290
+ this.items[itemIndex].name = newUniqueName;
291
+ this.#invalidateLookup();
292
+
293
+ // update all scene items with the new item value
294
+ this.updateSceneItem(currentItemName, newUniqueName);
295
+
296
+ return newUniqueName;
297
+ }
298
+
299
+ /**
300
+ * Update all items that use item
301
+ * @param {string} oldItemName
302
+ * @param {string} newItemName
303
+ */
304
+ updateSceneItem(oldItemName, newItemName) {
305
+ for (let i = 0; i < DesignCore.Scene.entities.count(); i++) {
306
+ if (DesignCore.Scene.entities.get(i)[this.itemProperty] === oldItemName) {
307
+ DesignCore.Scene.entities.get(i)[this.itemProperty] = newItemName;
308
+ }
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Update the item property with value
314
+ * @param {number} itemIndex
315
+ * @param {string} property
316
+ * @param {any} value
317
+ */
318
+ updateItem(itemIndex, property, value) {
319
+ // check of the index exists
320
+ if (this.items[itemIndex] === undefined) {
321
+ const msg = 'Invalid Item Index';
322
+ const err = (`${this.type} - ${msg}`);
323
+ throw Error(err);
324
+ }
325
+
326
+ if (this.items[itemIndex][property] === undefined) {
327
+ const msg = 'Invalid Item Property';
328
+ const err = (`${this.type} - ${msg}`);
329
+ throw Error(err);
330
+ }
331
+
332
+ if (property.toUpperCase() === 'NAME') {
333
+ this.renameItem(itemIndex, value);
334
+ } else {
335
+ this.items[itemIndex][property] = value;
336
+ }
337
+ }
338
+
339
+ /** Purge unused items */
340
+ purge() {
341
+ const itemsToPurge = [];
342
+ this.items.forEach((item, index) => {
343
+ const searchTerm = this.itemProperty === 'block' ? item : item.name;
344
+ const items = DesignCore.Scene.entities.find('ANY', this.itemProperty, searchTerm);
345
+ if (items.length === 0) {
346
+ itemsToPurge.push(index);
347
+ }
348
+ });
349
+
350
+ // sort the selection in descending order
351
+ itemsToPurge.sort((a, b) => b - a);
352
+ itemsToPurge.forEach((itemIndex) => this.deleteItem(itemIndex, false));
353
+ }
354
+ }
@@ -0,0 +1,28 @@
1
+ import { DXFFile } from '../lib/dxf/dxfFile.js';
2
+ import { Property } from '../properties/property.js';
3
+
4
+ /** UCS Class */
5
+ export class UCS {
6
+ /**
7
+ * Create a UCS
8
+ * @param {Object} data
9
+ */
10
+ constructor(data) {
11
+ // DXF Groupcode 5 - Handle
12
+ this.handle = Property.loadValue([data?.handle, data?.[5]]);
13
+ // DXF Groupcode 2 - Name
14
+ this.name = Property.loadValue([data?.name, data?.[2]], '');
15
+ }
16
+
17
+ /**
18
+ * Write the item to file in the dxf format
19
+ * @param {DXFFile} file
20
+ */
21
+ dxf(file) {
22
+ file.writeGroupCode('0', 'UCS', DXFFile.Version.R2000);
23
+ file.writeGroupCode('5', this.handle, DXFFile.Version.R2000);
24
+ file.writeGroupCode('100', 'AcDbSymbolTableRecord', DXFFile.Version.R2000);
25
+ file.writeGroupCode('100', 'AcDbUCSTableRecord', DXFFile.Version.R2000);
26
+ file.writeGroupCode('2', this.name, DXFFile.Version.R2000);
27
+ }
28
+ }