circuitscript 0.1.0 → 0.1.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 (61) hide show
  1. package/dist/cjs/BaseVisitor.js +13 -8
  2. package/dist/cjs/antlr/CircuitScriptLexer.js +80 -80
  3. package/dist/cjs/antlr/CircuitScriptParser.js +599 -657
  4. package/dist/cjs/builtinMethods.js +27 -8
  5. package/dist/cjs/draw_symbols.js +320 -197
  6. package/dist/cjs/execute.js +114 -116
  7. package/dist/cjs/export.js +2 -4
  8. package/dist/cjs/geometry.js +52 -19
  9. package/dist/cjs/globals.js +17 -12
  10. package/dist/cjs/helpers.js +16 -3
  11. package/dist/cjs/layout.js +473 -354
  12. package/dist/cjs/logger.js +8 -1
  13. package/dist/cjs/objects/ClassComponent.js +22 -22
  14. package/dist/cjs/objects/ExecutionScope.js +10 -4
  15. package/dist/cjs/objects/Frame.js +11 -2
  16. package/dist/cjs/objects/ParamDefinition.js +123 -4
  17. package/dist/cjs/objects/PinDefinition.js +1 -4
  18. package/dist/cjs/render.js +76 -138
  19. package/dist/cjs/sizing.js +33 -7
  20. package/dist/cjs/utils.js +86 -2
  21. package/dist/cjs/visitor.js +224 -255
  22. package/dist/esm/BaseVisitor.mjs +15 -10
  23. package/dist/esm/antlr/CircuitScriptLexer.mjs +80 -80
  24. package/dist/esm/antlr/CircuitScriptParser.mjs +599 -657
  25. package/dist/esm/builtinMethods.mjs +24 -8
  26. package/dist/esm/draw_symbols.mjs +322 -200
  27. package/dist/esm/execute.mjs +116 -118
  28. package/dist/esm/export.mjs +2 -4
  29. package/dist/esm/geometry.mjs +52 -19
  30. package/dist/esm/globals.mjs +17 -12
  31. package/dist/esm/helpers.mjs +17 -4
  32. package/dist/esm/layout.mjs +479 -360
  33. package/dist/esm/logger.mjs +8 -1
  34. package/dist/esm/objects/ClassComponent.mjs +21 -26
  35. package/dist/esm/objects/ExecutionScope.mjs +10 -4
  36. package/dist/esm/objects/Frame.mjs +10 -1
  37. package/dist/esm/objects/ParamDefinition.mjs +122 -3
  38. package/dist/esm/objects/PinDefinition.mjs +0 -2
  39. package/dist/esm/render.mjs +79 -141
  40. package/dist/esm/sizing.mjs +34 -8
  41. package/dist/esm/utils.mjs +80 -1
  42. package/dist/esm/visitor.mjs +226 -257
  43. package/dist/types/BaseVisitor.d.ts +1 -1
  44. package/dist/types/antlr/CircuitScriptParser.d.ts +2 -3
  45. package/dist/types/draw_symbols.d.ts +72 -45
  46. package/dist/types/execute.d.ts +15 -10
  47. package/dist/types/geometry.d.ts +31 -19
  48. package/dist/types/globals.d.ts +15 -11
  49. package/dist/types/helpers.d.ts +2 -1
  50. package/dist/types/layout.d.ts +35 -54
  51. package/dist/types/logger.d.ts +1 -1
  52. package/dist/types/objects/ClassComponent.d.ts +19 -16
  53. package/dist/types/objects/ExecutionScope.d.ts +3 -2
  54. package/dist/types/objects/Frame.d.ts +9 -2
  55. package/dist/types/objects/ParamDefinition.d.ts +32 -2
  56. package/dist/types/objects/PinDefinition.d.ts +0 -2
  57. package/dist/types/render.d.ts +2 -1
  58. package/dist/types/utils.d.ts +14 -1
  59. package/dist/types/visitor.d.ts +4 -5
  60. package/libs/lib.cst +25 -8
  61. package/package.json +7 -3
@@ -1,16 +1,16 @@
1
1
  import { Graph, alg } from '@dagrejs/graphlib';
2
- import { SymbolCustom, SymbolDrawing, SymbolFactory, SymbolCustomModule, SymbolPlaceholder, SymbolText, PlaceHolderCommands } from "./draw_symbols.mjs";
2
+ import { SymbolCustom, SymbolDrawing, SymbolCustomModule, SymbolPlaceholder, SymbolText, PlaceHolderCommands } from "./draw_symbols.mjs";
3
3
  import { FrameAction, SequenceAction } from "./objects/ExecutionScope.mjs";
4
- import { defaultFrameTitleTextSize, defaultGridSizeUnits, FrameType, GlobalNames, ParamKeys, WireAutoDirection } from './globals.mjs';
5
- import { Geometry } from './geometry.mjs';
4
+ import { ComponentTypes, defaultFrameTitleTextSize, defaultGridSizeUnits, FrameType, ParamKeys, SymbolPinSide, WireAutoDirection } from './globals.mjs';
5
+ import { Geometry, HorizontalAlign, VerticalAlign } from './geometry.mjs';
6
6
  import { Logger } from './logger.mjs';
7
- import { Frame, FrameParamKeys, FramePlotDirection } from './objects/Frame.mjs';
8
- import { combineMaps, getBoundsSize, printBounds, resizeBounds, resizeToNearestGrid, roundValue, toNearestGrid } from './utils.mjs';
7
+ import { FixedFrameIds, Frame, FrameParamKeys, FramePlotDirection } from './objects/Frame.mjs';
8
+ import { areasOverlap, combineMaps, getBoundsSize, printBounds, resizeBounds, resizeToNearestGrid, roundValue, toNearestGrid } from './utils.mjs';
9
9
  import { Direction } from './objects/types.mjs';
10
10
  import { milsToMM, UnitDimension } from './helpers.mjs';
11
+ import { numeric, NumericValue } from './objects/ParamDefinition.mjs';
11
12
  export class LayoutEngine {
12
13
  logger;
13
- placeSubgraphVersion = 2;
14
14
  layoutWarnings = [];
15
15
  showBaseFrame = false;
16
16
  constructor(options = { showBaseFrame: false }) {
@@ -113,8 +113,8 @@ export class LayoutEngine {
113
113
  const allLines = wires.map(wire => {
114
114
  return wire.points.map(pt => {
115
115
  return {
116
- x: wire.x + pt.x,
117
- y: wire.y + pt.y,
116
+ x: wire.x.add(pt.x),
117
+ y: wire.y.add(pt.y),
118
118
  };
119
119
  });
120
120
  });
@@ -125,7 +125,7 @@ export class LayoutEngine {
125
125
  intersectPoints,
126
126
  });
127
127
  intersectPoints.forEach(([x, y]) => {
128
- junctions.push(new RenderJunction(x, y));
128
+ junctions.push(new RenderJunction(numeric(x), numeric(y)));
129
129
  });
130
130
  }
131
131
  return {
@@ -135,21 +135,21 @@ export class LayoutEngine {
135
135
  }
136
136
  placeFrames(graph, subgraphInfo, frameObjects) {
137
137
  const baseFrame = frameObjects[0];
138
- baseFrame.padding = 0;
139
- baseFrame.borderWidth = 0;
138
+ baseFrame.padding = numeric(0);
139
+ baseFrame.borderWidth = numeric(0);
140
140
  if (this.showBaseFrame) {
141
- baseFrame.borderWidth = 5;
142
- baseFrame.width = 11692 - 400 * 2;
143
- baseFrame.height = 8267 - 400 * 2;
141
+ baseFrame.borderWidth = numeric(5);
142
+ baseFrame.width = numeric(11692 - 400 * 2);
143
+ baseFrame.height = numeric(8267 - 400 * 2);
144
144
  }
145
- baseFrame.x = 0;
146
- baseFrame.y = 0;
147
- let textObjects = [];
148
- let elementFrames = [];
145
+ baseFrame.x = numeric(0);
146
+ baseFrame.y = numeric(0);
149
147
  baseFrame.bounds = {
150
148
  xmin: 0, ymin: 0,
151
149
  xmax: 0, ymax: 0,
152
150
  };
151
+ let textObjects = [];
152
+ let elementFrames = [];
153
153
  if (subgraphInfo.length > 0) {
154
154
  const result = this.prepareFrames(graph, subgraphInfo, baseFrame);
155
155
  textObjects = result.textObjects;
@@ -174,10 +174,10 @@ export class LayoutEngine {
174
174
  const innerItems = frame.innerItems;
175
175
  const frames = [];
176
176
  innerItems.forEach(item => {
177
- if (item.type === RenderFrameType.Elements) {
177
+ if (item.renderType === RenderFrameType.Elements) {
178
178
  frames.push(item);
179
179
  }
180
- else if (item.type === RenderFrameType.Container) {
180
+ else if (item.renderType === RenderFrameType.Container) {
181
181
  const innerFrames = this.collectElementFrames(item, level + 1);
182
182
  frames.push(...innerFrames);
183
183
  }
@@ -189,18 +189,20 @@ export class LayoutEngine {
189
189
  const innerItems = frame.innerItems;
190
190
  innerItems.forEach(innerFrame => {
191
191
  if (innerFrame.frame.frameType === FrameType.Sheet) {
192
- innerFrame.x = 0;
193
- innerFrame.y = 0;
192
+ innerFrame.x = numeric(0);
193
+ innerFrame.y = numeric(0);
194
194
  }
195
195
  else {
196
- innerFrame.x += frame.x;
197
- innerFrame.y += frame.y;
196
+ innerFrame.x = innerFrame.x.add(frame.x);
197
+ innerFrame.y = innerFrame.y.add(frame.y);
198
198
  }
199
- if (innerFrame.type === RenderFrameType.Elements) {
199
+ if (innerFrame.renderType === RenderFrameType.Elements) {
200
200
  this.print(level, "".padStart(level * 4), 'element frame', innerFrame.x, innerFrame.y);
201
- innerFrame.innerItems.forEach(item2 => {
202
- item2.x += innerFrame.x - innerFrame.translateX;
203
- item2.y += innerFrame.y - innerFrame.translateY;
201
+ const diffX = innerFrame.x.sub(innerFrame.translateX);
202
+ const diffY = innerFrame.y.sub(innerFrame.translateY);
203
+ innerFrame.innerItems.forEach(item => {
204
+ item.x = item.x.add(diffX);
205
+ item.y = item.y.add(diffY);
204
206
  });
205
207
  }
206
208
  else {
@@ -212,11 +214,10 @@ export class LayoutEngine {
212
214
  placeAndSizeFrame(frame, level = 0) {
213
215
  const innerFrames = frame.innerItems;
214
216
  const gridSize = defaultGridSizeUnits;
215
- let accumX = 0;
216
- let accumY = 0;
217
+ const frameDirection = frame.direction;
217
218
  const boundPoints = [];
218
219
  const frameSizes = innerFrames.map(innerFrame => {
219
- if (innerFrame.type === RenderFrameType.Elements) {
220
+ if (innerFrame.renderType === RenderFrameType.Elements) {
220
221
  innerFrame.bounds = resizeToNearestGrid(innerFrame.bounds, gridSize);
221
222
  innerFrame.translateX = innerFrame.bounds.xmin;
222
223
  innerFrame.translateY = innerFrame.bounds.ymin;
@@ -230,10 +231,14 @@ export class LayoutEngine {
230
231
  const { width } = getBoundsSize(item);
231
232
  return width;
232
233
  }));
234
+ const maxHeight = Math.max(...frameSizes.map(item => {
235
+ const { height } = getBoundsSize(item);
236
+ return height;
237
+ }));
233
238
  let accumRowWidth = 0;
234
- let titleFrameWidth = null;
239
+ let titleFrameWidth = 0;
235
240
  const inRowShouldCenterInnerFrames = true;
236
- if (frame.direction === FramePlotDirection.Row) {
241
+ if (frameDirection === FramePlotDirection.Row) {
237
242
  accumRowWidth = frameSizes.reduce((accum, item, index) => {
238
243
  const { width } = getBoundsSize(item);
239
244
  if (frame.innerItems[index].containsTitle) {
@@ -241,85 +246,252 @@ export class LayoutEngine {
241
246
  return accum;
242
247
  }
243
248
  return accum + width +
244
- ((index + 1 < frameSizes.length) ? frame.gap : 0);
249
+ ((index + 1 < frameSizes.length) ? frame.gap.toNumber() : 0);
245
250
  }, 0);
246
251
  }
247
252
  else {
248
253
  accumRowWidth = maxWidth;
249
254
  }
255
+ let frameWidth = numeric(0);
256
+ let frameHeight = numeric(0);
257
+ let frameXMin = numeric(0);
258
+ let frameYMin = numeric(0);
259
+ const frameParams = frame.frame.parameters;
260
+ const avoidAreas = [];
261
+ if (frameParams.has(FrameParamKeys.SheetType)) {
262
+ const frameComponent = frameParams.get(FrameParamKeys.SheetType);
263
+ const frameDrawing = frameComponent.displayProp;
264
+ frameDrawing.variables = combineMaps(frameComponent.parameters, frameParams);
265
+ const rects = ExtractDrawingRects(frameDrawing);
266
+ const drawableRect = rects.find(rect => rect.className === 'plot-area');
267
+ let frameMinX = numeric(0);
268
+ let frameMinY = numeric(0);
269
+ if (drawableRect) {
270
+ frameMinX = milsToMM(drawableRect.x);
271
+ frameMinY = milsToMM(drawableRect.y);
272
+ frameWidth = milsToMM(drawableRect.width);
273
+ frameHeight = milsToMM(drawableRect.height);
274
+ }
275
+ const infoAreaRect = rects.filter(rect => rect.className === 'keepout-area');
276
+ infoAreaRect.forEach(area => {
277
+ const x1 = area.x;
278
+ const y1 = area.y;
279
+ const x2 = area.x.add(area.width);
280
+ const y2 = area.y.add(area.height);
281
+ avoidAreas.push([
282
+ milsToMM(x1).sub(frameMinX).toNumber(),
283
+ milsToMM(y1).sub(frameMinY).toNumber(),
284
+ milsToMM(x2).sub(frameMinX).toNumber(),
285
+ milsToMM(y2).sub(frameMinY).toNumber(),
286
+ ]);
287
+ });
288
+ }
289
+ else {
290
+ if (frame.width !== null) {
291
+ frameWidth = frame.width;
292
+ }
293
+ if (frame.height !== null) {
294
+ frameHeight = frame.height;
295
+ }
296
+ }
250
297
  const offsetX = frame.padding;
251
298
  const offsetY = frame.padding;
252
299
  let centeredOffsetX = 0;
253
300
  let widthForTitle;
254
- if (titleFrameWidth > accumRowWidth) {
301
+ if (frameWidth.toNumber() !== 0) {
302
+ widthForTitle = frameWidth.toNumber();
303
+ }
304
+ else if (titleFrameWidth > accumRowWidth) {
255
305
  widthForTitle = titleFrameWidth;
256
306
  }
257
307
  else {
258
308
  widthForTitle = accumRowWidth;
259
309
  }
260
- if (frame.direction === FramePlotDirection.Row &&
310
+ if (frameDirection === FramePlotDirection.Row &&
261
311
  inRowShouldCenterInnerFrames &&
262
312
  titleFrameWidth !== null && titleFrameWidth > accumRowWidth) {
263
- centeredOffsetX = toNearestGrid(titleFrameWidth / 2 - accumRowWidth / 2, gridSize);
313
+ centeredOffsetX =
314
+ toNearestGrid(titleFrameWidth / 2 - accumRowWidth / 2, gridSize);
264
315
  }
265
- innerFrames.forEach(innerFrame => {
266
- const { width: frameWidth, height: frameHeight } = getBoundsSize(innerFrame.bounds);
316
+ let title_align = HorizontalAlign.Middle;
317
+ if (frameParams.has(FrameParamKeys.TitleAlign)) {
318
+ title_align = frameParams.get(FrameParamKeys.TitleAlign);
319
+ }
320
+ let accumX = numeric(0);
321
+ let accumY = numeric(0);
322
+ innerFrames.forEach((innerFrame, index) => {
323
+ const { width: innerFrameWidth, height: innerFrameHeight } = getBoundsSize(innerFrame.bounds);
324
+ let arrangeLineAttempts = 0;
325
+ const maxAttempts = 10;
326
+ let innerFrameX = numeric(0);
327
+ let innerFrameY = numeric(0);
267
328
  if (innerFrame.containsTitle) {
268
- innerFrame.x = offsetX + accumX + toNearestGrid(widthForTitle / 2 - frameWidth / 2, gridSize);
269
- innerFrame.y = offsetY + accumY;
270
- accumY += (frameHeight + frame.gap);
329
+ innerFrame.x = offsetX.add(accumX);
330
+ innerFrame.y = offsetY.add(accumY);
331
+ accumY = accumY.add(innerFrameHeight).add(frame.gap);
271
332
  }
272
333
  else {
273
- if (frame.direction === FramePlotDirection.Column) {
274
- innerFrame.x = offsetX + accumX + toNearestGrid(maxWidth / 2 - frameWidth / 2, gridSize);
275
- innerFrame.y = offsetY + accumY;
276
- accumY += (frameHeight + frame.gap);
334
+ if (frameDirection === FramePlotDirection.Column) {
335
+ innerFrameX = offsetX.add(accumX);
336
+ innerFrameY = offsetY.add(accumY);
337
+ while (arrangeLineAttempts < maxAttempts) {
338
+ const innerFrameY2 = innerFrameY.toNumber() + innerFrameHeight;
339
+ const doesExceedFrameHeight = (frameHeight.toNumber() > 0
340
+ && innerFrameY2 > frameHeight.toNumber());
341
+ const { xmax } = getBoundsFromPoints(boundPoints);
342
+ const tmpX1 = innerFrameX.toNumber();
343
+ const tmpY1 = innerFrameY.toNumber();
344
+ const tmpX2 = tmpX1 + innerFrameWidth;
345
+ const tmpY2 = tmpY1 + innerFrameHeight;
346
+ const frameArea = [tmpX1, tmpY1, tmpX2, tmpY2];
347
+ const overlaps = avoidAreas.filter(area => areasOverlap(frameArea, area));
348
+ const doesOverlapAreasToAvoid = overlaps.length > 0;
349
+ if (doesExceedFrameHeight || doesOverlapAreasToAvoid) {
350
+ innerFrameY = offsetY;
351
+ const nextX = numeric(xmax).sub(offsetX).add(frame.gap);
352
+ innerFrameX = offsetX.add(nextX);
353
+ accumY = numeric(0);
354
+ accumX = nextX;
355
+ }
356
+ arrangeLineAttempts++;
357
+ if (arrangeLineAttempts > maxAttempts) {
358
+ throw "Failed to place inner frame";
359
+ }
360
+ }
361
+ innerFrame.x = innerFrameX;
362
+ innerFrame.y = innerFrameY;
363
+ accumY = accumY.add(innerFrameHeight).add(frame.gap);
277
364
  }
278
- else if (frame.direction === FramePlotDirection.Row) {
279
- innerFrame.x = offsetX + centeredOffsetX + accumX;
280
- innerFrame.y = offsetY + accumY;
281
- accumX += (frameWidth + frame.gap);
365
+ else if (frameDirection === FramePlotDirection.Row) {
366
+ innerFrameX = offsetX.add(centeredOffsetX).add(accumX);
367
+ innerFrameY = offsetY.add(accumY);
368
+ while (arrangeLineAttempts < maxAttempts) {
369
+ const innerFrameX2 = innerFrameX.toNumber() + innerFrameWidth;
370
+ const doesExceedFrameWidth = (frameWidth.toNumber() > 0
371
+ && innerFrameX2 > frameWidth.toNumber());
372
+ const tmpX1 = innerFrameX.toNumber();
373
+ const tmpY1 = innerFrameY.toNumber();
374
+ const tmpX2 = tmpX1 + innerFrameWidth;
375
+ const tmpY2 = tmpY1 + innerFrameHeight;
376
+ const frameArea = [tmpX1, tmpY1, tmpX2, tmpY2];
377
+ const overlaps = avoidAreas.filter(area => areasOverlap(frameArea, area));
378
+ const doesOverlapAreasToAvoid = overlaps.length > 0;
379
+ if (doesExceedFrameWidth || doesOverlapAreasToAvoid) {
380
+ innerFrameX = offsetX.add(centeredOffsetX);
381
+ const { ymax } = getBoundsFromPoints(boundPoints);
382
+ const nextY = numeric(ymax).sub(offsetY).add(frame.gap);
383
+ innerFrameY = offsetY.add(nextY);
384
+ accumX = numeric(0);
385
+ accumY = nextY;
386
+ }
387
+ else {
388
+ break;
389
+ }
390
+ arrangeLineAttempts++;
391
+ if (arrangeLineAttempts > maxAttempts) {
392
+ throw "Failed to place inner frame";
393
+ }
394
+ }
395
+ innerFrame.x = innerFrameX;
396
+ innerFrame.y = innerFrameY;
397
+ accumX = accumX.add(innerFrameWidth).add(frame.gap);
282
398
  }
283
399
  }
284
- boundPoints.push([innerFrame.x, innerFrame.y], [innerFrame.x + frameWidth, innerFrame.y + frameHeight]);
400
+ boundPoints.push([
401
+ innerFrame.x.toNumber(),
402
+ innerFrame.y.toNumber()
403
+ ], [
404
+ innerFrame.x.add(innerFrameWidth).toNumber(),
405
+ innerFrame.y.add(innerFrameHeight).toNumber()
406
+ ]);
285
407
  });
286
- const contentsBounds = resizeBounds(getBoundsFromPoints(boundPoints), frame.padding);
287
- if (frame.frame.parameters.has(FrameParamKeys.SheetType)) {
288
- const frameComponent = frame.frame.parameters.get(FrameParamKeys.SheetType);
289
- const frameDrawing = frameComponent.displayProp;
290
- frameDrawing.variables = combineMaps(frameComponent.parameters, frame.frame.parameters);
291
- const rects = ExtractDrawingRects(frameDrawing);
292
- let frameWidth = 0;
293
- let frameHeight = 0;
294
- if (rects[1]) {
295
- frameWidth = milsToMM(rects[1].width);
296
- frameHeight = milsToMM(rects[1].height);
297
- }
298
- const contentsWidth = contentsBounds.xmax - contentsBounds.xmin;
299
- const contentsHeight = contentsBounds.ymax - contentsBounds.ymin;
300
- const frameOffsetX = toNearestGrid((frameWidth - contentsWidth) / 2, gridSize);
301
- const frameOffsetY = toNearestGrid((frameHeight - contentsHeight) / 2, gridSize);
302
- innerFrames.forEach(innerFrame => {
303
- innerFrame.x += frameOffsetX;
304
- innerFrame.y += frameOffsetY;
305
- });
306
- frame.bounds = {
307
- xmin: 0,
308
- ymin: 0,
309
- xmax: frameWidth,
310
- ymax: frameHeight
311
- };
408
+ const contentsBounds = resizeBounds(getBoundsFromPoints(boundPoints), frame.padding.toNumber());
409
+ const contentsWidth = contentsBounds.xmax - contentsBounds.xmin;
410
+ const contentsHeight = contentsBounds.ymax - contentsBounds.ymin;
411
+ let hAlign = HorizontalAlign.Middle;
412
+ let vAlign = VerticalAlign.Middle;
413
+ if (frameParams.has(FrameParamKeys.HorizontalAlign)) {
414
+ hAlign =
415
+ frameParams.get(FrameParamKeys.HorizontalAlign);
416
+ }
417
+ if (frameParams.has(FrameParamKeys.VerticalAlign)) {
418
+ vAlign =
419
+ frameParams.get(FrameParamKeys.VerticalAlign);
420
+ }
421
+ if (frameParams.has(FrameParamKeys.SheetType)) {
422
+ frameXMin = numeric(0);
423
+ frameYMin = numeric(0);
312
424
  }
313
425
  else {
314
- frame.bounds = contentsBounds;
426
+ frameXMin = numeric(contentsBounds.xmin);
427
+ frameYMin = numeric(contentsBounds.ymin);
428
+ }
429
+ if (frameWidth.toNumber() === 0) {
430
+ frameWidth = numeric(contentsWidth);
431
+ }
432
+ if (frameHeight.toNumber() === 0) {
433
+ frameHeight = numeric(contentsHeight);
434
+ }
435
+ const titleFrame = innerFrames.find(frame => {
436
+ return frame.containsTitle;
437
+ });
438
+ if (titleFrame) {
439
+ const { width: innerFrameWidth } = getBoundsSize(titleFrame.bounds);
440
+ let titleOffset = 0;
441
+ switch (title_align) {
442
+ case HorizontalAlign.Left:
443
+ titleOffset = 0;
444
+ break;
445
+ case HorizontalAlign.Middle:
446
+ titleOffset = toNearestGrid(widthForTitle / 2 - innerFrameWidth / 2, gridSize);
447
+ break;
448
+ case HorizontalAlign.Right:
449
+ titleOffset = frameWidth.toNumber() - innerFrameWidth;
450
+ break;
451
+ }
452
+ titleFrame.x = titleFrame.x.add(titleOffset);
453
+ }
454
+ let frameOffsetX = 0;
455
+ let frameOffsetY = 0;
456
+ switch (hAlign) {
457
+ case HorizontalAlign.Left:
458
+ frameOffsetX = 0;
459
+ break;
460
+ case HorizontalAlign.Middle:
461
+ frameOffsetX = toNearestGrid((frameWidth.toNumber() - contentsWidth) / 2, gridSize);
462
+ break;
463
+ case HorizontalAlign.Right:
464
+ frameOffsetX = toNearestGrid(frameWidth.toNumber() - contentsWidth, gridSize);
465
+ break;
466
+ }
467
+ switch (vAlign) {
468
+ case VerticalAlign.Top:
469
+ frameOffsetY = 0;
470
+ break;
471
+ case VerticalAlign.Middle:
472
+ frameOffsetY = toNearestGrid((frameHeight.toNumber() - contentsHeight) / 2, gridSize);
473
+ break;
474
+ case VerticalAlign.Bottom:
475
+ frameOffsetY = toNearestGrid(frameHeight.toNumber() - contentsHeight, gridSize);
476
+ break;
315
477
  }
478
+ innerFrames.forEach(innerFrame => {
479
+ innerFrame.x = innerFrame.x.add(frameOffsetX);
480
+ innerFrame.y = innerFrame.y.add(frameOffsetY);
481
+ });
482
+ frame.bounds = {
483
+ xmin: frameXMin.toNumber(),
484
+ ymin: frameYMin.toNumber(),
485
+ xmax: frameXMin.toNumber() + frameWidth.toNumber(),
486
+ ymax: frameYMin.toNumber() + frameHeight.toNumber(),
487
+ };
316
488
  }
317
489
  dumpFrame(frame, level = 0) {
318
490
  this.print(level, "".padStart(level * 4), 'frame, items:', frame.innerItems.length);
319
491
  frame.innerItems.forEach(item => {
320
492
  item = item;
321
- if (item.type === RenderFrameType.Elements) {
322
- this.print(level, "".padStart(level * 4), 'element frame, items:', item.innerItems.map(item => {
493
+ if (item.renderType === RenderFrameType.Elements) {
494
+ this.print(level, "".padStart(level * 4), '- element frame, items:', item.innerItems.map(item => {
323
495
  if (item instanceof RenderComponent) {
324
496
  return item.component.instanceName;
325
497
  }
@@ -330,7 +502,7 @@ export class LayoutEngine {
330
502
  }));
331
503
  }
332
504
  else {
333
- this.print(level, "".padStart(level * 4), 'container');
505
+ this.print(level, "".padStart(level * 4), '- container');
334
506
  this.dumpFrame(item, level + 1);
335
507
  }
336
508
  });
@@ -347,21 +519,21 @@ export class LayoutEngine {
347
519
  accum.push(item);
348
520
  }
349
521
  else if (item instanceof RenderComponent) {
350
- const instanceName = item.component.instanceName;
522
+ const { instanceName } = item.component;
351
523
  if (ignoreItems.indexOf(instanceName) === -1) {
352
- const subgraph = subgraphInfo.find(item => {
353
- return item.components.indexOf(instanceName) !== -1;
524
+ const withinSubgraph = subgraphInfo.find(subgraphInfo => {
525
+ return subgraphInfo.components.indexOf(instanceName) !== -1;
354
526
  });
355
- if (subgraph !== undefined) {
356
- const tmpFrame = new RenderFrame(new Frame(-2), RenderFrameType.Elements);
527
+ if (withinSubgraph !== undefined) {
528
+ const tmpFrame = new RenderFrame(new Frame(FixedFrameIds.FrameIdNotUsed), RenderFrameType.Elements);
357
529
  tmpFrame.subgraphId = instanceName;
358
530
  tmpFrame.innerItems =
359
- subgraph.components.map(instanceName => {
531
+ withinSubgraph.components.map(instanceName => {
360
532
  const [, component,] = graph.node(instanceName);
361
533
  return component;
362
534
  });
363
- tmpFrame.bounds = subgraph.bounds;
364
- ignoreItems.push(...subgraph.components);
535
+ tmpFrame.bounds = withinSubgraph.bounds;
536
+ ignoreItems.push(...withinSubgraph.components);
365
537
  accum.push(tmpFrame);
366
538
  elementFrames.push(tmpFrame);
367
539
  }
@@ -372,16 +544,23 @@ export class LayoutEngine {
372
544
  }
373
545
  return accum;
374
546
  }, []);
375
- if (frame.type === RenderFrameType.Container) {
547
+ this.checkAddFrameTitle(frame, elementFrames, textObjects, level);
548
+ return {
549
+ elementFrames,
550
+ textObjects,
551
+ };
552
+ }
553
+ checkAddFrameTitle(frame, elementFrames, textObjects, level) {
554
+ if (frame.renderType === RenderFrameType.Container) {
376
555
  const frameObject = frame.frame;
377
556
  const isSheetFrame = frameObject.frameType === FrameType.Sheet;
378
557
  if (frameObject.parameters.has(FrameParamKeys.Title) && !isSheetFrame) {
379
558
  const title = frameObject.parameters.get(FrameParamKeys.Title);
380
- const tmpFrame = new RenderFrame(new Frame(-2), RenderFrameType.Elements);
559
+ const tmpFrame = new RenderFrame(new Frame(FixedFrameIds.FrameIdNotUsed), RenderFrameType.Elements);
381
560
  tmpFrame.containsTitle = true;
382
561
  tmpFrame.subgraphId = title.replace(/\s/g, "_");
383
562
  const textObject = new RenderText(title);
384
- textObject.fontSize = defaultFrameTitleTextSize;
563
+ textObject.fontSize = numeric(defaultFrameTitleTextSize);
385
564
  textObject.fontWeight = 'bold';
386
565
  textObject.symbol.refreshDrawing();
387
566
  tmpFrame.innerItems.push(textObject);
@@ -392,18 +571,14 @@ export class LayoutEngine {
392
571
  xmax: tmpBox.start[0] + tmpBox.width,
393
572
  ymax: tmpBox.start[1] + tmpBox.height
394
573
  };
395
- textObject.x = 0;
396
- textObject.y = 0;
574
+ textObject.x = numeric(0);
575
+ textObject.y = numeric(0);
397
576
  frame.innerItems.splice(0, 0, tmpFrame);
398
577
  this.printLevel(level, frame, 'added text', tmpFrame);
399
578
  textObjects.push(textObject);
400
579
  elementFrames.splice(0, 0, tmpFrame);
401
580
  }
402
581
  }
403
- return {
404
- elementFrames,
405
- textObjects,
406
- };
407
582
  }
408
583
  generateLayoutGraph(sequence, nets) {
409
584
  let previousNode = null;
@@ -413,161 +588,155 @@ export class LayoutEngine {
413
588
  compound: true,
414
589
  });
415
590
  this.print('sequence length:', sequence.length);
416
- const baseRenderFrame = new RenderFrame(new Frame(-1));
417
- const frameStack = [baseRenderFrame];
418
- const containerFrames = [baseRenderFrame];
419
- for (let i = 0; i < sequence.length; i++) {
420
- const action = sequence[i][0];
591
+ const baseFrame = new RenderFrame(new Frame(FixedFrameIds.BaseFrame));
592
+ const frameStack = [baseFrame];
593
+ const containerFrames = [baseFrame];
594
+ sequence.forEach((sequenceStep, index) => {
595
+ const action = sequenceStep[0];
421
596
  let tmpComponent;
422
- if (action === SequenceAction.At || action === SequenceAction.To) {
423
- this.print(...sequence[i]);
424
- const component = sequence[i][1];
425
- const pin = sequence[i][2];
426
- const tmpInstanceName = component.instanceName;
427
- if (!graph.hasNode(tmpInstanceName)) {
428
- this.print('create instance', tmpInstanceName);
429
- let { displayProp = null, widthProp = null, typeProp = null } = component;
430
- let tmpSymbol;
431
- if (displayProp === null &&
432
- component.parameters.get(ParamKeys.net_name) === GlobalNames.gnd) {
433
- displayProp = 'gnd';
434
- }
435
- if (displayProp !== null) {
597
+ switch (action) {
598
+ case SequenceAction.To:
599
+ case SequenceAction.At: {
600
+ this.print(...sequenceStep);
601
+ const [, component, pin] = sequenceStep;
602
+ const tmpInstanceName = component.instanceName;
603
+ if (!graph.hasNode(tmpInstanceName)) {
604
+ this.print('create instance', tmpInstanceName);
605
+ const { displayProp = null, widthProp = null, heightProp = null } = component;
606
+ let tmpSymbol;
436
607
  if (displayProp instanceof SymbolDrawing) {
437
608
  tmpSymbol = new SymbolPlaceholder(displayProp);
438
609
  tmpSymbol.drawing.logger = this.logger;
439
610
  }
440
- else if (typeof displayProp === "string") {
441
- tmpSymbol = SymbolFactory(displayProp);
611
+ else {
612
+ const symbolPinDefinitions = generateLayoutPinDefinition(component);
613
+ if (component.typeProp === ComponentTypes.module) {
614
+ tmpSymbol = new SymbolCustomModule(symbolPinDefinitions, component.pinsMaxPositions);
615
+ }
616
+ else {
617
+ tmpSymbol = new SymbolCustom(symbolPinDefinitions, component.pinsMaxPositions);
618
+ }
442
619
  }
443
- }
444
- else {
445
- const symbolPinDefinitions = generateLayoutPinDefinition(component);
446
- if (component.typeProp === 'module') {
447
- tmpSymbol = new SymbolCustomModule(symbolPinDefinitions);
620
+ applyComponentParamsToSymbol(component, tmpSymbol);
621
+ if (component.parameters.has(ParamKeys.angle)) {
622
+ const value = component.parameters.get(ParamKeys.angle).toNumber();
623
+ tmpSymbol.angle = value;
448
624
  }
449
- else {
450
- tmpSymbol = new SymbolCustom(symbolPinDefinitions);
625
+ if (component.parameters.has(ParamKeys.flipX)) {
626
+ tmpSymbol.flipX =
627
+ component.parameters.get(ParamKeys.flipX);
451
628
  }
629
+ if (component.parameters.has(ParamKeys.flipY)) {
630
+ tmpSymbol.flipY =
631
+ component.parameters.get(ParamKeys.flipY);
632
+ }
633
+ if (tmpSymbol instanceof SymbolCustom) {
634
+ if (widthProp) {
635
+ tmpSymbol.bodyWidth = milsToMM(widthProp);
636
+ }
637
+ if (heightProp) {
638
+ tmpSymbol.bodyHeight = milsToMM(heightProp);
639
+ }
640
+ }
641
+ tmpSymbol.refreshDrawing();
642
+ const { width: useWidth, height: useHeight } = tmpSymbol.size();
643
+ tmpComponent = new RenderComponent(component, useWidth, useHeight);
644
+ tmpComponent.symbol = tmpSymbol;
645
+ graph.setNode(tmpInstanceName, [RenderItemType.Component, tmpComponent, index]);
646
+ const currentFrame = frameStack[frameStack.length - 1];
647
+ currentFrame && currentFrame.innerItems.push(tmpComponent);
452
648
  }
453
- applyComponentParamsToSymbol(component, tmpSymbol);
454
- let didSetAngle = false;
455
- if (component.parameters.has('angle')) {
456
- didSetAngle = true;
457
- tmpSymbol.angle = component.parameters.get('angle');
458
- }
459
- if (component.parameters.has('flipX')) {
460
- tmpSymbol.flipX =
461
- component.parameters.get('flipX');
462
- }
463
- if (component.parameters.has('flipY')) {
464
- tmpSymbol.flipY =
465
- component.parameters.get('flipY');
466
- }
467
- if (tmpSymbol instanceof SymbolCustom && widthProp) {
468
- tmpSymbol.bodyWidth = milsToMM(widthProp);
469
- }
470
- if (!didSetAngle && component.parameters.has('_addDirection')) {
471
- tmpSymbol.refreshDrawing(false);
472
- tmpSymbol.angle = calculateSymbolAngle(tmpSymbol, component.parameters.get('_addPin'), component.parameters.get('_addDirection'));
649
+ if (action === SequenceAction.To && previousNode && previousPin) {
650
+ this.setGraphEdge(graph, previousNode, tmpInstanceName, makeEdgeValue(previousNode, previousPin, tmpInstanceName, pin, index));
473
651
  }
474
- tmpSymbol.refreshDrawing();
475
- const { width: useWidth, height: useHeight } = tmpSymbol.size();
476
- tmpComponent = new RenderComponent(component, useWidth, useHeight);
477
- tmpComponent.symbol = tmpSymbol;
478
- graph.setNode(tmpInstanceName, [RenderItemType.Component, tmpComponent, i]);
479
- const currentFrame = frameStack[frameStack.length - 1];
480
- currentFrame && currentFrame.innerItems.push(tmpComponent);
652
+ previousNode = tmpInstanceName;
653
+ previousPin = pin;
654
+ break;
481
655
  }
482
- if (action === SequenceAction.To) {
483
- this.setGraphEdge(graph, previousNode, tmpInstanceName, makeEdgeValue(previousNode, previousPin, tmpInstanceName, pin, i));
484
- }
485
- previousNode = tmpInstanceName;
486
- previousPin = pin;
487
- }
488
- else if (action === SequenceAction.Wire) {
489
- const [, wireId, wireSegments] = sequence[i];
490
- const wire = new RenderWire(0, 0, wireSegments);
491
- wire.id = wireId;
492
- let useNetName = null;
493
- if (previousNode !== null) {
494
- const [prevNodeType, prevNodeItem] = graph.node(previousNode);
495
- if (prevNodeType === RenderItemType.Component) {
496
- const matchingItem = nets.find(([comp, pin]) => {
497
- return comp.instanceName === previousNode && pin === previousPin;
498
- });
499
- useNetName = matchingItem !== undefined ? matchingItem[2].name : null;
500
- }
501
- else if (prevNodeType === RenderItemType.Wire) {
502
- useNetName = prevNodeItem.netName;
656
+ case SequenceAction.Wire: {
657
+ const [, wireId, wireSegments] = sequenceStep;
658
+ const wire = new RenderWire(numeric(0), numeric(0), wireSegments);
659
+ wire.id = wireId;
660
+ let useNetName = null;
661
+ if (previousNode !== null) {
662
+ const [prevNodeType, prevNodeItem] = graph.node(previousNode);
663
+ if (prevNodeType === RenderItemType.Component) {
664
+ const matchingItem = nets.find(([comp, pin]) => {
665
+ return comp.instanceName === previousNode && pin === previousPin;
666
+ });
667
+ useNetName = matchingItem !== undefined ? matchingItem[2].name : null;
668
+ }
669
+ else if (prevNodeType === RenderItemType.Wire) {
670
+ useNetName = prevNodeItem.netName;
671
+ }
503
672
  }
673
+ wire.netName = useNetName;
674
+ const wireName = getWireName(wire.id);
675
+ graph.setNode(wireName, [RenderItemType.Wire, wire, index]);
676
+ this.setGraphEdge(graph, previousNode, wireName, makeEdgeValue(previousNode, previousPin, wireName, 0, index));
677
+ previousNode = wireName;
678
+ previousPin = 1;
679
+ const wireSegmentsInfo = wireSegments.map(item => {
680
+ const tmp = {
681
+ direction: item.direction,
682
+ value: item.value,
683
+ };
684
+ if (item.valueXY) {
685
+ tmp.valueXY = item.valueXY;
686
+ }
687
+ if (item.until) {
688
+ tmp.until = [item.until[0].toString(), item.until[1]];
689
+ }
690
+ return tmp;
691
+ });
692
+ this.print(SequenceAction.Wire, wireId, JSON.stringify(wireSegmentsInfo));
693
+ break;
504
694
  }
505
- wire.netName = useNetName;
506
- const wireName = getWireName(wire.id);
507
- graph.setNode(wireName, [RenderItemType.Wire, wire, i]);
508
- this.setGraphEdge(graph, previousNode, wireName, makeEdgeValue(previousNode, previousPin, wireName, 0, i));
509
- previousNode = wireName;
510
- previousPin = 1;
511
- const wireSegmentsInfo = wireSegments.map(item => {
512
- const tmp = {
513
- direction: item.direction,
514
- value: item.value,
515
- };
516
- if (item.valueXY) {
517
- tmp.valueXY = item.valueXY;
695
+ case SequenceAction.WireJump: {
696
+ this.print(...sequenceStep);
697
+ const wireId = sequenceStep[1];
698
+ const wireName = getWireName(wireId);
699
+ let wirePin = 1;
700
+ if (sequenceStep.length === 3) {
701
+ wirePin = sequenceStep[2];
518
702
  }
519
- if (item.until) {
520
- tmp.until = [item.until[0].toString(), item.until[1]];
521
- }
522
- return tmp;
523
- });
524
- this.print(SequenceAction.Wire, wireId, JSON.stringify(wireSegmentsInfo));
525
- }
526
- else if (action === SequenceAction.WireJump) {
527
- this.print(...sequence[i]);
528
- const wireId = sequence[i][1];
529
- const wireName = getWireName(wireId);
530
- let wirePin = 1;
531
- if (sequence[i].length === 3) {
532
- wirePin = sequence[i][2];
703
+ previousNode = wireName;
704
+ previousPin = wirePin;
705
+ break;
533
706
  }
534
- previousNode = wireName;
535
- previousPin = wirePin;
536
- }
537
- else if (action === SequenceAction.Frame) {
538
- const [, frameObject, frameAction] = sequence[i];
539
- if (frameAction === FrameAction.Enter) {
540
- const prevFrame = frameStack[frameStack.length - 1];
541
- const newFrame = new RenderFrame(frameObject);
542
- if (frameObject.parameters.has(FrameParamKeys.Direction)) {
543
- newFrame.direction =
544
- frameObject.parameters.get(FrameParamKeys.Direction);
545
- }
546
- if (frameObject.parameters.has(FrameParamKeys.Padding)) {
547
- newFrame.padding =
548
- frameObject.parameters.get(FrameParamKeys.Padding);
549
- }
550
- if (frameObject.parameters.has(FrameParamKeys.Border)) {
551
- newFrame.borderWidth =
552
- frameObject.parameters.get(FrameParamKeys.Border);
553
- }
554
- if (frameObject.parameters.has(FrameParamKeys.Width)) {
555
- newFrame.width =
556
- frameObject.parameters.get(FrameParamKeys.Width);
707
+ case SequenceAction.Frame: {
708
+ const [, frameObject, frameAction] = sequenceStep;
709
+ if (frameAction === FrameAction.Enter) {
710
+ const prevFrame = frameStack[frameStack.length - 1];
711
+ const newFrame = new RenderFrame(frameObject);
712
+ if (frameObject.parameters.has(FrameParamKeys.Direction)) {
713
+ newFrame.direction =
714
+ frameObject.parameters.get(FrameParamKeys.Direction);
715
+ }
716
+ if (frameObject.parameters.has(FrameParamKeys.Padding)) {
717
+ newFrame.padding = milsToMM(frameObject.parameters.get(FrameParamKeys.Padding));
718
+ }
719
+ if (frameObject.parameters.has(FrameParamKeys.Border)) {
720
+ newFrame.borderWidth =
721
+ frameObject.parameters.get(FrameParamKeys.Border);
722
+ }
723
+ if (frameObject.parameters.has(FrameParamKeys.Width)) {
724
+ newFrame.width = milsToMM(frameObject.parameters.get(FrameParamKeys.Width));
725
+ }
726
+ if (frameObject.parameters.has(FrameParamKeys.Height)) {
727
+ newFrame.height = milsToMM(frameObject.parameters.get(FrameParamKeys.Height));
728
+ }
729
+ containerFrames.push(newFrame);
730
+ frameStack.push(newFrame);
731
+ prevFrame && prevFrame.innerItems.push(newFrame);
557
732
  }
558
- if (frameObject.parameters.has(FrameParamKeys.Height)) {
559
- newFrame.height =
560
- frameObject.parameters.get(FrameParamKeys.Height);
733
+ else if (frameAction === FrameAction.Exit) {
734
+ frameStack.pop();
561
735
  }
562
- containerFrames.push(newFrame);
563
- frameStack.push(newFrame);
564
- prevFrame && prevFrame.innerItems.push(newFrame);
565
- }
566
- else if (frameAction === FrameAction.Exit) {
567
- frameStack.pop();
736
+ break;
568
737
  }
569
738
  }
570
- }
739
+ });
571
740
  return {
572
741
  graph,
573
742
  containerFrames,
@@ -582,10 +751,10 @@ export class LayoutEngine {
582
751
  this.print('===== placing subgraphs =====');
583
752
  this.print('number of subgraphs: ', subGraphs.length);
584
753
  const subgraphInfo = [];
585
- subGraphs.forEach(innerGraph => {
754
+ subGraphs.forEach(subGraph => {
586
755
  let smallestNodeIdLevel = Number.POSITIVE_INFINITY;
587
- let smallestNodeId = null;
588
- innerGraph.forEach(nodeId => {
756
+ let smallestNodeId = "";
757
+ subGraph.forEach(nodeId => {
589
758
  const [, , sequenceId] = graph.node(nodeId);
590
759
  if (sequenceId < smallestNodeIdLevel) {
591
760
  smallestNodeIdLevel = sequenceId;
@@ -628,12 +797,7 @@ export class LayoutEngine {
628
797
  }
629
798
  return accum;
630
799
  }, []);
631
- if (this.placeSubgraphVersion === 1) {
632
- this.placeSubgraph(graph, firstNodeId, subgraphEdges);
633
- }
634
- else if (this.placeSubgraphVersion === 2) {
635
- this.placeSubgraphV2(graph, firstNodeId, subgraphEdges);
636
- }
800
+ this.placeSubgraphV2(graph, firstNodeId, subgraphEdges);
637
801
  }
638
802
  placeSubgraphV2(graph, firstNodeId, subgraphEdges) {
639
803
  let firstNodePlaced = false;
@@ -651,7 +815,7 @@ export class LayoutEngine {
651
815
  }
652
816
  if (subgraphEdges.length === 0) {
653
817
  const [, node1] = graph.node(firstNodeId);
654
- this.placeNodeAtPosition(0, 0, node1, 1);
818
+ this.placeNodeAtPosition(numeric(0), numeric(0), node1, 1);
655
819
  return;
656
820
  }
657
821
  let fixedNode;
@@ -664,7 +828,7 @@ export class LayoutEngine {
664
828
  const [, node2] = graph.node(nodeId2);
665
829
  if (nodeId1 === firstNodeId && !firstNodePlaced) {
666
830
  this.print('first node placed at origin');
667
- this.placeNodeAtPosition(0, 0, node1, pin1);
831
+ this.placeNodeAtPosition(numeric(0), numeric(0), node1, pin1);
668
832
  firstNodePlaced = true;
669
833
  node1.isFloating = false;
670
834
  originNodes.push(node1);
@@ -687,7 +851,7 @@ export class LayoutEngine {
687
851
  originNodes.push(node1);
688
852
  originNodeGroups.set(node1.toString(), [node1]);
689
853
  this.print('creating new origin node at', node1);
690
- this.placeNodeAtPosition(0, 0, node1, pin1);
854
+ this.placeNodeAtPosition(numeric(0), numeric(0), node1, pin1);
691
855
  node1.isFloating = false;
692
856
  fixedNode = node1;
693
857
  fixedNodePin = pin1;
@@ -704,7 +868,7 @@ export class LayoutEngine {
704
868
  else {
705
869
  const [x1, y1] = getNodePositionAtPin(node1, pin1);
706
870
  const [x2, y2] = getNodePositionAtPin(node2, pin2);
707
- if (x1 !== x2 && y1 !== y2) {
871
+ if (!x1.eq(x2) && !y1.eq(y2)) {
708
872
  if (node1 instanceof RenderWire &&
709
873
  node2 instanceof RenderComponent) {
710
874
  const refdes = node2.component.assignedRefDes;
@@ -781,8 +945,8 @@ export class LayoutEngine {
781
945
  this.print('merging origin node groups, fixed:', keepOriginNode, ', other:', otherOriginNode);
782
946
  const [x, y] = getNodePositionAtPin(fixedNode, fixedNodePin);
783
947
  const [otherNodeOriginX, otherNodeOriginY] = getNodePositionAtPin(mergedNode, mergedNodePin);
784
- const offsetX = x - otherNodeOriginX;
785
- const offsetY = y - otherNodeOriginY;
948
+ const offsetX = x.sub(otherNodeOriginX);
949
+ const offsetY = y.sub(otherNodeOriginY);
786
950
  this.print('offset of other origin:', offsetX, offsetY);
787
951
  const otherItemsLinkedToOriginNode = originNodeGroups.get(otherOriginNode);
788
952
  this.print('nodes in other origin:', otherItemsLinkedToOriginNode);
@@ -796,68 +960,15 @@ export class LayoutEngine {
796
960
  this.print('removed other origin');
797
961
  this.print('merge completed');
798
962
  }
799
- placeSubgraph(graph, firstNodeId, subgraphEdges) {
800
- let firstNodePlaced = false;
801
- subgraphEdges.forEach(edge => {
802
- const [nodeId1, pin1, nodeId2, pin2] = graph.edge(edge);
803
- const [, node1] = graph.node(nodeId1);
804
- const [, node2] = graph.node(nodeId2);
805
- if (nodeId1 === firstNodeId && !firstNodePlaced) {
806
- this.print('first node placed at origin');
807
- this.placeNodeAtPosition(0, 0, node1, pin1);
808
- firstNodePlaced = true;
809
- node1.isFloating = false;
810
- }
811
- let fixedNode;
812
- let fixedNodePin;
813
- let floatingNode;
814
- let floatingNodePin;
815
- this.print('edge:', '[', node1, pin1, node1.isFloating, ']', '[', node2, pin2, node2.isFloating, ']');
816
- if (!node1.isFloating && node2.isFloating) {
817
- fixedNode = node1;
818
- fixedNodePin = pin1;
819
- floatingNode = node2;
820
- floatingNodePin = pin2;
821
- }
822
- else if (node1.isFloating && !node2.isFloating) {
823
- fixedNode = node2;
824
- fixedNodePin = pin2;
825
- floatingNode = node1;
826
- floatingNodePin = pin1;
827
- }
828
- else if (node1.isFloating && node2.isFloating) {
829
- this.print('both nodes are floating', node1, 'pin', pin1, 'and', node2, 'pin', pin2);
830
- node1.floatingRelativeTo.push([pin1, nodeId2, pin2]);
831
- node2.floatingRelativeTo.push([pin2, nodeId1, pin1]);
832
- }
833
- if (fixedNode && floatingNode) {
834
- this.print('place floating node', floatingNode, 'pin', floatingNodePin, 'to', fixedNode, 'pin', fixedNodePin);
835
- const [x, y] = getNodePositionAtPin(fixedNode, fixedNodePin);
836
- this.placeNodeAtPosition(x, y, floatingNode, floatingNodePin);
837
- floatingNode.isFloating = false;
838
- this.placeFloatingItems(graph, floatingNode);
839
- }
840
- [node1, node2].forEach(item => {
841
- if (item instanceof RenderWire) {
842
- if (item.isEndAutoLength()) {
843
- const [instance, pin] = item.getEndAuto();
844
- const [, targetNode] = graph.node(instance.instanceName);
845
- const [untilX, untilY] = getNodePositionAtPin(targetNode, pin);
846
- item.setEndAuto(untilX, untilY);
847
- }
848
- }
849
- });
850
- });
851
- }
852
963
  translateNodeBy(offsetX, offsetY, item) {
853
- item.x += offsetX;
854
- item.y += offsetY;
964
+ item.x = item.x.add(offsetX);
965
+ item.y = item.y.add(offsetY);
855
966
  }
856
967
  placeNodeAtPosition(fromX, fromY, item, pin, depth = 0) {
857
968
  if (item instanceof RenderComponent) {
858
969
  const pinPosition = item.symbol.pinPosition(pin);
859
- item.x = fromX - pinPosition.x;
860
- item.y = fromY - pinPosition.y;
970
+ item.x = fromX.sub(pinPosition.x);
971
+ item.y = fromY.sub(pinPosition.y);
861
972
  }
862
973
  else if (item instanceof RenderWire) {
863
974
  if (pin === 0) {
@@ -866,8 +977,8 @@ export class LayoutEngine {
866
977
  }
867
978
  else {
868
979
  const wireEnd = item.getWireEnd();
869
- item.x = fromX - wireEnd.x;
870
- item.y = fromY - wireEnd.y;
980
+ item.x = fromX.sub(wireEnd.x);
981
+ item.y = fromY.sub(wireEnd.y);
871
982
  }
872
983
  }
873
984
  this.print(this.padLevel(depth), 'place', item, 'pin', pin, 'at', item.x, item.y);
@@ -906,12 +1017,12 @@ export class LayoutEngine {
906
1017
  }
907
1018
  }
908
1019
  function getNodePositionAtPin(item, pin) {
909
- let x = 0;
910
- let y = 0;
1020
+ let x = numeric(0);
1021
+ let y = numeric(0);
911
1022
  if (item instanceof RenderComponent) {
912
1023
  const pinPosition = item.symbol.pinPosition(pin);
913
- x = item.x + pinPosition.x;
914
- y = item.y + pinPosition.y;
1024
+ x = item.x.add(pinPosition.x);
1025
+ y = item.y.add(pinPosition.y);
915
1026
  }
916
1027
  else if (item instanceof RenderWire) {
917
1028
  if (pin === 0) {
@@ -920,8 +1031,8 @@ function getNodePositionAtPin(item, pin) {
920
1031
  }
921
1032
  else {
922
1033
  const wireEnd = item.getWireEnd();
923
- x = item.x + wireEnd.x;
924
- y = item.y + wireEnd.y;
1034
+ x = item.x.add(wireEnd.x);
1035
+ y = item.y.add(wireEnd.y);
925
1036
  }
926
1037
  }
927
1038
  return [
@@ -954,7 +1065,7 @@ function generateLayoutPinDefinition(component) {
954
1065
  const pinPosition = Math.floor(i / 2);
955
1066
  const pin = pins.get(existingPinIds[i]);
956
1067
  symbolPinDefinitions.push({
957
- side: (i % 2 === 0) ? "left" : "right",
1068
+ side: (i % 2 === 0) ? SymbolPinSide.Left : SymbolPinSide.Right,
958
1069
  pinId: existingPinIds[i],
959
1070
  text: pin.name,
960
1071
  position: pinPosition,
@@ -973,24 +1084,24 @@ function generateLayoutPinDefinition(component) {
973
1084
  useItems = [...items];
974
1085
  }
975
1086
  useItems.forEach(pinId => {
976
- if (existingPinIds.indexOf(pinId) !== -1) {
977
- const pin = pins.get(pinId);
978
- symbolPinDefinitions.push({
979
- side: key,
980
- pinId: pinId,
981
- text: pin.name,
982
- position: pin.position,
983
- pinType: pin.pinType,
984
- });
985
- addedPins.push(pinId);
1087
+ if (pinId instanceof NumericValue) {
1088
+ const pinIdValue = pinId.toNumber();
1089
+ if (existingPinIds.indexOf(pinIdValue) !== -1) {
1090
+ const pin = pins.get(pinIdValue);
1091
+ symbolPinDefinitions.push({
1092
+ side: key,
1093
+ pinId: pinIdValue,
1094
+ text: pin.name,
1095
+ position: pin.position,
1096
+ pinType: pin.pinType,
1097
+ });
1098
+ addedPins.push(pinIdValue);
1099
+ }
986
1100
  }
987
1101
  });
988
1102
  }
989
- const unplacedPins = [];
990
- existingPinIds.forEach(item => {
991
- if (addedPins.indexOf(item) === -1) {
992
- unplacedPins.push(item);
993
- }
1103
+ const unplacedPins = existingPinIds.filter(pinId => {
1104
+ return addedPins.indexOf(pinId) === -1;
994
1105
  });
995
1106
  if (unplacedPins.length > 0) {
996
1107
  throw "'arrange' property is defined, but not all pins are specified: " + unplacedPins.join(",");
@@ -1031,21 +1142,21 @@ export function getBounds(components, wires, junctions, frames) {
1031
1142
  const bbox = item.symbol.drawing.getBoundingBox();
1032
1143
  const [x1, y1] = bbox.start;
1033
1144
  const [x2, y2] = bbox.end;
1034
- points.push([x1 + item.x, y1 + item.y]);
1035
- points.push([x2 + item.x, y2 + item.y]);
1145
+ points.push([x1 + item.x.toNumber(), y1 + item.y.toNumber()]);
1146
+ points.push([x2 + item.x.toNumber(), y2 + item.y.toNumber()]);
1036
1147
  });
1037
1148
  wires.forEach(wire => {
1038
1149
  wire.points.forEach(point => {
1039
- points.push([wire.x + point.x, wire.y + point.y]);
1150
+ points.push([wire.x.add(point.x).toNumber(), wire.y.add(point.y).toNumber()]);
1040
1151
  });
1041
1152
  });
1042
1153
  junctions.forEach(item => {
1043
- points.push([item.x, item.y]);
1154
+ points.push([item.x.toNumber(), item.y.toNumber()]);
1044
1155
  });
1045
1156
  frames.forEach(item => {
1046
1157
  const { width, height } = getBoundsSize(item.bounds);
1047
- points.push([item.x, item.y]);
1048
- points.push([item.x + width, item.y + height]);
1158
+ points.push([item.x.toNumber(), item.y.toNumber()]);
1159
+ points.push([item.x.toNumber() + width, item.y.toNumber() + height]);
1049
1160
  });
1050
1161
  return getBoundsFromPoints(points);
1051
1162
  }
@@ -1061,8 +1172,8 @@ function getBoundsFromPoints(points) {
1061
1172
  };
1062
1173
  }
1063
1174
  export class RenderObject {
1064
- x = -1;
1065
- y = -1;
1175
+ x = numeric(-1);
1176
+ y = numeric(-1);
1066
1177
  isFloating = true;
1067
1178
  floatingRelativeTo = [];
1068
1179
  }
@@ -1105,7 +1216,7 @@ export class RenderWire extends RenderObject {
1105
1216
  tmpX += useValue;
1106
1217
  }
1107
1218
  else if (direction === WireAutoDirection.Auto || direction === WireAutoDirection.Auto_) {
1108
- const { valueXY = [0, 0] } = segment;
1219
+ const { valueXY = [numeric(0), numeric(0)] } = segment;
1109
1220
  const tmpPoints = this.getAutoPoints(valueXY, direction);
1110
1221
  tmpPoints.forEach(point => {
1111
1222
  if (point[0] !== 0 || point[1] !== 0) {
@@ -1123,8 +1234,8 @@ export class RenderWire extends RenderObject {
1123
1234
  this.points = points;
1124
1235
  }
1125
1236
  getAutoPoints(value, direction) {
1126
- const valueX = roundValue(value[0]);
1127
- const valueY = roundValue(value[1]);
1237
+ const valueX = roundValue(value[0]).toNumber();
1238
+ const valueY = roundValue(value[1]).toNumber();
1128
1239
  const inQuadrant = Geometry.getQuadrant(valueX, valueY);
1129
1240
  const [dx, dy] = [valueX, valueY];
1130
1241
  if (direction === WireAutoDirection.Auto) {
@@ -1180,16 +1291,16 @@ export class RenderWire extends RenderObject {
1180
1291
  useValue = value;
1181
1292
  }
1182
1293
  if (direction === Direction.Down) {
1183
- tmpY += useValue;
1294
+ tmpY = tmpY.add(useValue);
1184
1295
  }
1185
1296
  else if (direction === Direction.Up) {
1186
- tmpY -= useValue;
1297
+ tmpY = tmpY.sub(useValue);
1187
1298
  }
1188
1299
  else if (direction === Direction.Left) {
1189
- tmpX -= useValue;
1300
+ tmpX = tmpX.sub(useValue);
1190
1301
  }
1191
1302
  else if (direction === Direction.Right) {
1192
- tmpX += useValue;
1303
+ tmpX = tmpX.add(useValue);
1193
1304
  }
1194
1305
  });
1195
1306
  let useValue = null;
@@ -1197,22 +1308,22 @@ export class RenderWire extends RenderObject {
1197
1308
  const lastSegment = this.segments[this.segments.length - 1];
1198
1309
  switch (lastSegment.direction) {
1199
1310
  case Direction.Left:
1200
- useValue = tmpX - untilX;
1311
+ useValue = tmpX.sub(untilX);
1201
1312
  break;
1202
1313
  case Direction.Right:
1203
- useValue = untilX - tmpX;
1314
+ useValue = untilX.sub(tmpX);
1204
1315
  break;
1205
1316
  case Direction.Up:
1206
- useValue = untilY - tmpY;
1317
+ useValue = untilY.sub(tmpY);
1207
1318
  break;
1208
1319
  case Direction.Down:
1209
- useValue = tmpY - untilY;
1320
+ useValue = tmpY.sub(untilY);
1210
1321
  break;
1211
1322
  case WireAutoDirection.Auto:
1212
1323
  case WireAutoDirection.Auto_:
1213
1324
  valueXY = [
1214
- untilX - tmpX,
1215
- untilY - tmpY,
1325
+ untilX.sub(tmpX),
1326
+ untilY.sub(tmpY),
1216
1327
  ];
1217
1328
  useValue = 0;
1218
1329
  break;
@@ -1250,7 +1361,7 @@ export class RenderComponent extends RenderObject {
1250
1361
  }
1251
1362
  export class RenderText extends RenderObject {
1252
1363
  symbol;
1253
- _fontSize = 12;
1364
+ _fontSize = numeric(12);
1254
1365
  _fontWeight = 'regular';
1255
1366
  get fontSize() {
1256
1367
  return this._fontSize;
@@ -1279,28 +1390,28 @@ export class RenderFrame extends RenderObject {
1279
1390
  translateY = 0;
1280
1391
  padding = milsToMM(100);
1281
1392
  gap = milsToMM(100);
1393
+ borderWidth = numeric(5);
1282
1394
  direction = FramePlotDirection.Column;
1283
- borderWidth = 5;
1284
1395
  width = null;
1285
1396
  height = null;
1286
- size = null;
1287
1397
  subgraphId = "";
1288
- type;
1398
+ renderType;
1289
1399
  containsTitle = false;
1290
1400
  constructor(frame, type = RenderFrameType.Container) {
1291
1401
  super();
1292
1402
  this.frame = frame;
1293
- this.type = type;
1403
+ this.renderType = type;
1294
1404
  }
1295
1405
  toString() {
1296
1406
  let name = "";
1297
- if (this.type === RenderFrameType.Container) {
1407
+ if (this.renderType === RenderFrameType.Container) {
1298
1408
  name = 'container_' + this.frame.frameId;
1299
1409
  }
1300
- else if (this.type === RenderFrameType.Elements) {
1410
+ else if (this.renderType === RenderFrameType.Elements) {
1301
1411
  name = 'elements_' + this.subgraphId;
1302
1412
  }
1303
- return name + ": " + this.x + "," + this.y + " bounds:" + printBounds(this.bounds);
1413
+ return name + ": " + this.x + "," + this.y
1414
+ + " bounds:" + (this.bounds && printBounds(this.bounds));
1304
1415
  }
1305
1416
  }
1306
1417
  export var RenderFrameType;
@@ -1325,7 +1436,7 @@ export function CalculatePinPositions(component) {
1325
1436
  }
1326
1437
  else {
1327
1438
  const symbolPinDefinitions = generateLayoutPinDefinition(component);
1328
- tmpSymbol = new SymbolCustom(symbolPinDefinitions);
1439
+ tmpSymbol = new SymbolCustom(symbolPinDefinitions, component.pinsMaxPositions);
1329
1440
  }
1330
1441
  applyComponentParamsToSymbol(component, tmpSymbol);
1331
1442
  tmpSymbol.refreshDrawing();
@@ -1339,9 +1450,17 @@ export function ExtractDrawingRects(drawing) {
1339
1450
  return drawing.getCommands().filter(item => {
1340
1451
  return (item[0] === PlaceHolderCommands.rect);
1341
1452
  }).map(item => {
1453
+ const map = item[2];
1454
+ let className = undefined;
1455
+ if (map.has('class')) {
1456
+ className = map.get('class');
1457
+ }
1342
1458
  return {
1459
+ x: item[1][0],
1460
+ y: item[1][1],
1343
1461
  width: item[1][2],
1344
1462
  height: item[1][3],
1463
+ className
1345
1464
  };
1346
1465
  });
1347
1466
  }