@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,133 @@
1
+ import { DesignCore } from '../designCore.js';
2
+ import { Strings } from './strings.js';
3
+ import { Input } from './input.js';
4
+
5
+ /** PromptOptions Class */
6
+ export class PromptOptions {
7
+ /**
8
+ * Create PromptOptions
9
+ * @param {string} promptMessage
10
+ * @param {Array} types
11
+ * @param {Array} options
12
+ * @param {any} defaultValue
13
+ * @param {string|null} cursor
14
+ */
15
+ constructor(promptMessage = 'error', types = [], options = [], defaultValue = undefined, cursor = null) {
16
+ this.promptMessage = promptMessage;
17
+ this.types = types;
18
+ this.options = options;
19
+ this.defaultValue = defaultValue;
20
+ this.cursor = cursor;
21
+ this.resolve = undefined;
22
+ this.reject = undefined;
23
+ }
24
+
25
+ /**
26
+ * Check if the input matches the accepted types
27
+ * @param {any} input
28
+ * @return {boolean}
29
+ */
30
+ acceptsInput(input) {
31
+ const inputType = Input.getType(input);
32
+ if (this.types.includes(inputType)) return true;
33
+ if (this.types.includes(Input.Type.DYNAMIC) && !isNaN(input)) return true;
34
+ return false;
35
+ }
36
+
37
+ /**
38
+ * Create a new promise for this prompt
39
+ * @return {Promise}
40
+ */
41
+ createPromise() {
42
+ return new Promise((resolve, reject) => {
43
+ this.resolve = resolve;
44
+ this.reject = reject;
45
+ });
46
+ }
47
+
48
+ /**
49
+ * Return data to the input request
50
+ * @param {any} input
51
+ * @return {boolean} true if input was accepted
52
+ */
53
+ respond(input) {
54
+ if (this.acceptsInput(input)) {
55
+ this.resolve(input);
56
+ return true;
57
+ }
58
+
59
+ const matchedOption = this.parseInputToOption(input);
60
+ if (matchedOption !== undefined) {
61
+ this.resolve(matchedOption);
62
+ return true;
63
+ }
64
+
65
+ DesignCore.Core.notify(`${Strings.Error.INPUT}: ${this.promptMessage}`);
66
+ return false;
67
+ }
68
+
69
+ /**
70
+ * Match the input to a command option
71
+ * @param {any} input
72
+ * @return {string} undefined or the matched option
73
+ */
74
+ parseInputToOption(input) {
75
+ // no options to match
76
+ if (this.options.length === 0) {
77
+ return;
78
+ }
79
+
80
+ // can't match non-string values to options
81
+ if (typeof input !== 'string') {
82
+ return;
83
+ }
84
+
85
+ // loop through options to find a match
86
+ for (let i = 0; i < this.options.length; i++) {
87
+ const option = this.options[i];
88
+ // convert the option to uppercase and substring to the input length for comparison
89
+ const optionSubstring = option.toUpperCase().substring(0, input.length);
90
+ if (optionSubstring === input.toUpperCase()) {
91
+ return option;
92
+ }
93
+ }
94
+
95
+ return;
96
+ }
97
+
98
+ /**
99
+ * Cancel the input request by resolving with undefined
100
+ */
101
+ cancel() {
102
+ if (this.resolve) {
103
+ this.resolve(undefined);
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Return the prompt for the input request
109
+ * @return {string}
110
+ */
111
+ getPrompt() {
112
+ let msg = `${this.promptMessage}`;
113
+ if (this.options.length) {
114
+ // Add \u0332 after the first letter of each option to include underscore
115
+ const optionsWithShortcut = this.options.map((option) => this.getOptionWithShortcut(option));
116
+ msg = `${this.promptMessage} ${Strings.Strings.OR} [${optionsWithShortcut}]`;
117
+ }
118
+ if (this.defaultValue !== undefined) {
119
+ msg = `${msg} <${this.defaultValue}>`;
120
+ }
121
+ return msg;
122
+ }
123
+
124
+ /**
125
+ * Underline the shortcut key for the prompt option
126
+ * @param {string} option
127
+ * @return {string} option with shortcut underlined
128
+ */
129
+ getOptionWithShortcut(option) {
130
+ const optionWithShortcut = `${option.substring(0, 1)}\u0332${option.substring(1, option.length)}`;
131
+ return optionWithShortcut;
132
+ }
133
+ }
package/core/lib/scene.js CHANGED
@@ -1,80 +1,76 @@
1
- import {SelectionManager} from './selectionManager.js';
2
- import {Logging} from './logging.js';
3
- import {Strings} from './strings.js';
4
- import {InputManager} from './inputManager.js';
5
- import {DXFFile} from './dxf/dxfFile.js';
6
- import {BoundingBox} from './boundingBox.js';
7
- import {Point} from '../entities/point.js';
8
-
9
- import {DesignCore} from '../designCore.js';
10
-
1
+ import { SelectionManager } from './selectionManager.js';
2
+ import { Logging } from './logging.js';
3
+ import { Strings } from './strings.js';
4
+ import { InputManager } from './inputManager.js';
5
+ import { BoundingBox } from './boundingBox.js';
6
+ import { EntityManager } from './entityManager.js';
7
+ import { Headers } from './headers.js';
8
+
9
+ import { DesignCore } from '../designCore.js';
10
+ import { BlockManager } from '../tables/blockManager.js';
11
+ import { AddState, StateManager, UpdateState } from './stateManager.js';
12
+
13
+ /**
14
+ * Scene Class
15
+ * Holds all entity instances
16
+ */
11
17
  export class Scene {
18
+ /** Create a Scene */
12
19
  constructor() {
13
20
  // initialise the scene variables
14
21
  this.saved = false;
15
22
 
16
- this.items = []; // Main array that stores all the geometry
17
- this.tempItems = []; // Temporary Array to store items while input is being gathered
18
- this.auxiliaryItems = []; // Auxiliary items such as the selection window and snap points
19
-
20
23
  this.selectionManager = new SelectionManager();
21
24
  this.inputManager = new InputManager();
25
+ this.blockManager = new BlockManager();
26
+
27
+ this.entities = new EntityManager();
28
+ this.tempEntities = new EntityManager(false);
29
+ this.auxiliaryEntities = new EntityManager(false);
22
30
 
23
- // store the version of dxf that is currently being used
24
- this.dxfVersion = 'R2018';
31
+ this.stateManager = new StateManager();
32
+
33
+ this.headers = new Headers();
25
34
  }
26
35
 
27
36
  /**
28
- * Reset the scene
37
+ * Sets the save state following scene changes
29
38
  */
39
+ get isModified() {
40
+ return this.stateManager.isModified;
41
+ }
42
+
43
+
44
+ /** Clear the scene of all items */
45
+ clear() {
46
+ this.entities.clear();
47
+ this.tempEntities.clear();
48
+ this.auxiliaryEntities.clear();
49
+ }
50
+
51
+ /** Reset the scene */
30
52
  reset() {
31
- this.tempItems = [];
32
- this.auxiliaryItems = [];
53
+ this.tempEntities.clear();
54
+ this.auxiliaryEntities.clear();
33
55
  this.selectionManager.reset();
34
56
  DesignCore.Canvas.requestPaint();
35
57
  }
36
58
 
37
59
  /**
38
60
  * Get the scene bounding box
39
- * @returns scene bounding box
61
+ * @return {BoundingBox} scene bounding box
40
62
  */
41
63
  boundingBox() {
42
- let xmin; let xmax; let ymin; let ymax;
43
-
44
- if (this.items.length === 0) {
45
- return;
46
- }
47
-
48
- for (let i = 0; i < this.items.length; i++) {
49
- const itemBoundingBox = this.items[i].boundingBox();
50
-
51
- xmin = Math.min(xmin || Infinity, itemBoundingBox.xMin);
52
- xmax = Math.max(xmax || -Infinity, itemBoundingBox.xMax);
53
- ymin = Math.min(ymin || Infinity, itemBoundingBox.yMin);
54
- ymax = Math.max(ymax || -Infinity, itemBoundingBox.yMax);
55
- }
56
-
57
- // if all values are zero return undefined
58
- if (xmin === 0 && xmax === 0, ymin === 0, ymax === 0) {
59
- return;
60
- }
61
-
62
- return new BoundingBox(new Point(xmin, ymin), new Point(xmax, ymax));
63
- }
64
-
65
- /**
66
- * Sets the save state following scene changes
67
- */
68
- saveRequired() {
69
- this.saved = false; // Changes have occured. A save may be required.
64
+ const boundingBox = BoundingBox.fromEntities(this.entities.getAll());
65
+ return boundingBox;
70
66
  }
71
67
 
72
68
  /**
73
69
  * Create and add new items to the scene
74
70
  * @param {string} type - entity type
75
- * @param {object} data - object of entity parameters
71
+ * @param {Object} data - object of entity parameters
76
72
  * @param {number} index - integer of item to replace
77
- * @returns - index of created item
73
+ * @return {number} - index of created item
78
74
  */
79
75
  addItem(type, data, index) {
80
76
  // TODO: validate data is valid for type
@@ -92,12 +88,15 @@ export class Scene {
92
88
  const item = DesignCore.CommandManager.createNew(type, data);
93
89
 
94
90
  if (typeof index === 'undefined') {
95
- // add to end of array
96
- this.items.push(item); // add item to the scene
97
- index = this.items.length - 1;
91
+ // add item to the scene
92
+ const stateChange = new AddState(item);
93
+ this.commit([stateChange]);
94
+ index = this.entities.count() - 1;
98
95
  } else {
99
96
  // replace item at index
100
- this.items.splice(index, 1, item);
97
+ const existingItem = this.entities.get(index);
98
+ const stateChange = new UpdateState(existingItem, data);
99
+ this.commit([stateChange]);
101
100
  }
102
101
 
103
102
  // return the index of the added item
@@ -105,136 +104,34 @@ export class Scene {
105
104
  }
106
105
 
107
106
  /**
108
- * Find items in scene
109
- * @param {string} type - entity type
110
- * @param {string} prop - object of entity parameters
111
- * @param {any} value - value of the property
112
- * @returns - index of items
113
- */
114
- findItem(type, prop, value) {
115
- const filteredItems = [];
116
-
117
- this.items.forEach((item, index) => {
118
- if (item.type.toUpperCase() === type.toUpperCase() && item.hasOwnProperty(prop) && item[prop] === value) {
119
- filteredItems.push(index);
120
- }
121
- });
122
-
123
- return filteredItems;
124
- }
125
-
126
- /**
127
- * Get Item
128
- * @param {number} type - items index
129
- * @returns - item
107
+ * Commit state changes to the scene
108
+ * @param {Array} stateChanges
130
109
  */
131
- getItem(index) {
132
- return this.items[index];
110
+ commit(stateChanges) {
111
+ this.stateManager.commit(this.entities, stateChanges);
133
112
  }
134
113
 
135
114
  /**
136
- * Remove Item
137
- * @param {number} type - items index
138
- * @returns - success status
115
+ * Undo the last action
139
116
  */
140
- removeItem(index) {
141
- const count = this.items.length;
142
- this.items.splice(index, 1);
143
-
144
- if (this.items.length < count) {
145
- return true;
117
+ undo() {
118
+ if (this.stateManager.canUndo()) {
119
+ this.stateManager.undo();
120
+ DesignCore.Canvas.requestPaint();
121
+ } else {
122
+ DesignCore.Core.notify(Strings.Message.NOUNDO);
146
123
  }
147
-
148
- return false;
149
- }
150
-
151
- /**
152
- * Add items to the scenes tempItems
153
- * @param {object} item
154
- */
155
- addToTempItems(item) {
156
- this.tempItems.push(item); // Add it to the tempItems Array
157
- }
158
-
159
- /**
160
- * Add items to the scenes auxiliary items
161
- * @param {object} item
162
- */
163
- addToAuxiliaryItems(item) {
164
- this.auxiliaryItems.push(item); // Add it to the auxiliary Array
165
124
  }
166
125
 
167
126
  /**
168
- * Create a new temp item and add to scenes tempItems
169
- * @param {string} type - entity type
170
- * @param {object} data - object of entity parameters
127
+ * Redo the last undone action
171
128
  */
172
- createTempItem(type, data) {
173
- const helper = DesignCore.CommandManager.createNew(type, data);
174
- this.addToTempItems(helper);
175
- }
176
-
177
- dxf(file) {
178
- let width = 0;
179
- let height = 0;
180
- let viewCenterX = 0;
181
- let viewCenterY = 0;
182
- let ratio = 0;
183
-
184
- const extents = this.boundingBox();
185
-
186
- if (extents) {
187
- width = extents.xLength;
188
- height = extents.yLength;
189
- viewCenterX = extents.xMin + width / 2;
190
- viewCenterY = extents.yMin + height / 2;
191
- ratio = width / height;
129
+ redo() {
130
+ if (this.stateManager.canRedo()) {
131
+ this.stateManager.redo();
132
+ DesignCore.Canvas.requestPaint();
133
+ } else {
134
+ DesignCore.Core.notify(Strings.Message.NOREDO);
192
135
  }
193
-
194
- file.writeGroupCode('0', 'TABLE');
195
- file.writeGroupCode('2', 'VPORT'); // Table Name
196
- file.writeGroupCode('5', file.nextHandle(), DXFFile.Version.R2000); // Handle
197
- file.writeGroupCode('100', 'AcDbSymbolTable', DXFFile.Version.R2000);
198
- file.writeGroupCode('70', '1'); // Number of entries in table
199
- file.writeGroupCode('0', 'VPORT');
200
- file.writeGroupCode('5', file.nextHandle(), DXFFile.Version.R2000); // Handle
201
- file.writeGroupCode('100', 'AcDbSymbolTableRecord', DXFFile.Version.R2000);
202
- file.writeGroupCode('100', 'AcDbViewportTableRecord', DXFFile.Version.R2000);
203
- file.writeGroupCode('2', '*ACTIVE');
204
- file.writeGroupCode('70', '0'); // vport flags
205
- file.writeGroupCode('10', '0.0'); // lower left corner x pos
206
- file.writeGroupCode('20', '0.0'); // lower left corner y pos
207
- file.writeGroupCode('11', '1.0'); // upper right corner x pos
208
- file.writeGroupCode('21', '1.0'); // upper right corner y pos
209
- file.writeGroupCode('12', viewCenterX); // view centre x pos
210
- file.writeGroupCode('22', viewCenterY); // view centre y pos
211
- file.writeGroupCode('13', '0.0'); // snap base point x
212
- file.writeGroupCode('23', '0.0'); // snap base point y
213
- file.writeGroupCode('14', '10.0'); // snap spacing x
214
- file.writeGroupCode('24', '10.0'); // snap spacing y
215
- file.writeGroupCode('15', '10.0'); // grid spacing x
216
- file.writeGroupCode('25', '10.0'); // grid spacing y
217
- file.writeGroupCode('16', '0.0'); // view direction (x) from target point
218
- file.writeGroupCode('26', '0.0'); // view direction (y) from target point
219
- file.writeGroupCode('36', '1.0'); // view direction (z) from target point
220
- file.writeGroupCode('17', '0.0'); // view target point x
221
- file.writeGroupCode('27', '0.0'); // view target point y
222
- file.writeGroupCode('37', '0.0'); // view target point z
223
- file.writeGroupCode('40', height); // VPort Height
224
- file.writeGroupCode('41', ratio); // Vport height/width ratio
225
- file.writeGroupCode('42', '50.0'); // Lens Length
226
- file.writeGroupCode('43', '0.0');// Front Clipping Plane
227
- file.writeGroupCode('44', '0.0'); // Back Clipping Plane
228
- file.writeGroupCode('50', '0.0'); // Snap Rotation Angle
229
- file.writeGroupCode('51', '0.0'); // View Twist Angle
230
- file.writeGroupCode('71', '0.0'); // Viewmode (System constiable)
231
- file.writeGroupCode('72', '1000'); // Circle sides
232
- file.writeGroupCode('73', '1'); // fast zoom setting
233
- file.writeGroupCode('74', '3');// UCSICON Setting
234
- file.writeGroupCode('75', '0'); // snap on/off
235
- file.writeGroupCode('76', '1'); // grid on/off
236
- file.writeGroupCode('77', '0'); // snap style
237
- file.writeGroupCode('78', '0'); // snap isopair
238
- file.writeGroupCode('0', 'ENDTAB');
239
136
  }
240
137
  }
@@ -1,23 +1,41 @@
1
- import {Utils} from './utils.js';
2
- import {SelectionWindow} from './selectionWindow.js';
3
- import {DesignCore} from '../designCore.js';
1
+ import { Utils } from './utils.js';
2
+ import { Point } from '../entities/point.js';
3
+ import { SelectionWindow } from './selectionWindow.js';
4
+ import { DesignCore } from '../designCore.js';
4
5
 
6
+ /** SingleSelection Class */
5
7
  export class SingleSelection {
8
+ /**
9
+ * Create a SingleSelection
10
+ * @param {number} index
11
+ * @param {Point} point
12
+ */
6
13
  constructor(index, point) {
7
14
  this.selectedItemIndex = index;
8
15
  this.selectedPoint = point;
9
16
  }
10
17
  }
11
18
 
19
+ /** SelectionSet Class */
12
20
  export class SelectionSet {
21
+ /** Create SelectionSet */
13
22
  constructor() {
14
23
  this.accepted = false;
15
24
  this.selectionSet = [];
16
25
  }
26
+
27
+ /**
28
+ * Remove the last selection from the selectionSet
29
+ */
30
+ removeLastSelection() {
31
+ this.selectionSet.pop();
32
+ }
17
33
  }
18
34
 
19
35
  // TODO: Refactor class.
36
+ /** Selection Manager Class */
20
37
  export class SelectionManager {
38
+ /** Create a SelectionManager */
21
39
  constructor() {
22
40
  this.selectionSet = new SelectionSet(); // store a list of selected items indices
23
41
  this.selectedItems = []; // store a copy of selected items
@@ -32,6 +50,15 @@ export class SelectionManager {
32
50
  this.selectionSetChanged();
33
51
  }
34
52
 
53
+ /**
54
+ * Remove the last selection from the selected items
55
+ */
56
+ removeLastSelection() {
57
+ this.selectedItems.pop();
58
+ this.selectionSet.removeLastSelection();
59
+ this.selectionSetChanged();
60
+ }
61
+
35
62
  /**
36
63
  * Handle selection set changes
37
64
  */
@@ -52,7 +79,7 @@ export class SelectionManager {
52
79
  points: selectionPoints,
53
80
  };
54
81
 
55
- DesignCore.Scene.addToAuxiliaryItems(new SelectionWindow(data));
82
+ DesignCore.Scene.auxiliaryEntities.add(new SelectionWindow(data));
56
83
  }
57
84
 
58
85
  /**
@@ -60,19 +87,19 @@ export class SelectionManager {
60
87
  */
61
88
  windowSelect() {
62
89
  const selectionRect = this.getSelectionRect();
63
- const crossingSelect = DesignCore.Mouse.pointOnScene().y >DesignCore.Mouse.transformToScene(DesignCore.Mouse.mouseDownCanvasPoint).y;
90
+ const crossingSelect = DesignCore.Mouse.pointOnScene().y > DesignCore.Mouse.transformToScene(DesignCore.Mouse.mouseDownCanvasPoint).y;
64
91
 
65
92
  if (selectionRect !== undefined) {
66
- // Loop through all the entities and see if it should be selected
67
- for (let i = 0; i <DesignCore.Scene.items.length; i++) {
68
- // check if the item is within the selection rect
69
- if (DesignCore.Scene.items[i].within(selectionRect)) {
93
+ // Loop through all the entities and see if it should be selected
94
+ for (let i = 0; i < DesignCore.Scene.entities.count(); i++) {
95
+ // check if the item is within the selection rect
96
+ if (DesignCore.Scene.entities.get(i).within(selectionRect)) {
70
97
  this.addToSelectionSet(i);
71
98
  }
72
99
 
73
100
  if (crossingSelect) {
74
- // check if the item is touched / crossed by the selection rect
75
- if (DesignCore.Scene.items[i].touched(selectionRect)) {
101
+ // check if the item is touched / crossed by the selection rect
102
+ if (DesignCore.Scene.entities.get(i).touched(selectionRect)) {
76
103
  this.addToSelectionSet(i);
77
104
  }
78
105
  }
@@ -85,24 +112,23 @@ export class SelectionManager {
85
112
 
86
113
  /**
87
114
  * Get the rectangle points formed between mouseDown and current mouse location
88
- * @return {array} selectionRect - [x1, x2, y1, y2]
115
+ * @return {Object} selectionRect - {min: Point, max: Point}
89
116
  */
90
117
  getSelectionRect() {
91
- // TODO: It would be nice if this returned an object {xmin: xmin, ymin:ymin ...}
92
- const xmin = Math.min(DesignCore.Mouse.transformToScene(DesignCore.Mouse.mouseDownCanvasPoint).x, DesignCore.Mouse.pointOnScene().x);
93
- const xmax = Math.max(DesignCore.Mouse.transformToScene(DesignCore.Mouse.mouseDownCanvasPoint).x, DesignCore.Mouse.pointOnScene().x);
94
- const ymin = Math.min(DesignCore.Mouse.transformToScene(DesignCore.Mouse.mouseDownCanvasPoint).y, DesignCore.Mouse.pointOnScene().y);
95
- const ymax = Math.max(DesignCore.Mouse.transformToScene(DesignCore.Mouse.mouseDownCanvasPoint).y, DesignCore.Mouse.pointOnScene().y);
118
+ const p1 = DesignCore.Mouse.transformToScene(DesignCore.Mouse.mouseDownCanvasPoint);
119
+ const p2 = DesignCore.Mouse.pointOnScene();
96
120
 
97
- const selectionRect = [xmin, xmax, ymin, ymax];
98
-
99
- return selectionRect;
121
+ return {
122
+ min: new Point(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y)),
123
+ max: new Point(Math.max(p1.x, p2.x), Math.max(p1.y, p2.y)),
124
+ };
100
125
  }
101
126
 
102
127
 
103
128
  /**
104
129
  * Select the item closest to the mouse and add it to the selection set
105
- * @returns {SingleSelection} - return single selection
130
+ * @param {Point} point
131
+ * @return {SingleSelection} - return single selection
106
132
  */
107
133
  singleSelect(point) {
108
134
  const closestItemIndex = this.findClosestItem(point);
@@ -120,34 +146,15 @@ export class SelectionManager {
120
146
  /**
121
147
  * Find closest item to point
122
148
  * @param {Point} point
123
- * @returns {Integer} - return index of closest item or undefined
149
+ * @return {number} - return index of closest item or undefined
124
150
  */
125
151
  findClosestItem(point) {
126
- let delta = 1.65 /DesignCore.Core.canvas.getScale(); // find a more suitable starting value
127
- let closestItemIndex;
128
-
129
- for (let i = 0; i <DesignCore.Scene.items.length; i++) {
130
- // check the items layer is selectable - i.e. on, thawed, etc...
131
- const layer = DesignCore.LayerManager.getStyleByName(DesignCore.Scene.items[i].layer);
132
-
133
- if (!layer.isSelectable) {
134
- continue;
135
- }
136
-
137
- const distance = DesignCore.Scene.items[i].closestPoint(point)[1]; // ClosestPoint()[1] returns a distance to the closest point
138
-
139
- if (distance < delta) {
140
- delta = distance;
141
- closestItemIndex = i;
142
- }
143
- }
144
-
145
- return closestItemIndex;
152
+ return DesignCore.Scene.entities.findClosest(point);
146
153
  }
147
154
 
148
155
  /**
149
156
  * Remove the item at index from the selectionSet and selectedItems
150
- * @param {Integer} index - index of the item in scene.items
157
+ * @param {number} index - index of the item
151
158
  */
152
159
  removeFromSelectionSet(index) {
153
160
  const itemIndex = this.selectionSet.selectionSet.indexOf(index);
@@ -159,7 +166,7 @@ export class SelectionManager {
159
166
 
160
167
  /**
161
168
  * Add the item at index to the selectionSet and selectedItems
162
- * @param {Integer} index
169
+ * @param {number} index
163
170
  */
164
171
  addToSelectionSet(index) {
165
172
  if (index === undefined) {
@@ -174,12 +181,10 @@ export class SelectionManager {
174
181
 
175
182
  /**
176
183
  * Duplicate the item at index and add to selectedItems
177
- * @param {Integer} index
184
+ * @param {number} index
178
185
  */
179
186
  addToSelectedItems(index) {
180
- const copyofitem = Utils.cloneObject(DesignCore.Scene.items[index]);
181
- copyofitem.colour = DesignCore.Core.settings.selecteditemscolour.toString();
182
- copyofitem.lineWidth = copyofitem.lineWidth * 2;
187
+ const copyofitem = Utils.cloneObject(DesignCore.Scene.entities.get(index));
183
188
  this.selectedItems.push(copyofitem);
184
189
  }
185
190
 
@@ -196,4 +201,25 @@ export class SelectionManager {
196
201
 
197
202
  DesignCore.Core.canvas.requestPaint();
198
203
  }
204
+
205
+ /**
206
+ * Select all items on the canvas
207
+ */
208
+ selectAll() {
209
+ // Clear current selection
210
+ this.reset();
211
+
212
+ // Add all selectable items to the selection
213
+ for (let i = 0; i < DesignCore.Scene.entities.count(); i++) {
214
+ const layer = DesignCore.LayerManager.getItemByName(DesignCore.Scene.entities.get(i).layer);
215
+
216
+ // Only select items on selectable layers
217
+ if (layer?.isSelectable) {
218
+ this.addToSelectionSet(i);
219
+ }
220
+ }
221
+
222
+ this.selectionSetChanged();
223
+ DesignCore.Core.canvas.requestPaint();
224
+ }
199
225
  }