circuitscript 0.5.4 → 0.5.6
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/README.md +105 -2
- package/dist/cjs/BaseVisitor.js +11 -10
- package/dist/cjs/builtinMethods.js +6 -5
- package/dist/cjs/environment/environment.js +2 -2
- package/dist/cjs/errors.js +140 -0
- package/dist/cjs/execute.js +12 -5
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/main.js +3 -2
- package/dist/cjs/objects/ClassComponent.js +4 -4
- package/dist/cjs/objects/ExecutionScope.js +2 -2
- package/dist/cjs/objects/NumericValue.js +15 -0
- package/dist/cjs/objects/PinDefinition.js +2 -2
- package/dist/cjs/objects/types.js +2 -2
- package/dist/cjs/parser.js +3 -2
- package/dist/cjs/pipeline.js +21 -14
- package/dist/cjs/regenerate-tests.js +6 -6
- package/dist/cjs/render/draw_symbols.js +17 -17
- package/dist/cjs/render/geometry.js +6 -6
- package/dist/cjs/render/layout.js +325 -253
- package/dist/cjs/render/render.js +21 -18
- package/dist/cjs/semantic-tokens/getSemanticTokens.js +2 -2
- package/dist/cjs/sizing.js +2 -2
- package/dist/cjs/utils.js +13 -110
- package/dist/cjs/validate/validateScript.js +2 -2
- package/dist/cjs/visitor.js +14 -12
- package/dist/esm/BaseVisitor.js +2 -1
- package/dist/esm/builtinMethods.js +6 -5
- package/dist/esm/environment/environment.js +1 -1
- package/dist/esm/errors.js +119 -0
- package/dist/esm/execute.js +10 -3
- package/dist/esm/index.js +1 -0
- package/dist/esm/main.js +3 -2
- package/dist/esm/objects/ClassComponent.js +1 -1
- package/dist/esm/objects/ExecutionScope.js +1 -1
- package/dist/esm/objects/NumericValue.js +15 -0
- package/dist/esm/objects/PinDefinition.js +1 -1
- package/dist/esm/objects/types.js +1 -1
- package/dist/esm/parser.js +2 -1
- package/dist/esm/pipeline.js +10 -3
- package/dist/esm/regenerate-tests.js +6 -6
- package/dist/esm/render/draw_symbols.js +15 -15
- package/dist/esm/render/geometry.js +6 -6
- package/dist/esm/render/layout.js +325 -253
- package/dist/esm/render/render.js +22 -19
- package/dist/esm/semantic-tokens/getSemanticTokens.js +1 -1
- package/dist/esm/sizing.js +2 -2
- package/dist/esm/utils.js +10 -95
- package/dist/esm/validate/validateScript.js +1 -1
- package/dist/esm/visitor.js +4 -2
- package/dist/libs/std.cst +31 -31
- package/dist/types/BaseVisitor.d.ts +3 -1
- package/dist/types/errors.d.ts +37 -0
- package/dist/types/execute.d.ts +1 -1
- package/dist/types/helpers.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/objects/NumericValue.d.ts +5 -1
- package/dist/types/render/geometry.d.ts +4 -4
- package/dist/types/render/layout.d.ts +7 -1
- package/dist/types/utils.d.ts +2 -27
- package/dist/types/visitor.d.ts +1 -1
- package/libs/std.cst +31 -31
- package/package.json +5 -2
|
@@ -5,6 +5,7 @@ import { DefaultComponentUnit, defaultFrameTitleTextSize, defaultGridSizeUnits,
|
|
|
5
5
|
import { Geometry, HorizontalAlign, VerticalAlign } from './geometry.js';
|
|
6
6
|
import { FixedFrameIds, Frame, FrameParamKeys, FramePlotDirection } from '../objects/Frame.js';
|
|
7
7
|
import { areasOverlap, combineMaps, getBoundsSize, printBounds, resizeBounds, resizeToNearestGrid, toNearestGrid } from '../utils.js';
|
|
8
|
+
import { AutoWireFailedError_ } from "../errors.js";
|
|
8
9
|
import { Direction } from '../objects/types.js';
|
|
9
10
|
import { PinId } from '../objects/PinDefinition.js';
|
|
10
11
|
import { milsToMM, UnitDimension } from '../helpers.js';
|
|
@@ -177,6 +178,7 @@ export class LayoutEngine {
|
|
|
177
178
|
placeFrames(graph, subgraphInfo, frameObjects) {
|
|
178
179
|
const baseFrame = frameObjects[0];
|
|
179
180
|
baseFrame.padding = numeric(0);
|
|
181
|
+
baseFrame.gap = numeric(defaultGridSizeUnits);
|
|
180
182
|
baseFrame.borderWidth = numeric(0);
|
|
181
183
|
if (this.showBaseFrame) {
|
|
182
184
|
baseFrame.borderWidth = numeric(5);
|
|
@@ -253,51 +255,49 @@ export class LayoutEngine {
|
|
|
253
255
|
});
|
|
254
256
|
}
|
|
255
257
|
placeAndSizeFrame(frame, level = 0) {
|
|
258
|
+
if (level > 50) {
|
|
259
|
+
throw 'Exceeded placeAndSizeFrame depth limit!';
|
|
260
|
+
}
|
|
261
|
+
this.printLevel(level, `placeAndSizeFrame called`);
|
|
256
262
|
const innerFrames = frame.innerItems;
|
|
257
263
|
const gridSize = defaultGridSizeUnits;
|
|
258
264
|
const frameDirection = frame.direction;
|
|
259
|
-
const
|
|
260
|
-
|
|
265
|
+
const isFrameDirectionRow = frameDirection === FramePlotDirection.Row;
|
|
266
|
+
this.printLevel(level, `frame info, id: ${frame.frameId}, direction: ${frameDirection}, virtual: ${frame.virtual}`);
|
|
267
|
+
const frameParams = frame.frame.parameters;
|
|
268
|
+
let hAlign = HorizontalAlign.Center;
|
|
269
|
+
let vAlign = VerticalAlign.Top;
|
|
270
|
+
if (frameParams.has(FrameParamKeys.HorizontalAlign)) {
|
|
271
|
+
hAlign =
|
|
272
|
+
frameParams.get(FrameParamKeys.HorizontalAlign);
|
|
273
|
+
}
|
|
274
|
+
if (frameParams.has(FrameParamKeys.VerticalAlign)) {
|
|
275
|
+
vAlign =
|
|
276
|
+
frameParams.get(FrameParamKeys.VerticalAlign);
|
|
277
|
+
}
|
|
278
|
+
if (frame.overwriteAlignParamsForTitleLayout) {
|
|
279
|
+
hAlign = HorizontalAlign.Center;
|
|
280
|
+
vAlign = VerticalAlign.Top;
|
|
281
|
+
}
|
|
282
|
+
this.printLevel(level, `align params: ${hAlign} ${vAlign}`);
|
|
283
|
+
this.printLevel(level, `size inner frames, length: ${innerFrames.length}`);
|
|
284
|
+
for (const innerFrame of innerFrames) {
|
|
261
285
|
if (innerFrame.renderType === RenderFrameType.Elements) {
|
|
262
|
-
|
|
286
|
+
if (!innerFrame.didResize) {
|
|
287
|
+
innerFrame.bounds = resizeToNearestGrid(innerFrame.bounds, gridSize);
|
|
288
|
+
innerFrame.didResize = true;
|
|
289
|
+
}
|
|
263
290
|
innerFrame.translateX = innerFrame.bounds.xmin;
|
|
264
291
|
innerFrame.translateY = innerFrame.bounds.ymin;
|
|
292
|
+
this.printLevel(level, `element frame, id: ${innerFrame.frameId}, bounds: ${JSON.stringify(innerFrame.bounds)}`);
|
|
265
293
|
}
|
|
266
294
|
else {
|
|
267
295
|
this.placeAndSizeFrame(innerFrame, level + 1);
|
|
268
296
|
}
|
|
269
|
-
return innerFrame.bounds;
|
|
270
|
-
});
|
|
271
|
-
const maxWidth = Math.max(...frameSizes.map(item => {
|
|
272
|
-
const { width } = getBoundsSize(item);
|
|
273
|
-
return width;
|
|
274
|
-
}));
|
|
275
|
-
const maxHeight = Math.max(...frameSizes.map(item => {
|
|
276
|
-
const { height } = getBoundsSize(item);
|
|
277
|
-
return height;
|
|
278
|
-
}));
|
|
279
|
-
let accumRowWidth = 0;
|
|
280
|
-
let titleFrameWidth = 0;
|
|
281
|
-
const inRowShouldCenterInnerFrames = true;
|
|
282
|
-
if (frameDirection === FramePlotDirection.Row) {
|
|
283
|
-
accumRowWidth = frameSizes.reduce((accum, item, index) => {
|
|
284
|
-
const { width } = getBoundsSize(item);
|
|
285
|
-
if (frame.innerItems[index].containsTitle) {
|
|
286
|
-
titleFrameWidth = width;
|
|
287
|
-
return accum;
|
|
288
|
-
}
|
|
289
|
-
return accum + width +
|
|
290
|
-
((index + 1 < frameSizes.length) ? frame.gap.toNumber() : 0);
|
|
291
|
-
}, 0);
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
accumRowWidth = maxWidth;
|
|
295
297
|
}
|
|
298
|
+
this.printLevel(level, 'done sizing inner frames');
|
|
296
299
|
let frameWidth = numeric(0);
|
|
297
300
|
let frameHeight = numeric(0);
|
|
298
|
-
let frameXMin = numeric(0);
|
|
299
|
-
let frameYMin = numeric(0);
|
|
300
|
-
const frameParams = frame.frame.parameters;
|
|
301
301
|
const avoidAreas = [];
|
|
302
302
|
if (frameParams.has(FrameParamKeys.SheetType)) {
|
|
303
303
|
const frameComponent = frameParams.get(FrameParamKeys.SheetType);
|
|
@@ -327,6 +327,9 @@ export class LayoutEngine {
|
|
|
327
327
|
milsToMM(y2).sub(frameMinY).toNumber(),
|
|
328
328
|
]);
|
|
329
329
|
});
|
|
330
|
+
if (!frameParams.has(FrameParamKeys.VerticalAlign)) {
|
|
331
|
+
vAlign = VerticalAlign.Center;
|
|
332
|
+
}
|
|
330
333
|
}
|
|
331
334
|
else {
|
|
332
335
|
if (frame.width !== null) {
|
|
@@ -336,197 +339,144 @@ export class LayoutEngine {
|
|
|
336
339
|
frameHeight = frame.height;
|
|
337
340
|
}
|
|
338
341
|
}
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
if (
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
342
|
+
const innerFramesWithoutTitle = innerFrames.filter(item => !item.containsTitle);
|
|
343
|
+
this.printLevel(level, `split into lines, width: ${frameWidth.toNumber()} height: ${frameHeight.toNumber()}, padding: ${frame.padding.toNumber()}, gap: ${frame.gap.toNumber()}, direction: ${frameDirection}`);
|
|
344
|
+
const frameLines = SplitIntoLines(frameWidth, frameHeight, frame.padding, frame.gap, frameDirection, innerFramesWithoutTitle, avoidAreas);
|
|
345
|
+
this.printLevel(level, `frame lines: ${frameLines.length}`);
|
|
346
|
+
if (frameLines.length > 1) {
|
|
347
|
+
this.printLevel(level, `split lines to containers`);
|
|
348
|
+
const newInnerFrames = [];
|
|
349
|
+
for (const line of frameLines) {
|
|
350
|
+
const container = RenderFrame.createContainer(frame.gap);
|
|
351
|
+
container.innerItems = [...line];
|
|
352
|
+
container.direction = frameDirection;
|
|
353
|
+
container.frame.parameters.set(FrameParamKeys.HorizontalAlign, hAlign);
|
|
354
|
+
container.frame.parameters.set(FrameParamKeys.VerticalAlign, vAlign);
|
|
355
|
+
if (isFrameDirectionRow) {
|
|
356
|
+
if (frameWidth.toNumber() !== 0) {
|
|
357
|
+
container.width = frameWidth.sub(frame.padding.mul(2));
|
|
358
|
+
}
|
|
359
|
+
const itemHeights = container.innerItems.map(frame => {
|
|
360
|
+
const bounds = frame.bounds;
|
|
361
|
+
return (bounds.ymax - bounds.ymin);
|
|
362
|
+
});
|
|
363
|
+
const maxHeight = Math.max(...itemHeights);
|
|
364
|
+
container.height = numeric(maxHeight);
|
|
365
|
+
this.printLevel(level, `set container size w: ${container.width}, h: ${container.height}`);
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
if (frameHeight.toNumber() !== 0) {
|
|
369
|
+
container.height = frameHeight.sub(frame.padding.mul(2));
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
newInnerFrames.push(container);
|
|
373
|
+
}
|
|
374
|
+
const container = RenderFrame.createContainer(frame.gap);
|
|
375
|
+
container.direction = isFrameDirectionRow ? FramePlotDirection.Column : FramePlotDirection.Row;
|
|
376
|
+
container.innerItems = newInnerFrames;
|
|
377
|
+
frame.innerItems = [container];
|
|
378
|
+
this.placeAndSizeFrame(frame, level + 1);
|
|
348
379
|
}
|
|
349
380
|
else {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
let innerFrameX = numeric(0);
|
|
369
|
-
let innerFrameY = numeric(0);
|
|
370
|
-
if (innerFrame.containsTitle) {
|
|
371
|
-
innerFrame.x = offsetX.add(accumX);
|
|
372
|
-
innerFrame.y = offsetY.add(accumY);
|
|
373
|
-
accumY = accumY.add(innerFrameHeight).add(frame.gap);
|
|
381
|
+
let accumValue = frame.padding.copy();
|
|
382
|
+
const bounds = [];
|
|
383
|
+
for (const innerFrame of innerFrames) {
|
|
384
|
+
const { width: innerFrameWidth, height: innerFrameHeight } = getBoundsSize(innerFrame.bounds);
|
|
385
|
+
if (isFrameDirectionRow) {
|
|
386
|
+
innerFrame.x = accumValue.copy();
|
|
387
|
+
innerFrame.y = frame.padding.copy();
|
|
388
|
+
accumValue = accumValue.add(innerFrameWidth).add(frame.gap);
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
innerFrame.x = frame.padding.copy();
|
|
392
|
+
innerFrame.y = accumValue.copy();
|
|
393
|
+
accumValue = accumValue.add(innerFrameHeight).add(frame.gap);
|
|
394
|
+
}
|
|
395
|
+
bounds.push([innerFrame.x.toNumber(), innerFrame.y.toNumber()], [
|
|
396
|
+
innerFrame.x.add(innerFrameWidth).toNumber(),
|
|
397
|
+
innerFrame.y.add(innerFrameHeight).toNumber(),
|
|
398
|
+
]);
|
|
374
399
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
400
|
+
const frameInnerBounds = getBoundsFromPoints(bounds);
|
|
401
|
+
const contentsPaddedBounds = resizeBounds(frameInnerBounds, frame.padding.toNumber());
|
|
402
|
+
const contentsPaddedWidth = roundValue(contentsPaddedBounds.xmax - contentsPaddedBounds.xmin).toNumber();
|
|
403
|
+
const contentsPaddedHeight = roundValue(contentsPaddedBounds.ymax - contentsPaddedBounds.ymin).toNumber();
|
|
404
|
+
const contentsWidth = roundValue(frameInnerBounds.xmax - frameInnerBounds.xmin).toNumber();
|
|
405
|
+
const contentsHeight = roundValue(frameInnerBounds.ymax - frameInnerBounds.ymin).toNumber();
|
|
406
|
+
if (frameWidth.toNumber() === 0) {
|
|
407
|
+
frameWidth = numeric(contentsPaddedWidth);
|
|
408
|
+
}
|
|
409
|
+
if (frameHeight.toNumber() === 0) {
|
|
410
|
+
frameHeight = numeric(contentsPaddedHeight);
|
|
411
|
+
}
|
|
412
|
+
frame.bounds = {
|
|
413
|
+
xmin: contentsPaddedBounds.xmin,
|
|
414
|
+
xmax: contentsPaddedBounds.xmin + frameWidth.toNumber(),
|
|
415
|
+
ymin: contentsPaddedBounds.ymin,
|
|
416
|
+
ymax: contentsPaddedBounds.ymin + frameHeight.toNumber(),
|
|
417
|
+
};
|
|
418
|
+
this.printLevel(level, `alignment h: ${hAlign}, v: ${vAlign}`);
|
|
419
|
+
const tmpFrameWidth = frameWidth.sub(frame.padding.mul(2));
|
|
420
|
+
const tmpFrameHeight = frameHeight.sub(frame.padding.mul(2));
|
|
421
|
+
this.printLevel(level, `inner frame size, width: ${tmpFrameWidth}, height: ${tmpFrameHeight}`);
|
|
422
|
+
let offsetX = 0;
|
|
423
|
+
let offsetY = 0;
|
|
424
|
+
if (isFrameDirectionRow) {
|
|
425
|
+
switch (hAlign) {
|
|
426
|
+
case HorizontalAlign.Left:
|
|
427
|
+
offsetX = 0;
|
|
428
|
+
break;
|
|
429
|
+
case HorizontalAlign.Center:
|
|
430
|
+
offsetX = toNearestGrid(tmpFrameWidth.sub(contentsWidth).div(2).toNumber(), gridSize);
|
|
431
|
+
break;
|
|
432
|
+
case HorizontalAlign.Right:
|
|
433
|
+
offsetX = toNearestGrid(tmpFrameWidth.sub(contentsWidth).toNumber(), gridSize);
|
|
434
|
+
break;
|
|
435
|
+
}
|
|
436
|
+
offsetX = roundValue(offsetX).toNumber();
|
|
437
|
+
offsetY = 0;
|
|
438
|
+
for (const innerFrame of innerFrames) {
|
|
439
|
+
const { height: innerFrameHeight } = getBoundsSize(innerFrame.bounds);
|
|
440
|
+
if (vAlign === VerticalAlign.Center) {
|
|
441
|
+
offsetY = toNearestGrid(tmpFrameHeight.sub(innerFrameHeight).div(2).toNumber(), gridSize);
|
|
442
|
+
}
|
|
443
|
+
else if (vAlign === VerticalAlign.Bottom) {
|
|
444
|
+
offsetY = toNearestGrid(tmpFrameHeight.sub(innerFrameHeight).toNumber(), gridSize);
|
|
402
445
|
}
|
|
403
|
-
|
|
404
|
-
innerFrame.
|
|
405
|
-
|
|
446
|
+
offsetY = roundValue(offsetY).toNumber();
|
|
447
|
+
innerFrame.x = innerFrame.x.add(offsetX);
|
|
448
|
+
innerFrame.y = innerFrame.y.add(offsetY);
|
|
406
449
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
accumX = numeric(0);
|
|
427
|
-
accumY = nextY;
|
|
428
|
-
}
|
|
429
|
-
else {
|
|
430
|
-
break;
|
|
431
|
-
}
|
|
432
|
-
arrangeLineAttempts++;
|
|
433
|
-
if (arrangeLineAttempts > maxAttempts) {
|
|
434
|
-
throw "Failed to place inner frame";
|
|
435
|
-
}
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
switch (vAlign) {
|
|
453
|
+
case VerticalAlign.Top:
|
|
454
|
+
offsetY = 0;
|
|
455
|
+
break;
|
|
456
|
+
case VerticalAlign.Center:
|
|
457
|
+
offsetY = toNearestGrid(tmpFrameHeight.sub(contentsHeight).div(2).toNumber(), gridSize);
|
|
458
|
+
break;
|
|
459
|
+
case VerticalAlign.Bottom:
|
|
460
|
+
offsetY = toNearestGrid(tmpFrameHeight.sub(contentsHeight).toNumber(), gridSize);
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
offsetX = 0;
|
|
464
|
+
offsetY = roundValue(offsetY).toNumber();
|
|
465
|
+
for (const innerFrame of innerFrames) {
|
|
466
|
+
const { width: innerFrameHeight } = getBoundsSize(innerFrame.bounds);
|
|
467
|
+
if (hAlign === HorizontalAlign.Center) {
|
|
468
|
+
offsetX = toNearestGrid(tmpFrameWidth.sub(innerFrameHeight).div(2).toNumber(), gridSize);
|
|
436
469
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
470
|
+
else if (hAlign === HorizontalAlign.Right) {
|
|
471
|
+
offsetX = toNearestGrid(tmpFrameWidth.sub(innerFrameHeight).toNumber(), gridSize);
|
|
472
|
+
}
|
|
473
|
+
offsetX = roundValue(offsetX).toNumber();
|
|
474
|
+
innerFrame.x = innerFrame.x.add(offsetX);
|
|
475
|
+
innerFrame.y = innerFrame.y.add(offsetY);
|
|
440
476
|
}
|
|
441
477
|
}
|
|
442
|
-
boundPoints.push([
|
|
443
|
-
innerFrame.x.toNumber(),
|
|
444
|
-
innerFrame.y.toNumber()
|
|
445
|
-
], [
|
|
446
|
-
innerFrame.x.add(innerFrameWidth).toNumber(),
|
|
447
|
-
innerFrame.y.add(innerFrameHeight).toNumber()
|
|
448
|
-
]);
|
|
449
|
-
});
|
|
450
|
-
const contentsBounds = resizeBounds(getBoundsFromPoints(boundPoints), frame.padding.toNumber());
|
|
451
|
-
const contentsWidth = contentsBounds.xmax - contentsBounds.xmin;
|
|
452
|
-
const contentsHeight = contentsBounds.ymax - contentsBounds.ymin;
|
|
453
|
-
let hAlign = HorizontalAlign.Middle;
|
|
454
|
-
let vAlign = VerticalAlign.Middle;
|
|
455
|
-
if (frameParams.has(FrameParamKeys.HorizontalAlign)) {
|
|
456
|
-
hAlign =
|
|
457
|
-
frameParams.get(FrameParamKeys.HorizontalAlign);
|
|
458
478
|
}
|
|
459
|
-
|
|
460
|
-
vAlign =
|
|
461
|
-
frameParams.get(FrameParamKeys.VerticalAlign);
|
|
462
|
-
}
|
|
463
|
-
if (frameParams.has(FrameParamKeys.SheetType)) {
|
|
464
|
-
frameXMin = numeric(0);
|
|
465
|
-
frameYMin = numeric(0);
|
|
466
|
-
}
|
|
467
|
-
else {
|
|
468
|
-
frameXMin = numeric(contentsBounds.xmin);
|
|
469
|
-
frameYMin = numeric(contentsBounds.ymin);
|
|
470
|
-
}
|
|
471
|
-
if (frameWidth.toNumber() === 0) {
|
|
472
|
-
frameWidth = numeric(contentsWidth);
|
|
473
|
-
}
|
|
474
|
-
if (frameHeight.toNumber() === 0) {
|
|
475
|
-
frameHeight = numeric(contentsHeight);
|
|
476
|
-
}
|
|
477
|
-
const titleFrame = innerFrames.find(frame => {
|
|
478
|
-
return frame.containsTitle;
|
|
479
|
-
});
|
|
480
|
-
if (titleFrame) {
|
|
481
|
-
const { width: innerFrameWidth } = getBoundsSize(titleFrame.bounds);
|
|
482
|
-
let titleOffset = 0;
|
|
483
|
-
switch (title_align) {
|
|
484
|
-
case HorizontalAlign.Left:
|
|
485
|
-
titleOffset = 0;
|
|
486
|
-
break;
|
|
487
|
-
case HorizontalAlign.Middle:
|
|
488
|
-
titleOffset = toNearestGrid(widthForTitle / 2 - innerFrameWidth / 2, gridSize);
|
|
489
|
-
break;
|
|
490
|
-
case HorizontalAlign.Right:
|
|
491
|
-
titleOffset = frameWidth.toNumber() - innerFrameWidth;
|
|
492
|
-
break;
|
|
493
|
-
}
|
|
494
|
-
titleFrame.x = titleFrame.x.add(titleOffset);
|
|
495
|
-
}
|
|
496
|
-
let frameOffsetX = 0;
|
|
497
|
-
let frameOffsetY = 0;
|
|
498
|
-
switch (hAlign) {
|
|
499
|
-
case HorizontalAlign.Left:
|
|
500
|
-
frameOffsetX = 0;
|
|
501
|
-
break;
|
|
502
|
-
case HorizontalAlign.Middle:
|
|
503
|
-
frameOffsetX = toNearestGrid((frameWidth.toNumber() - contentsWidth) / 2, gridSize);
|
|
504
|
-
break;
|
|
505
|
-
case HorizontalAlign.Right:
|
|
506
|
-
frameOffsetX = toNearestGrid(frameWidth.toNumber() - contentsWidth, gridSize);
|
|
507
|
-
break;
|
|
508
|
-
}
|
|
509
|
-
switch (vAlign) {
|
|
510
|
-
case VerticalAlign.Top:
|
|
511
|
-
frameOffsetY = 0;
|
|
512
|
-
break;
|
|
513
|
-
case VerticalAlign.Middle:
|
|
514
|
-
frameOffsetY = toNearestGrid((frameHeight.toNumber() - contentsHeight) / 2, gridSize);
|
|
515
|
-
break;
|
|
516
|
-
case VerticalAlign.Bottom:
|
|
517
|
-
frameOffsetY = toNearestGrid(frameHeight.toNumber() - contentsHeight, gridSize);
|
|
518
|
-
break;
|
|
519
|
-
}
|
|
520
|
-
innerFrames.forEach(innerFrame => {
|
|
521
|
-
innerFrame.x = innerFrame.x.add(frameOffsetX);
|
|
522
|
-
innerFrame.y = innerFrame.y.add(frameOffsetY);
|
|
523
|
-
});
|
|
524
|
-
frame.bounds = {
|
|
525
|
-
xmin: frameXMin.toNumber(),
|
|
526
|
-
ymin: frameYMin.toNumber(),
|
|
527
|
-
xmax: frameXMin.toNumber() + frameWidth.toNumber(),
|
|
528
|
-
ymax: frameYMin.toNumber() + frameHeight.toNumber(),
|
|
529
|
-
};
|
|
479
|
+
return;
|
|
530
480
|
}
|
|
531
481
|
dumpFrame(frame, level = 0) {
|
|
532
482
|
this.print(level, "".padStart(level * 4), 'frame, items:', frame.innerItems.length);
|
|
@@ -593,33 +543,80 @@ export class LayoutEngine {
|
|
|
593
543
|
};
|
|
594
544
|
}
|
|
595
545
|
checkAddFrameTitle(frame, elementFrames, textObjects, level) {
|
|
596
|
-
if (frame.renderType
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
546
|
+
if (frame.renderType !== RenderFrameType.Container) {
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
const frameObject = frame.frame;
|
|
550
|
+
const frameParams = frame.frame.parameters;
|
|
551
|
+
const isSheetFrame = frameObject.frameType === FrameType.Sheet;
|
|
552
|
+
if (frameParams.has(FrameParamKeys.Title) && !isSheetFrame) {
|
|
553
|
+
const title = frameParams.get(FrameParamKeys.Title);
|
|
554
|
+
const titleFrame = new RenderFrame(new Frame(FixedFrameIds.FrameIdNotUsed), RenderFrameType.Elements);
|
|
555
|
+
titleFrame.containsTitle = true;
|
|
556
|
+
titleFrame.subgraphId = title.replace(/\s/g, "_");
|
|
557
|
+
const textObject = new RenderText(title);
|
|
558
|
+
textObject.fontSize = numeric(defaultFrameTitleTextSize);
|
|
559
|
+
textObject.fontWeight = 'bold';
|
|
560
|
+
textObject.x = numeric(0);
|
|
561
|
+
textObject.y = numeric(0);
|
|
562
|
+
textObject.symbol.refreshDrawing();
|
|
563
|
+
titleFrame.innerItems = [textObject];
|
|
564
|
+
const tmpBox = textObject.symbol.drawing.getBoundingBox();
|
|
565
|
+
const tmpBounds = {
|
|
566
|
+
xmin: tmpBox.start[0],
|
|
567
|
+
ymin: tmpBox.start[1],
|
|
568
|
+
xmax: tmpBox.start[0] + tmpBox.width,
|
|
569
|
+
ymax: tmpBox.start[1] + tmpBox.height
|
|
570
|
+
};
|
|
571
|
+
titleFrame.bounds = resizeToNearestGrid(tmpBounds, defaultGridSizeUnits);
|
|
572
|
+
titleFrame.didResize = true;
|
|
573
|
+
const titleFrameContainer = RenderFrame.createContainer(numeric(0));
|
|
574
|
+
titleFrameContainer.innerItems = [titleFrame];
|
|
575
|
+
if (frameParams.has(FrameParamKeys.TitleAlign)) {
|
|
576
|
+
const alignValue = frameParams.get(FrameParamKeys.TitleAlign);
|
|
577
|
+
titleFrameContainer.frame.parameters.set(FrameParamKeys.HorizontalAlign, alignValue);
|
|
578
|
+
}
|
|
579
|
+
const container = RenderFrame.createContainer(frame.gap);
|
|
580
|
+
container.direction = frame.direction;
|
|
581
|
+
container.innerItems = [...frame.innerItems];
|
|
582
|
+
let hAlign = HorizontalAlign.Center;
|
|
583
|
+
let vAlign = VerticalAlign.Center;
|
|
584
|
+
if (frameParams.has(FrameParamKeys.HorizontalAlign)) {
|
|
585
|
+
hAlign =
|
|
586
|
+
frameParams.get(FrameParamKeys.HorizontalAlign);
|
|
587
|
+
}
|
|
588
|
+
if (frameParams.has(FrameParamKeys.VerticalAlign)) {
|
|
589
|
+
vAlign =
|
|
590
|
+
frameParams.get(FrameParamKeys.VerticalAlign);
|
|
591
|
+
}
|
|
592
|
+
container.frame.parameters.set(FrameParamKeys.HorizontalAlign, hAlign);
|
|
593
|
+
container.frame.parameters.set(FrameParamKeys.VerticalAlign, vAlign);
|
|
594
|
+
const columnLayoutContainer = RenderFrame.createContainer(numeric(defaultGridSizeUnits));
|
|
595
|
+
columnLayoutContainer.direction = FramePlotDirection.Column;
|
|
596
|
+
columnLayoutContainer.innerItems = [
|
|
597
|
+
titleFrameContainer,
|
|
598
|
+
container,
|
|
599
|
+
];
|
|
600
|
+
const frameWidth = frame.width ?? numeric(0);
|
|
601
|
+
if (frameWidth.toNumber() !== 0) {
|
|
602
|
+
columnLayoutContainer.width = frameWidth.sub(frame.padding.mul(2));
|
|
603
|
+
container.width = columnLayoutContainer.width.copy();
|
|
604
|
+
titleFrameContainer.width = columnLayoutContainer.width.copy();
|
|
622
605
|
}
|
|
606
|
+
const frameHeight = frame.height ?? numeric(0);
|
|
607
|
+
if (frameHeight.toNumber() !== 0) {
|
|
608
|
+
columnLayoutContainer.height = frameHeight.sub(frame.padding.mul(2));
|
|
609
|
+
const { height: titleFrameHeight } = getBoundsSize(titleFrame.bounds);
|
|
610
|
+
container.height = columnLayoutContainer.height
|
|
611
|
+
.sub(titleFrameHeight)
|
|
612
|
+
.sub(columnLayoutContainer.gap);
|
|
613
|
+
}
|
|
614
|
+
frame.innerItems = [columnLayoutContainer];
|
|
615
|
+
frame.overwriteAlignParamsForTitleLayout = true;
|
|
616
|
+
columnLayoutContainer.overwriteAlignParamsForTitleLayout = true;
|
|
617
|
+
this.printLevel(level, frame, 'added text', titleFrame);
|
|
618
|
+
textObjects.push(textObject);
|
|
619
|
+
elementFrames.splice(0, 0, titleFrame);
|
|
623
620
|
}
|
|
624
621
|
}
|
|
625
622
|
sizeSubGraphs(graph) {
|
|
@@ -779,7 +776,7 @@ export class LayoutEngine {
|
|
|
779
776
|
const targetOriginNode = findOriginNode(targetNode);
|
|
780
777
|
const itemOriginNode = findOriginNode(item);
|
|
781
778
|
if (targetOriginNode !== itemOriginNode) {
|
|
782
|
-
throw "Wire auto length failed. Please specify a fixed wire length.";
|
|
779
|
+
throw new AutoWireFailedError_("Wire auto length failed. Please specify a fixed wire length.", item.wire);
|
|
783
780
|
}
|
|
784
781
|
const [untilX, untilY] = getNodePositionAtPin(targetNode, pin);
|
|
785
782
|
item.setEndAuto(untilX, untilY);
|
|
@@ -915,17 +912,6 @@ function getNodePositionAtPin(item, pin) {
|
|
|
915
912
|
roundValue(x), roundValue(y)
|
|
916
913
|
];
|
|
917
914
|
}
|
|
918
|
-
function getNeighbours(graph, nodeIds) {
|
|
919
|
-
return nodeIds.reduce((accum, nodeId) => {
|
|
920
|
-
const tmp = graph.neighbors(nodeId);
|
|
921
|
-
if (tmp) {
|
|
922
|
-
tmp.forEach(neighborNodeId => {
|
|
923
|
-
accum.push([nodeId, neighborNodeId]);
|
|
924
|
-
});
|
|
925
|
-
}
|
|
926
|
-
return accum;
|
|
927
|
-
}, []);
|
|
928
|
-
}
|
|
929
915
|
export function applyComponentParamsToSymbol(componentUnit, symbol) {
|
|
930
916
|
const { widthProp = null, heightProp = null } = componentUnit;
|
|
931
917
|
const newMap = new Map(componentUnit.parameters);
|
|
@@ -1255,19 +1241,25 @@ export class RenderFrame extends RenderObject {
|
|
|
1255
1241
|
padding = milsToMM(100);
|
|
1256
1242
|
gap = milsToMM(100);
|
|
1257
1243
|
borderWidth = numeric(5);
|
|
1244
|
+
borderColor = "#111";
|
|
1258
1245
|
direction = FramePlotDirection.Row;
|
|
1259
1246
|
width = null;
|
|
1260
1247
|
height = null;
|
|
1261
1248
|
subgraphId = "";
|
|
1262
1249
|
renderType;
|
|
1263
1250
|
containsTitle = false;
|
|
1251
|
+
overwriteAlignParamsForTitleLayout = false;
|
|
1252
|
+
virtual = false;
|
|
1253
|
+
didResize = false;
|
|
1254
|
+
lineIndex = 0;
|
|
1264
1255
|
frameId;
|
|
1265
|
-
constructor(frame, type = RenderFrameType.Container) {
|
|
1256
|
+
constructor(frame, type = RenderFrameType.Container, virtual = false) {
|
|
1266
1257
|
super();
|
|
1267
1258
|
this.frame = frame;
|
|
1268
1259
|
this.renderType = type;
|
|
1269
1260
|
this.frameId = RenderFrame.FrameIdCounter;
|
|
1270
1261
|
RenderFrame.FrameIdCounter++;
|
|
1262
|
+
this.virtual = virtual;
|
|
1271
1263
|
}
|
|
1272
1264
|
toString() {
|
|
1273
1265
|
let name = "";
|
|
@@ -1280,6 +1272,13 @@ export class RenderFrame extends RenderObject {
|
|
|
1280
1272
|
return name + ": " + this.x + "," + this.y
|
|
1281
1273
|
+ " bounds:" + (this.bounds && printBounds(this.bounds));
|
|
1282
1274
|
}
|
|
1275
|
+
static createContainer(gap) {
|
|
1276
|
+
const tmpFrame = new RenderFrame(new Frame(FixedFrameIds.FrameIdNotUsed), RenderFrameType.Container, true);
|
|
1277
|
+
tmpFrame.gap = gap.copy();
|
|
1278
|
+
tmpFrame.borderWidth = numeric(0);
|
|
1279
|
+
tmpFrame.padding = numeric(0);
|
|
1280
|
+
return tmpFrame;
|
|
1281
|
+
}
|
|
1283
1282
|
}
|
|
1284
1283
|
export var RenderFrameType;
|
|
1285
1284
|
(function (RenderFrameType) {
|
|
@@ -1338,3 +1337,76 @@ export function ExtractDrawingRects(drawing) {
|
|
|
1338
1337
|
function isPointOverlap(x, y, other) {
|
|
1339
1338
|
return (x >= other.x && y >= other.y && x <= (other.x + other.width) && y <= (other.y + other.height));
|
|
1340
1339
|
}
|
|
1340
|
+
function SplitIntoLines(frameWidth, frameHeight, framePadding, frameGap, frameDirection, innerFrames, avoidAreas) {
|
|
1341
|
+
if (frameWidth.toNumber() === 0) {
|
|
1342
|
+
frameWidth = numeric(1e24);
|
|
1343
|
+
}
|
|
1344
|
+
if (frameHeight.toNumber() === 0) {
|
|
1345
|
+
frameHeight = numeric(1e24);
|
|
1346
|
+
}
|
|
1347
|
+
const allGroups = [];
|
|
1348
|
+
let currentGroup = [];
|
|
1349
|
+
const tmpFrameWidth = frameWidth.sub(framePadding.mul(2)).toNumber();
|
|
1350
|
+
const tmpFrameHeight = frameHeight.sub(framePadding.mul(2)).toNumber();
|
|
1351
|
+
const isRowDirection = frameDirection === FramePlotDirection.Row;
|
|
1352
|
+
const dimensionLimit = isRowDirection ? tmpFrameWidth : tmpFrameHeight;
|
|
1353
|
+
let accumX = numeric(0);
|
|
1354
|
+
let accumY = numeric(0);
|
|
1355
|
+
const framePaddingValue = framePadding.toNumber();
|
|
1356
|
+
avoidAreas = avoidAreas.map(bounds => {
|
|
1357
|
+
return [
|
|
1358
|
+
bounds[0] - framePaddingValue,
|
|
1359
|
+
bounds[1] - framePaddingValue,
|
|
1360
|
+
bounds[2] - framePaddingValue,
|
|
1361
|
+
bounds[3] - framePaddingValue
|
|
1362
|
+
];
|
|
1363
|
+
});
|
|
1364
|
+
for (const innerFrame of innerFrames) {
|
|
1365
|
+
const { width: innerFrameWidth, height: innerFrameHeight } = getBoundsSize(innerFrame.bounds);
|
|
1366
|
+
const tmpX1 = accumX.toNumber();
|
|
1367
|
+
const tmpY1 = accumY.toNumber();
|
|
1368
|
+
const tmpX2 = tmpX1 + innerFrameWidth;
|
|
1369
|
+
const tmpY2 = tmpY1 + innerFrameHeight;
|
|
1370
|
+
const frameArea = [tmpX1, tmpY1, tmpX2, tmpY2];
|
|
1371
|
+
const conditionOverlapAvoidAreas = avoidAreas.filter(area => areasOverlap(frameArea, area)).length > 0;
|
|
1372
|
+
if (isRowDirection) {
|
|
1373
|
+
const tmpX = accumX.add(innerFrameWidth).toNumber();
|
|
1374
|
+
const conditionExceedDimension = tmpX > dimensionLimit;
|
|
1375
|
+
if ((conditionExceedDimension || conditionOverlapAvoidAreas) && currentGroup.length > 0) {
|
|
1376
|
+
allGroups.push(currentGroup);
|
|
1377
|
+
const heightsInLine = currentGroup.map(item => item.height);
|
|
1378
|
+
const maxHeight = Math.max(...heightsInLine);
|
|
1379
|
+
accumX = numeric(0);
|
|
1380
|
+
accumY = accumY.add(frameGap).add(maxHeight);
|
|
1381
|
+
currentGroup = [];
|
|
1382
|
+
}
|
|
1383
|
+
accumX = accumX.add(innerFrameWidth).add(frameGap);
|
|
1384
|
+
}
|
|
1385
|
+
else {
|
|
1386
|
+
const tmpY = accumY.add(innerFrameHeight).toNumber();
|
|
1387
|
+
const conditionExistDimension = tmpY > dimensionLimit;
|
|
1388
|
+
if ((conditionExistDimension || conditionOverlapAvoidAreas) && currentGroup.length > 0) {
|
|
1389
|
+
allGroups.push(currentGroup);
|
|
1390
|
+
const widthsInLine = currentGroup.map(item => item.width);
|
|
1391
|
+
const maxWidth = Math.max(...widthsInLine);
|
|
1392
|
+
accumX = accumX.add(frameGap).add(maxWidth);
|
|
1393
|
+
accumY = numeric(0);
|
|
1394
|
+
currentGroup = [];
|
|
1395
|
+
}
|
|
1396
|
+
accumY = accumY.add(innerFrameHeight).add(frameGap);
|
|
1397
|
+
}
|
|
1398
|
+
currentGroup.push({
|
|
1399
|
+
x: accumX.toNumber(),
|
|
1400
|
+
y: accumY.toNumber(),
|
|
1401
|
+
width: innerFrameWidth,
|
|
1402
|
+
height: innerFrameHeight,
|
|
1403
|
+
frame: innerFrame
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
if (currentGroup.length > 0) {
|
|
1407
|
+
allGroups.push(currentGroup);
|
|
1408
|
+
}
|
|
1409
|
+
return allGroups.map(lines => {
|
|
1410
|
+
return lines.map(layoutItem => layoutItem.frame);
|
|
1411
|
+
});
|
|
1412
|
+
}
|