@design-core/core 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +4 -0
- package/TODO.md +49 -6
- package/core/core/core.js +0 -3
- package/core/dimensions/alignedDimension.js +5 -4
- package/core/dimensions/angularDimension.js +6 -5
- package/core/dimensions/baseCircularDimension.js +3 -2
- package/core/dimensions/baseDimension.js +59 -93
- package/core/dimensions/baseLinearDimension.js +6 -5
- package/core/dimensions/diametricDimension.js +4 -3
- package/core/dimensions/dimension.js +21 -14
- package/core/dimensions/radialDimension.js +4 -3
- package/core/dimensions/rotatedDimension.js +12 -11
- package/core/entities/arc.js +112 -145
- package/core/entities/arctext.js +212 -174
- package/core/entities/basePolyline.js +33 -284
- package/core/entities/circle.js +77 -99
- package/core/entities/entity.js +114 -93
- package/core/entities/hatch.js +322 -249
- package/core/entities/insert.js +66 -81
- package/core/entities/line.js +21 -142
- package/core/entities/lwpolyline.js +16 -11
- package/core/entities/polyline.js +4 -4
- package/core/entities/rectangle.js +3 -1
- package/core/entities/solid.js +6 -15
- package/core/entities/text.js +188 -199
- package/core/lib/auxiliary/rubberBand.js +32 -0
- package/core/lib/auxiliary/selectionWindow.js +63 -0
- package/core/lib/auxiliary/snapPoint.js +113 -0
- package/core/lib/auxiliary/trackingLine.js +76 -0
- package/core/lib/canvas.js +228 -166
- package/core/lib/clipboard.js +7 -1
- package/core/lib/colour.js +16 -0
- package/core/lib/commandLine.js +1 -6
- package/core/lib/commandManager.js +18 -8
- package/core/lib/constants.js +28 -0
- package/core/lib/dxf/dxf.js +4 -3
- package/core/lib/entityManager.js +18 -11
- package/core/lib/inputManager.js +36 -13
- package/core/lib/intersect.js +25 -0
- package/core/lib/patterns.js +8 -1
- package/core/lib/plotOptions.js +67 -0
- package/core/lib/polylineUtils.js +75 -0
- package/core/lib/renderers/cairoRenderer.js +371 -0
- package/core/lib/renderers/canvasRenderer.js +315 -0
- package/core/lib/renderers/pdfRenderer.js +366 -0
- package/core/lib/renderers/rendererBase.js +284 -0
- package/core/lib/renderers/svgRenderer.js +343 -0
- package/core/lib/scene.js +27 -5
- package/core/lib/selectionManager.js +2 -2
- package/core/lib/settings.js +4 -2
- package/core/lib/snapping.js +4 -191
- package/core/lib/stateManager.js +30 -1
- package/core/lib/utils.js +21 -2
- package/core/properties/entityProperties.js +104 -0
- package/core/properties/property.js +106 -2
- package/core/properties/propertyManager.js +29 -13
- package/core/tables/block.js +4 -37
- package/core/tables/endblk.js +1 -1
- package/core/tables/layer.js +8 -0
- package/core/tables/styleManagerBase.js +3 -2
- package/core/tables/tableManagerBase.js +8 -3
- package/core/tools/chamfer.js +111 -137
- package/core/tools/chamferFilletBase.js +135 -34
- package/core/tools/copy.js +3 -3
- package/core/tools/explode.js +2 -2
- package/core/tools/extend.js +132 -19
- package/core/tools/fillet.js +86 -183
- package/core/tools/matchProp.js +2 -11
- package/core/tools/mirror.js +7 -6
- package/core/tools/move.js +3 -3
- package/core/tools/offset.js +3 -5
- package/core/tools/pasteclip.js +1 -1
- package/core/tools/rotate.js +6 -3
- package/core/tools/scale.js +1 -1
- package/core/tools/trim.js +265 -23
- package/core/tools/zoom.js +1 -1
- package/jest.config.js +6 -0
- package/package.json +5 -3
- package/test/dimensions/alignedDimension.test.js +14 -7
- package/test/dimensions/angularDimension.test.js +6 -6
- package/test/dimensions/baseDimension.test.js +69 -8
- package/test/dimensions/baseLinearDimension.test.js +62 -0
- package/test/dimensions/diametricDimension.test.js +6 -6
- package/test/dimensions/radialDimension.test.js +6 -6
- package/test/dimensions/rotatedDimension.test.js +14 -7
- package/test/entities/arc.test.js +80 -83
- package/test/entities/arctext.test.js +180 -53
- package/test/entities/basePolyline.test.js +129 -2
- package/test/entities/circle.test.js +57 -85
- package/test/entities/entity.test.js +42 -8
- package/test/entities/hatch.test.js +543 -70
- package/test/entities/insert.test.js +96 -1
- package/test/entities/line.test.js +15 -41
- package/test/entities/lwpolyline.test.js +104 -0
- package/test/entities/polyline.test.js +11 -0
- package/test/entities/rectangle.test.js +11 -0
- package/test/entities/solid.test.js +1 -1
- package/test/entities/text.test.js +294 -69
- package/test/integration/exportIntegration.reference.dxf +9 -9
- package/test/integration/exportIntegration.test.js +2 -2
- package/test/integration/intersectionIntegration.test.js +4 -5
- package/test/integration/pdfRendererIntegration.reference.pdf +17709 -0
- package/test/integration/pdfRendererIntegration.test.js +61 -0
- package/test/integration/svgRendererIntegration.reference.svg +3343 -0
- package/test/integration/svgRendererIntegration.test.js +61 -0
- package/test/integration/userInputIntegration.reference.dxf +1165 -105
- package/test/integration/userInputIntegration.test.js +239 -132
- package/test/lib/canvas.test.js +742 -123
- package/test/lib/constants.test.js +27 -0
- package/test/lib/entityManager.test.js +4 -4
- package/test/lib/inputManager.test.js +80 -19
- package/test/lib/intersect.test.js +83 -0
- package/test/lib/plotOptions.test.js +179 -0
- package/test/lib/rubberBand.test.js +84 -0
- package/test/lib/settings.test.js +5 -6
- package/test/lib/snapping.test.js +71 -129
- package/test/lib/stateManager.test.js +7 -7
- package/test/lib/utils.test.js +36 -2
- package/test/properties/entityProperties.test.js +132 -0
- package/test/properties/property.test.js +53 -0
- package/test/properties/propertyManager.test.js +3 -3
- package/test/renderers/canvasRenderer.test.js +317 -0
- package/test/renderers/pdfRenderer.test.js +271 -0
- package/test/renderers/rendererBase.test.js +213 -0
- package/test/renderers/svgRenderer.test.js +326 -0
- package/test/tables/block.test.js +31 -1
- package/test/tables/endblk.test.js +2 -2
- package/test/tables/layer.test.js +30 -0
- package/test/test-helpers/hatchGridRenderer.js +180 -0
- package/test/test-helpers/test-helpers.js +152 -0
- package/test/tools/chamfer.test.js +227 -5
- package/test/tools/chamferFilletBase.test.js +98 -9
- package/test/tools/copy.test.js +2 -2
- package/test/tools/explode.test.js +3 -3
- package/test/tools/extend.test.js +331 -0
- package/test/tools/fillet.test.js +296 -0
- package/test/tools/matchProp.test.js +5 -5
- package/test/tools/mirror.test.js +13 -13
- package/test/tools/offset.test.js +170 -3
- package/test/tools/pasteclip.test.js +5 -5
- package/test/tools/rotate.test.js +32 -2
- package/test/tools/scale.test.js +5 -5
- package/test/tools/trim.test.js +526 -0
- package/test/tools/zoom.test.js +7 -7
- package/core/lib/selectionWindow.js +0 -83
package/core/lib/stateManager.js
CHANGED
|
@@ -200,7 +200,7 @@ class State {
|
|
|
200
200
|
// capture previous properties for undo
|
|
201
201
|
const previousProperties = {};
|
|
202
202
|
for (const prop of Object.getOwnPropertyNames(stateChange.properties)) {
|
|
203
|
-
previousProperties[prop] = stateChange.entity
|
|
203
|
+
previousProperties[prop] = stateChange.entity.getProperty(prop);
|
|
204
204
|
}
|
|
205
205
|
const undoStateChange = new UpdateState(stateChange.entity, previousProperties);
|
|
206
206
|
this.undoStateChanges.push(undoStateChange);
|
|
@@ -208,6 +208,15 @@ class State {
|
|
|
208
208
|
this.entityManager.update(index, stateChange.properties);
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
|
+
|
|
212
|
+
if (stateChange instanceof ReplaceState) {
|
|
213
|
+
const index = this.entityManager.indexOf(stateChange.entity);
|
|
214
|
+
if (index !== -1) {
|
|
215
|
+
this.entityManager.replace(index, stateChange.replacement);
|
|
216
|
+
const undoStateChange = new ReplaceState(stateChange.replacement, stateChange.entity);
|
|
217
|
+
this.undoStateChanges.push(undoStateChange);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
211
220
|
}
|
|
212
221
|
}
|
|
213
222
|
|
|
@@ -231,6 +240,13 @@ class State {
|
|
|
231
240
|
this.entityManager.update(index, stateChange.properties);
|
|
232
241
|
}
|
|
233
242
|
}
|
|
243
|
+
|
|
244
|
+
if (stateChange instanceof ReplaceState) {
|
|
245
|
+
const index = this.entityManager.indexOf(stateChange.entity);
|
|
246
|
+
if (index !== -1) {
|
|
247
|
+
this.entityManager.replace(index, stateChange.replacement);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
234
250
|
}
|
|
235
251
|
}
|
|
236
252
|
}
|
|
@@ -286,3 +302,16 @@ export class UpdateState extends StateChange {
|
|
|
286
302
|
super(entity, properties);
|
|
287
303
|
}
|
|
288
304
|
}
|
|
305
|
+
|
|
306
|
+
/** Replace State Class */
|
|
307
|
+
export class ReplaceState {
|
|
308
|
+
/**
|
|
309
|
+
* Create Replace State
|
|
310
|
+
* @param {object} entity - the entity to be replaced (used to locate it by reference)
|
|
311
|
+
* @param {object} replacement - the entity to put in its place
|
|
312
|
+
*/
|
|
313
|
+
constructor(entity, replacement) {
|
|
314
|
+
this.entity = entity;
|
|
315
|
+
this.replacement = replacement;
|
|
316
|
+
}
|
|
317
|
+
}
|
package/core/lib/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import { Logging } from './logging.js';
|
|
3
3
|
import { Constants } from './constants.js';
|
|
4
|
+
import { Property } from '../properties/property.js';
|
|
4
5
|
|
|
5
6
|
/** Utils Class */
|
|
6
7
|
export class Utils {
|
|
@@ -114,13 +115,31 @@ export class Utils {
|
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
// Clear handle so a fresh unique handle is assigned when added to the scene
|
|
117
|
-
if (clone.
|
|
118
|
-
clone.
|
|
118
|
+
if (clone.getProperty?.(Property.Names.HANDLE) !== undefined) {
|
|
119
|
+
clone.setProperty?.(Property.Names.HANDLE, undefined);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
return clone;
|
|
122
123
|
}
|
|
123
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Copy display properties from a source entity into a plain data object.
|
|
127
|
+
* Useful when creating a new entity that should inherit the visual properties
|
|
128
|
+
* of an existing one (e.g. the arc produced by Fillet).
|
|
129
|
+
* @param {Entity} entity - source entity
|
|
130
|
+
* @param {Array<string>} properties - property names to copy
|
|
131
|
+
* @return {Object} plain object containing the copied properties
|
|
132
|
+
*/
|
|
133
|
+
static cloneProperties(entity, properties = ['colour', 'layer', 'lineType', 'lineWidth', 'height', 'styleName', 'dimensionStyle', 'patternName', 'scale']) {
|
|
134
|
+
const result = {};
|
|
135
|
+
for (const prop of properties) {
|
|
136
|
+
if (entity.properties?.has(prop)) {
|
|
137
|
+
result[prop] = entity.getProperty(prop);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
|
|
124
143
|
/**
|
|
125
144
|
* Calculate area of triangle given 3 points
|
|
126
145
|
* @param {Point} p1
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Property } from './property.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EntityProperties — typed property store for an entity.
|
|
5
|
+
*
|
|
6
|
+
* Holds a plain-object store of named Property descriptors.
|
|
7
|
+
* Each descriptor owns its value.
|
|
8
|
+
* Using a plain object (rather than a private Map) ensures the store is deep-cloneable by Utils.cloneObject.
|
|
9
|
+
*
|
|
10
|
+
* Computed properties may supply get(entity) and set(entity, value) functions.
|
|
11
|
+
* These are stateless functions (not bound methods) so they survive cloneObject.
|
|
12
|
+
*/
|
|
13
|
+
export class EntityProperties {
|
|
14
|
+
/** @type {Object.<string, Property>} */
|
|
15
|
+
// Store is a plain object to ensure it is deep-cloneable by Utils.cloneObject.
|
|
16
|
+
_store = {};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Register a property.
|
|
20
|
+
* @param {string} name - property name
|
|
21
|
+
* @param {Object} definition - passed directly to the Property constructor
|
|
22
|
+
* @param {string} definition.type - Property.Type constant
|
|
23
|
+
* @param {any} definition.value - initial value
|
|
24
|
+
* @param {boolean} [definition.readOnly=false]
|
|
25
|
+
* @param {boolean} [definition.visible=true]
|
|
26
|
+
* @param {number} [definition.dxfCode]
|
|
27
|
+
* @param {Function} [definition.get] - computed getter: (entity) => value
|
|
28
|
+
* @param {Function} [definition.set] - computed setter: (entity, value) => void
|
|
29
|
+
*/
|
|
30
|
+
add(name, definition) {
|
|
31
|
+
this._store[name] = new Property(definition);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get the current value of a property.
|
|
36
|
+
* For computed properties, invokes get(entity).
|
|
37
|
+
* For stored properties, returns prop.value directly.
|
|
38
|
+
* @param {string} name
|
|
39
|
+
* @param {Object} [entity] - passed to the computed getter when prop.get is defined
|
|
40
|
+
* @return {any} value, or undefined if not registered
|
|
41
|
+
*/
|
|
42
|
+
get(name, entity) {
|
|
43
|
+
const prop = this._store[name];
|
|
44
|
+
if (!prop) return undefined;
|
|
45
|
+
if (prop.get) return prop.get(entity);
|
|
46
|
+
return prop.value;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Set the value of a property.
|
|
51
|
+
* For computed properties, invokes set(entity, value).
|
|
52
|
+
* For stored properties, updates prop.value directly.
|
|
53
|
+
* No-op if the property is not registered or is readOnly.
|
|
54
|
+
* @param {string} name
|
|
55
|
+
* @param {any} value
|
|
56
|
+
* @param {Object} [entity] - passed to the computed setter when prop.set is defined
|
|
57
|
+
*/
|
|
58
|
+
set(name, value, entity) {
|
|
59
|
+
const prop = this._store[name];
|
|
60
|
+
if (!prop) return;
|
|
61
|
+
if (prop.readOnly) return;
|
|
62
|
+
if (prop.set) {
|
|
63
|
+
prop.set(entity, value);
|
|
64
|
+
} else {
|
|
65
|
+
prop.value = value;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check whether a property is registered.
|
|
71
|
+
* @param {string} name
|
|
72
|
+
* @return {boolean}
|
|
73
|
+
*/
|
|
74
|
+
has(name) {
|
|
75
|
+
return name in this._store;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Remove a property from the store.
|
|
80
|
+
* @param {string} name
|
|
81
|
+
*/
|
|
82
|
+
remove(name) {
|
|
83
|
+
delete this._store[name];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Return names of all visible properties in registration order.
|
|
88
|
+
* @return {string[]}
|
|
89
|
+
*/
|
|
90
|
+
list() {
|
|
91
|
+
return Object.entries(this._store)
|
|
92
|
+
.filter(([, prop]) => prop.visible)
|
|
93
|
+
.map(([name]) => name);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Return the full Property descriptor for a named property.
|
|
98
|
+
* @param {string} name
|
|
99
|
+
* @return {Property|undefined}
|
|
100
|
+
*/
|
|
101
|
+
definition(name) {
|
|
102
|
+
return this._store[name];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -2,8 +2,112 @@ import { Flags } from './flags.js';
|
|
|
2
2
|
|
|
3
3
|
/** Property Class */
|
|
4
4
|
export class Property {
|
|
5
|
-
/**
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Create a Property descriptor
|
|
7
|
+
* @param {Object} [options]
|
|
8
|
+
* @param {string} options.type - Property.Type constant describing the value kind
|
|
9
|
+
* @param {any} options.value - initial value
|
|
10
|
+
* @param {boolean} [options.readOnly=false] - when true, set() is a no-op
|
|
11
|
+
* @param {boolean} [options.visible=true] - controls whether the property appears in listings
|
|
12
|
+
* @param {number} [options.dxfCode] - associated DXF group code (informational)
|
|
13
|
+
* @param {Function} [options.get] - computed getter: (entity) => value
|
|
14
|
+
* @param {Function} [options.set] - computed setter: (entity, value) => void
|
|
15
|
+
*/
|
|
16
|
+
constructor({ type, value, readOnly = false, visible = true, dxfCode, get, set, options } = {}) {
|
|
17
|
+
this.type = type;
|
|
18
|
+
this._value = value;
|
|
19
|
+
this.readOnly = readOnly;
|
|
20
|
+
this.visible = visible;
|
|
21
|
+
this.dxfCode = dxfCode;
|
|
22
|
+
this.get = get;
|
|
23
|
+
this.set = set;
|
|
24
|
+
this.options = options;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** @return {any} current value */
|
|
28
|
+
get value() {
|
|
29
|
+
return this._value;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** @param {any} val - new value; ignored when readOnly */
|
|
33
|
+
set value(val) {
|
|
34
|
+
if (!this.readOnly) {
|
|
35
|
+
this._value = val;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Property type constants
|
|
41
|
+
* Used to describe the type of a property value for UI rendering and validation.
|
|
42
|
+
* - NUMBER: numeric value (integer or float)
|
|
43
|
+
* - STRING: text value
|
|
44
|
+
* - BOOLEAN: true/false toggle
|
|
45
|
+
* - LIST: selection from a named set (layer, lineType, hatch pattern, etc.)
|
|
46
|
+
* - COLOUR: RGB colour object
|
|
47
|
+
* - LABEL: read-only display value (no editing)
|
|
48
|
+
*/
|
|
49
|
+
static Type = {
|
|
50
|
+
NUMBER: 'NUMBER',
|
|
51
|
+
STRING: 'STRING',
|
|
52
|
+
BOOLEAN: 'BOOLEAN',
|
|
53
|
+
LIST: 'LIST',
|
|
54
|
+
COLOUR: 'COLOUR',
|
|
55
|
+
LABEL: 'LABEL',
|
|
56
|
+
ENTITIES: 'ENTITIES',
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Canonical property name constants.
|
|
61
|
+
* Use these instead of raw strings when calling getProperty() / setProperty().
|
|
62
|
+
*/
|
|
63
|
+
static Names = Object.freeze({
|
|
64
|
+
// ── Base entity (Entity class) ────────────────────────────────────────────
|
|
65
|
+
HANDLE: 'handle',
|
|
66
|
+
LAYER: 'layer',
|
|
67
|
+
LINETYPE: 'lineType',
|
|
68
|
+
LINEWIDTH: 'lineWidth',
|
|
69
|
+
COLOUR: 'colour',
|
|
70
|
+
POINTS: 'points',
|
|
71
|
+
// ── Shared (multiple entities) ────────────────────────────────────────────
|
|
72
|
+
ANGLE: 'angle',
|
|
73
|
+
BLOCKNAME: 'blockName',
|
|
74
|
+
DIRECTION: 'direction',
|
|
75
|
+
HEIGHT: 'height',
|
|
76
|
+
RADIUS: 'radius',
|
|
77
|
+
ROTATION: 'rotation',
|
|
78
|
+
SCALE: 'scale',
|
|
79
|
+
STRING: 'string',
|
|
80
|
+
STYLENAME: 'styleName',
|
|
81
|
+
// ── BasePolyline ──────────────────────────────────────────────────────────
|
|
82
|
+
CLOSED: 'closed',
|
|
83
|
+
// ── Hatch ─────────────────────────────────────────────────────────────────
|
|
84
|
+
CHILDENTITIES: 'childEntities',
|
|
85
|
+
PATTERNNAME: 'patternName',
|
|
86
|
+
// ── Text ──────────────────────────────────────────────────────────────────
|
|
87
|
+
BACKWARDS: 'backwards',
|
|
88
|
+
HORIZONTALALIGNMENT: 'horizontalAlignment',
|
|
89
|
+
UPSIDEDOWN: 'upsideDown',
|
|
90
|
+
VERTICALALIGNMENT: 'verticalAlignment',
|
|
91
|
+
// ── ArcAlignedText ────────────────────────────────────────────────────────
|
|
92
|
+
ARCSIDE: 'arcSide',
|
|
93
|
+
BOLD: 'bold',
|
|
94
|
+
CHARACTERSPACING: 'characterSpacing',
|
|
95
|
+
FONTNAME: 'fontName',
|
|
96
|
+
ITALIC: 'italic',
|
|
97
|
+
OFFSETFROMARC: 'offsetFromArc',
|
|
98
|
+
OFFSETFROMLEFT: 'offsetFromLeft',
|
|
99
|
+
OFFSETFROMRIGHT: 'offsetFromRight',
|
|
100
|
+
TEXTALIGNMENT: 'textAlignment',
|
|
101
|
+
TEXTORIENTATION: 'textOrientation',
|
|
102
|
+
TEXTREVERSED: 'textReversed',
|
|
103
|
+
UNDERLINE: 'underline',
|
|
104
|
+
WIDTHFACTOR: 'widthFactor',
|
|
105
|
+
// ── Dimensions ────────────────────────────────────────────────────────────
|
|
106
|
+
DIMENSIONSTYLE: 'dimensionStyle',
|
|
107
|
+
LEADERLENGTH: 'leaderLength',
|
|
108
|
+
LINEARDIMANGLE: 'linearDimAngle',
|
|
109
|
+
TEXTOVERRIDE: 'textOverride',
|
|
110
|
+
});
|
|
7
111
|
|
|
8
112
|
/**
|
|
9
113
|
* Parse the input values and return a value
|
|
@@ -46,11 +46,13 @@ export class PropertyManager {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// check if the item has the selected property
|
|
49
|
-
if (!item.
|
|
49
|
+
if (!item.properties?.has(property)) {
|
|
50
50
|
continue;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
const currentValue = item.getProperty(property);
|
|
54
|
+
|
|
55
|
+
if (typeof (currentValue) !== typeof (newPropertyValue)) {
|
|
54
56
|
DesignCore.Core.notify(Strings.Error.INPUT);
|
|
55
57
|
} else {
|
|
56
58
|
// update the item property
|
|
@@ -119,22 +121,36 @@ export class PropertyManager {
|
|
|
119
121
|
const propertiesList = [];
|
|
120
122
|
|
|
121
123
|
subset.forEach((el) => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
propertiesList.push(key);
|
|
124
|
+
if (el.properties) {
|
|
125
|
+
el.properties.list().forEach((key) => {
|
|
126
|
+
if (propertiesList.includes(key) === false) {
|
|
127
|
+
if (subset.every((sub) => sub.properties?.has(key))) {
|
|
128
|
+
propertiesList.push(key);
|
|
129
|
+
}
|
|
129
130
|
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
132
133
|
});
|
|
133
134
|
|
|
134
135
|
return propertiesList;
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Get the Property descriptor for a named property from a representative selected entity.
|
|
141
|
+
* @param {string} itemType
|
|
142
|
+
* @param {string} property
|
|
143
|
+
* @return {Property|undefined}
|
|
144
|
+
*/
|
|
145
|
+
getItemPropertyDefinition(itemType, property) {
|
|
146
|
+
const index = DesignCore.Scene.selectionManager.selectionSet.selectionSet.find((i) => {
|
|
147
|
+
const item = DesignCore.Scene.entities.get(i);
|
|
148
|
+
return (itemType === 'All' || item.type === itemType) && item.properties?.has(property);
|
|
149
|
+
});
|
|
150
|
+
if (index === undefined) return undefined;
|
|
151
|
+
return DesignCore.Scene.entities.get(index).properties.definition(property);
|
|
152
|
+
}
|
|
153
|
+
|
|
138
154
|
/**
|
|
139
155
|
* Get a list the property values
|
|
140
156
|
* @param {string} itemType
|
|
@@ -147,8 +163,8 @@ export class PropertyManager {
|
|
|
147
163
|
if (DesignCore.Scene.selectionManager.selectionSet.selectionSet.length > 0) {
|
|
148
164
|
for (let i = 0; i < DesignCore.Scene.selectionManager.selectionSet.selectionSet.length; i++) {
|
|
149
165
|
if (DesignCore.Scene.entities.get(DesignCore.Scene.selectionManager.selectionSet.selectionSet[i]).type === itemType || itemType === 'All') {
|
|
150
|
-
const
|
|
151
|
-
propertiesValueList.push(
|
|
166
|
+
const entity = DesignCore.Scene.entities.get(DesignCore.Scene.selectionManager.selectionSet.selectionSet[i]);
|
|
167
|
+
propertiesValueList.push(entity.getProperty(property));
|
|
152
168
|
}
|
|
153
169
|
}
|
|
154
170
|
}
|
package/core/tables/block.js
CHANGED
|
@@ -119,6 +119,8 @@ export class Block extends Entity {
|
|
|
119
119
|
const item = DesignCore.Scene.entities.get(index);
|
|
120
120
|
// remove item from scene
|
|
121
121
|
const copyofitem = Utils.cloneObject(item);
|
|
122
|
+
// assign a fresh handle — the block item is a new entity distinct from the scene entity
|
|
123
|
+
copyofitem.setProperty('handle', DesignCore.HandleManager.next());
|
|
122
124
|
// adjust the items points to reflect the insert point
|
|
123
125
|
const delta = new Point(-insertPoint.x, -insertPoint.y);
|
|
124
126
|
if (item.hasOwnProperty('points')) {
|
|
@@ -161,9 +163,9 @@ export class Block extends Entity {
|
|
|
161
163
|
*/
|
|
162
164
|
dxf(file) {
|
|
163
165
|
file.writeGroupCode('0', 'BLOCK');
|
|
164
|
-
file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
|
|
166
|
+
file.writeGroupCode('5', this.getProperty('handle'), DXFFile.Version.R2000); // Handle
|
|
165
167
|
file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
|
|
166
|
-
file.writeGroupCode('8', this.layer);
|
|
168
|
+
file.writeGroupCode('8', this.getProperty('layer'));
|
|
167
169
|
file.writeGroupCode('100', 'AcDbBlockBegin', DXFFile.Version.R2000);
|
|
168
170
|
file.writeGroupCode('2', this.name);
|
|
169
171
|
file.writeGroupCode('70', this.flags.getFlagValue());
|
|
@@ -196,41 +198,6 @@ export class Block extends Entity {
|
|
|
196
198
|
this.items.push(item);
|
|
197
199
|
}
|
|
198
200
|
|
|
199
|
-
/**
|
|
200
|
-
* Draw the entity
|
|
201
|
-
* @param {Object} ctx - context
|
|
202
|
-
* @param {number} scale
|
|
203
|
-
* @param {Object} insert - insert entity
|
|
204
|
-
*/
|
|
205
|
-
draw(ctx, scale, insert = undefined) {
|
|
206
|
-
if (!this.items.length) {
|
|
207
|
-
// nothing to draw
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
this.items.forEach((item) => {
|
|
212
|
-
ctx.save();
|
|
213
|
-
// Use the current item and block insert to set the context
|
|
214
|
-
// insert required for colour ByBlock
|
|
215
|
-
DesignCore.Canvas.setContext(item, ctx, insert);
|
|
216
|
-
|
|
217
|
-
item.draw(ctx, scale);
|
|
218
|
-
ctx.restore();
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
/*
|
|
222
|
-
//////////////////////////////////////////
|
|
223
|
-
// draw test point for location
|
|
224
|
-
ctx.strokeStyle = Colours.rgbToString(colour);
|
|
225
|
-
ctx.lineWidth = 1 / scale;
|
|
226
|
-
ctx.beginPath()
|
|
227
|
-
ctx.moveTo(this.points[0].x, this.points[0].y);
|
|
228
|
-
ctx.arc(this.points[0].x, this.points[0].y, 5 / scale, radians2degrees(0), radians2degrees(360), false);
|
|
229
|
-
ctx.stroke();
|
|
230
|
-
//////////////////////////////////////////
|
|
231
|
-
*/
|
|
232
|
-
}
|
|
233
|
-
|
|
234
201
|
/**
|
|
235
202
|
* Get snap points
|
|
236
203
|
* @param {Point} mousePoint
|
package/core/tables/endblk.js
CHANGED
|
@@ -20,7 +20,7 @@ export class EndBlock extends Entity {
|
|
|
20
20
|
*/
|
|
21
21
|
dxf(file) {
|
|
22
22
|
file.writeGroupCode('0', 'ENDBLK');
|
|
23
|
-
file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
|
|
23
|
+
file.writeGroupCode('5', this.getProperty('handle'), DXFFile.Version.R2000); // Handle
|
|
24
24
|
file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
|
|
25
25
|
// file.writeGroupCode('8', this.layer);
|
|
26
26
|
file.writeGroupCode('100', 'AcDbBlockEnd', DXFFile.Version.R2000);
|
package/core/tables/layer.js
CHANGED
|
@@ -166,6 +166,14 @@ export class Layer {
|
|
|
166
166
|
return false;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Determine if layer is plottable (visible and plotting flag set)
|
|
171
|
+
* @return {boolean}
|
|
172
|
+
*/
|
|
173
|
+
get isPlottable() {
|
|
174
|
+
return this.isVisible && this.plotting;
|
|
175
|
+
}
|
|
176
|
+
|
|
169
177
|
/**
|
|
170
178
|
* Determine if layer is selectable
|
|
171
179
|
* @return {boolean}
|
|
@@ -40,7 +40,7 @@ export class StyleManagerBase extends TableManagerBase {
|
|
|
40
40
|
const selectionSet = [];
|
|
41
41
|
|
|
42
42
|
for (let i = 0; i < DesignCore.Scene.entities.count(); i++) {
|
|
43
|
-
if (DesignCore.Scene.entities.get(i)[this.itemProperty] === style) {
|
|
43
|
+
if ((DesignCore.Scene.entities.get(i).getProperty?.(this.itemProperty) ?? DesignCore.Scene.entities.get(i)[this.itemProperty]) === style) {
|
|
44
44
|
selectionSet.push(i);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -79,7 +79,8 @@ export class StyleManagerBase extends TableManagerBase {
|
|
|
79
79
|
this.addStandardItems();
|
|
80
80
|
|
|
81
81
|
for (let i = 0; i < DesignCore.Scene.entities.count(); i++) {
|
|
82
|
-
const
|
|
82
|
+
const entity = DesignCore.Scene.entities.get(i);
|
|
83
|
+
const style = entity.getProperty?.(this.itemProperty) ?? entity[this.itemProperty];
|
|
83
84
|
this.addItem({
|
|
84
85
|
'name': style,
|
|
85
86
|
});
|
|
@@ -122,10 +122,15 @@ export class TableManagerBase {
|
|
|
122
122
|
return this.getItemByName(newItemName);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
const existingHandle = newItem.getProperty?.('handle') ?? newItem.handle;
|
|
126
|
+
if (existingHandle === undefined) {
|
|
127
|
+
if (newItem.setProperty) {
|
|
128
|
+
newItem.setProperty('handle', DesignCore.HandleManager.next());
|
|
129
|
+
} else {
|
|
130
|
+
newItem.handle = DesignCore.HandleManager.next();
|
|
131
|
+
}
|
|
127
132
|
} else {
|
|
128
|
-
DesignCore.HandleManager.checkHandle(
|
|
133
|
+
DesignCore.HandleManager.checkHandle(existingHandle);
|
|
129
134
|
}
|
|
130
135
|
|
|
131
136
|
if (!exists) {
|