circuitscript 0.0.26 → 0.0.28

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.
@@ -256,7 +256,7 @@ class SymbolText extends SymbolGraphic {
256
256
  }
257
257
  generateDrawing() {
258
258
  const drawing = new SymbolDrawing();
259
- drawing.addLabel(0, 0, this.text, {
259
+ drawing.addTextbox(0, 0, this.text, {
260
260
  fontSize: this.fontSize,
261
261
  anchor: geometry_js_1.HorizontalAlign.Middle,
262
262
  fontWeight: this.fontWeight,
@@ -322,13 +322,7 @@ class SymbolPlaceholder extends SymbolGraphic {
322
322
  break;
323
323
  }
324
324
  case PlaceHolderCommands.label: {
325
- const keywords = ['fontSize', 'anchor', 'vanchor', 'angle'];
326
- const style = {};
327
- keywords.forEach(item => {
328
- if (keywordParams.has(item)) {
329
- style[item] = keywordParams.get(item);
330
- }
331
- });
325
+ const style = this.parseLabelStyle(keywordParams);
332
326
  positionParams = [...positionParams];
333
327
  positionParams.push(style);
334
328
  const labelId = positionParams[0];
@@ -341,10 +335,33 @@ class SymbolPlaceholder extends SymbolGraphic {
341
335
  drawing.addLabelId(...tmpPositionParams);
342
336
  break;
343
337
  }
338
+ case PlaceHolderCommands.text: {
339
+ const style = this.parseLabelStyle(keywordParams);
340
+ const content = keywordParams.get('content');
341
+ let offsetX = 0;
342
+ let offsetY = 0;
343
+ if (keywordParams.has('offset')) {
344
+ const offset = keywordParams.get('offset');
345
+ offsetX = offset[0];
346
+ offsetY = offset[1];
347
+ }
348
+ drawing.addTextbox(offsetX, offsetY, content, style);
349
+ break;
350
+ }
344
351
  }
345
352
  });
346
353
  drawing.log("=== end generate drawing ===");
347
354
  }
355
+ parseLabelStyle(keywordParams) {
356
+ const keywords = ['fontSize', 'anchor', 'vanchor', 'angle'];
357
+ const style = {};
358
+ keywords.forEach(item => {
359
+ if (keywordParams.has(item)) {
360
+ style[item] = keywordParams.get(item);
361
+ }
362
+ });
363
+ return style;
364
+ }
348
365
  drawPinParams(drawing, commandName, keywordParams, positionParams) {
349
366
  drawing.log('add pin', ...positionParams);
350
367
  const keywordDisplayPinId = 'display_pin_id';
@@ -455,6 +472,7 @@ var PlaceHolderCommands;
455
472
  PlaceHolderCommands["lineWidth"] = "lineWidth";
456
473
  PlaceHolderCommands["fill"] = "fill";
457
474
  PlaceHolderCommands["lineColor"] = "lineColor";
475
+ PlaceHolderCommands["text"] = "text";
458
476
  })(PlaceHolderCommands || (exports.PlaceHolderCommands = PlaceHolderCommands = {}));
459
477
  class SymbolCustom extends SymbolGraphic {
460
478
  constructor(pinDefinition) {
@@ -643,6 +661,10 @@ class SymbolDrawing {
643
661
  this.items.push(geometry_js_1.Geometry.label(id, x, y, textValue, style));
644
662
  return this;
645
663
  }
664
+ addTextbox(x, y, textValue, style) {
665
+ this.items.push(geometry_js_1.Geometry.textbox(null, x, y, textValue, style));
666
+ return this;
667
+ }
646
668
  addPath(...pathParts) {
647
669
  const parts = pathParts.reduce((accum, tmp) => {
648
670
  if (typeof tmp === "string") {
@@ -717,7 +739,7 @@ class SymbolDrawing {
717
739
  let currentLineColor = '#333';
718
740
  const pathItems = [];
719
741
  this.items.forEach(item => {
720
- if (!(item instanceof geometry_js_1.Label)) {
742
+ if (!(item instanceof geometry_js_1.Textbox)) {
721
743
  if (item instanceof geometry_js_1.GeometryProp) {
722
744
  if (item.name === 'lineWidth') {
723
745
  currentLineWidth = item.value;
@@ -732,7 +754,7 @@ class SymbolDrawing {
732
754
  else {
733
755
  let tmpResult = geometry_js_1.Geometry.groupFlip([item], this.flipX, this.flipY);
734
756
  tmpResult = geometry_js_1.Geometry.groupRotate(tmpResult, this.angle, this.mainOrigin);
735
- const { path, isClosedPolygon } = this.featuresToPath(tmpResult);
757
+ const { path, isClosedPolygon } = this.featuresToPath(tmpResult, this.flipX, this.flipY);
736
758
  pathItems.push({
737
759
  path: path,
738
760
  lineWidth: currentLineWidth,
@@ -748,21 +770,21 @@ class SymbolDrawing {
748
770
  let features = this.pins.map(item => item[1]);
749
771
  features = geometry_js_1.Geometry.groupFlip(features, this.flipX, this.flipY);
750
772
  features = geometry_js_1.Geometry.groupRotate(features, this.angle, this.mainOrigin);
751
- const { path } = this.featuresToPath(features);
773
+ const { path } = this.featuresToPath(features, this.flipX, this.flipY);
752
774
  return path;
753
775
  }
754
776
  getLabels() {
755
- return this.items.filter(item => item instanceof geometry_js_1.Label);
777
+ return this.items.filter(item => item instanceof geometry_js_1.Textbox);
756
778
  }
757
- featuresToPath(items) {
758
- return geometry_js_1.Geometry.featuresToPath(items);
779
+ featuresToPath(items, flipX, flipY) {
780
+ return geometry_js_1.Geometry.featuresToPath(items, flipX, flipY);
759
781
  }
760
782
  getBoundingBox(excludeLabels = false) {
761
783
  const pinFeatures = this.pins.map(pin => {
762
784
  return pin[1];
763
785
  });
764
786
  const drawingFeatures = this.items.reduce((accum, item) => {
765
- if (!excludeLabels || (excludeLabels && !(item instanceof geometry_js_1.Label))) {
787
+ if (!excludeLabels || (excludeLabels && !(item instanceof geometry_js_1.Textbox && item.label))) {
766
788
  if (!(item instanceof geometry_js_1.GeometryProp)) {
767
789
  accum.push(item);
768
790
  }
@@ -6,8 +6,10 @@ const ClassComponent_js_1 = require("./objects/ClassComponent.js");
6
6
  const ExecutionScope_js_1 = require("./objects/ExecutionScope.js");
7
7
  const Net_js_1 = require("./objects/Net.js");
8
8
  const PinDefinition_js_1 = require("./objects/PinDefinition.js");
9
+ const types_js_1 = require("./objects/types.js");
9
10
  const Wire_js_1 = require("./objects/Wire.js");
10
11
  const Frame_js_1 = require("./objects/Frame.js");
12
+ const layout_js_1 = require("./layout.js");
11
13
  class ExecutionContext {
12
14
  constructor(name, namespace, netNamespace, executionLevel = 0, indentLevel = 0, silent = false, logger, parent) {
13
15
  this.tmpPointId = 0;
@@ -16,6 +18,7 @@ class ExecutionContext {
16
18
  this.returnValue = null;
17
19
  this.silent = false;
18
20
  this.__functionCache = {};
21
+ this.componentAngleFollowsWire = true;
19
22
  this.name = name;
20
23
  this.namespace = namespace;
21
24
  this.netNamespace = netNamespace;
@@ -145,6 +148,15 @@ class ExecutionContext {
145
148
  component.widthProp = props.width ?? null;
146
149
  component.typeProp = props.type ?? null;
147
150
  component.copyProp = props.copy ?? false;
151
+ let useAngle = null;
152
+ if (props.angle) {
153
+ useAngle = props.angle % 360;
154
+ if (useAngle < 0) {
155
+ useAngle += 360;
156
+ }
157
+ }
158
+ component.angleProp = useAngle ?? 0;
159
+ component.followWireOrientationProp = props.followWireOrientation;
148
160
  const paramsMap = new Map();
149
161
  params.forEach((param) => {
150
162
  component.parameters.set(param.paramName, param.paramValue);
@@ -201,6 +213,7 @@ class ExecutionContext {
201
213
  addComponentExisting(component, pin) {
202
214
  const startPin = pin;
203
215
  const nextPin = component.getNextPinAfter(startPin);
216
+ this.applyComponentAngleFromWire(component, pin);
204
217
  this.toComponent(component, startPin, { addSequence: true });
205
218
  this.log('move to next pin: ' + nextPin);
206
219
  this.atComponent(component, nextPin, {
@@ -236,6 +249,7 @@ class ExecutionContext {
236
249
  .toString());
237
250
  }
238
251
  const linkedNet = this.linkComponentPinNet(this.scope.currentComponent, this.scope.currentPin, component, pinId);
252
+ this.applyComponentAngleFromWire(component, pinId);
239
253
  this.scope.currentComponent = component;
240
254
  this.scope.currentPin = pinId;
241
255
  this.scope.clearActive();
@@ -684,6 +698,59 @@ class ExecutionContext {
684
698
  this.scope.currentComponent.styles[key] = styles[key];
685
699
  }
686
700
  }
701
+ applyComponentAngleFromWire(component, pin) {
702
+ if (this.componentAngleFollowsWire
703
+ && component.followWireOrientationProp
704
+ && component.useWireOrientationAngle
705
+ && this.scope.currentWireId !== -1) {
706
+ const currentWire = this.scope.wires[this.scope.currentWireId];
707
+ const lastSegment = currentWire.path[currentWire.path.length - 1];
708
+ const pinPositions = (0, layout_js_1.CalculatePinPositions)(component);
709
+ if (pinPositions.has(pin)) {
710
+ const connectedPinPos = pinPositions.get(pin);
711
+ let targetAngle = null;
712
+ switch (lastSegment.direction) {
713
+ case types_js_1.Direction.Down:
714
+ targetAngle = 90;
715
+ break;
716
+ case types_js_1.Direction.Up:
717
+ targetAngle = 270;
718
+ break;
719
+ case types_js_1.Direction.Right:
720
+ targetAngle = 0;
721
+ break;
722
+ case types_js_1.Direction.Left:
723
+ targetAngle = 180;
724
+ break;
725
+ default:
726
+ targetAngle = null;
727
+ }
728
+ if (targetAngle === null) {
729
+ return;
730
+ }
731
+ this.log('set component angle from wire, target angle:', targetAngle, ', component angle:', component.angleProp, 'pin angle:', connectedPinPos.angle);
732
+ let useAngle = (targetAngle - connectedPinPos.angle) % 360;
733
+ if (useAngle < 0) {
734
+ useAngle += 360;
735
+ }
736
+ if (useAngle === 90) {
737
+ component.setParam('angle', 90);
738
+ }
739
+ else if (useAngle === 180) {
740
+ if (component.angleProp === 0 || component.angleProp === 180) {
741
+ component.setParam('flipX', 1);
742
+ }
743
+ else if (component.angleProp === 90 || component.angleProp === 270) {
744
+ component.setParam('flipY', 1);
745
+ }
746
+ }
747
+ else if (useAngle === 270) {
748
+ component.setParam('angle', 270);
749
+ }
750
+ component.wireOrientationAngle = useAngle;
751
+ }
752
+ }
753
+ }
687
754
  enterFrame() {
688
755
  const frameId = this.scope.frames.length + 1;
689
756
  const frameObject = new Frame_js_1.Frame(frameId);
@@ -3,16 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.VerticalAlign = exports.HorizontalAlign = exports.Geometry = exports.GeometryProp = exports.Label = void 0;
6
+ exports.VerticalAlign = exports.HorizontalAlign = exports.Geometry = exports.GeometryProp = exports.Label = exports.Textbox = void 0;
7
7
  const core_1 = __importDefault(require("@flatten-js/core"));
8
8
  const sizing_js_1 = require("./sizing.js");
9
9
  const globals_js_1 = require("./globals.js");
10
10
  const ParamDefinition_js_1 = require("./objects/ParamDefinition.js");
11
- class Label extends core_1.default.Polygon {
11
+ class Textbox extends core_1.default.Polygon {
12
12
  get box() {
13
13
  return this.polygon.box;
14
14
  }
15
- constructor(id, text, anchorPoint, polygon, style, bounds) {
15
+ constructor(id, text, anchorPoint, polygon, style, bounds, label) {
16
16
  super(polygon.vertices);
17
17
  this.anchorPoint = [0, 0];
18
18
  this.boundingBox = { width: -1, height: -1 };
@@ -24,8 +24,9 @@ class Label extends core_1.default.Polygon {
24
24
  this.boundingBox = polygon.box;
25
25
  this.polygon = polygon;
26
26
  this.textMeasurementBounds = bounds;
27
+ this.label = label;
27
28
  }
28
- static fromPoint(id, x, y, text, style) {
29
+ static fromPoint(id, x, y, text, style, label) {
29
30
  let useText;
30
31
  if (typeof text === 'number') {
31
32
  useText = text.toString();
@@ -38,7 +39,7 @@ class Label extends core_1.default.Polygon {
38
39
  useText = text;
39
40
  }
40
41
  else {
41
- throw 'Invalid string passed into label';
42
+ throw 'Invalid string passed into textbox';
42
43
  }
43
44
  const { fontSize = 10, anchor = HorizontalAlign.Left, vanchor = VerticalAlign.Bottom, fontWeight = 'regular', } = style ?? {};
44
45
  const { width, height, box } = (0, sizing_js_1.measureTextSize2)(useText, globals_js_1.defaultFont, fontSize, fontWeight, anchor, vanchor);
@@ -50,20 +51,23 @@ class Label extends core_1.default.Polygon {
50
51
  [box.x, box.y],
51
52
  ];
52
53
  const polygon = new core_1.default.Polygon(polygonCoords);
53
- return new Label(id, useText, [x, y], polygon, style, box);
54
+ return new Textbox(id, useText, [x, y], polygon, style, box, label);
54
55
  }
55
56
  rotate(angle, origin) {
56
57
  const feature = super.rotate(angle, origin);
57
- return new Label(this.id, this.text, this.anchorPoint, feature, this.style, this.textMeasurementBounds);
58
+ return new Textbox(this.id, this.text, this.anchorPoint, feature, this.style, this.textMeasurementBounds, this.label);
58
59
  }
59
60
  transform(matrix) {
60
61
  const feature = super.transform(matrix);
61
- return new Label(this.id, this.text, this.anchorPoint, feature, this.style, this.textMeasurementBounds);
62
+ return new Textbox(this.id, this.text, this.anchorPoint, feature, this.style, this.textMeasurementBounds, this.label);
62
63
  }
63
64
  getLabelPosition() {
64
65
  return this.anchorPoint;
65
66
  }
66
67
  }
68
+ exports.Textbox = Textbox;
69
+ class Label extends Textbox {
70
+ }
67
71
  exports.Label = Label;
68
72
  class GeometryProp {
69
73
  constructor(name, value) {
@@ -80,7 +84,10 @@ class Geometry {
80
84
  return new core_1.default.Line(Geometry.point(x1, y1), Geometry.point(x2, y2));
81
85
  }
82
86
  static label(id, x, y, text, style) {
83
- return Label.fromPoint(id, x, y, text, style);
87
+ return Textbox.fromPoint(id, x, y, text, style, true);
88
+ }
89
+ static textbox(id, x, y, text, style) {
90
+ return Textbox.fromPoint(id, x, y, text, style, false);
84
91
  }
85
92
  static segment(start, end) {
86
93
  return new core_1.default.Segment(Geometry.point(start[0], start[1]), Geometry.point(end[0], end[1]));
@@ -131,12 +138,28 @@ class Geometry {
131
138
  let maxX = Number.NEGATIVE_INFINITY;
132
139
  let maxY = Number.NEGATIVE_INFINITY;
133
140
  features.forEach(feature => {
134
- const box = feature.box;
135
- if (feature instanceof Label
141
+ const tmpBox = feature.box;
142
+ let box = {
143
+ xmin: tmpBox.xmin,
144
+ ymin: tmpBox.ymin,
145
+ xmax: tmpBox.xmax,
146
+ ymax: tmpBox.ymax
147
+ };
148
+ if (feature instanceof Textbox
149
+ && feature.label
136
150
  && typeof feature.text === 'string'
137
151
  && feature.text.trim().length === 0) {
138
152
  return;
139
153
  }
154
+ if (feature instanceof Textbox && !feature.label) {
155
+ const [x, y] = feature.anchorPoint;
156
+ box = {
157
+ xmin: box.xmin + x,
158
+ ymin: box.ymin + y,
159
+ xmax: box.xmax + x,
160
+ ymax: box.ymax + y
161
+ };
162
+ }
140
163
  if (box.xmin === undefined) {
141
164
  throw "Invalid box!";
142
165
  }
@@ -152,23 +175,11 @@ class Geometry {
152
175
  height: maxY - minY,
153
176
  };
154
177
  }
155
- static getType(feature) {
156
- if (feature instanceof Label) {
157
- return 'label';
158
- }
159
- else if (feature instanceof core_1.default.Polygon) {
160
- return 'polygon';
161
- }
162
- else if (feature instanceof core_1.default.Segment) {
163
- return 'segment';
164
- }
165
- console.log('unknown type', feature);
166
- }
167
- static featuresToPath(items) {
178
+ static featuresToPath(items, flipX, flipY) {
168
179
  const paths = [];
169
180
  let isClosedPolygon = false;
170
181
  items.forEach(item => {
171
- if (item instanceof Label) {
182
+ if (item instanceof Textbox) {
172
183
  return;
173
184
  }
174
185
  const path = [];
@@ -185,7 +196,15 @@ class Geometry {
185
196
  }
186
197
  const startPoint = getArcPointRadians(x, y, radius, item.startAngle);
187
198
  const endPoint = getArcPointRadians(x, y, radius, useEndAngle);
188
- paths.push('M', startPoint[0], startPoint[1], 'A', radius, radius, 0, 1, 1, endPoint[0], endPoint[1], extraEnd);
199
+ let largeArcSweepFlag = 0;
200
+ if (useEndAngle - item.startAngle > Math.PI) {
201
+ largeArcSweepFlag = 1;
202
+ }
203
+ let sweepFlag = 1;
204
+ if (flipX === 1 && flipY === 0) {
205
+ sweepFlag = 0;
206
+ }
207
+ paths.push('M', startPoint[0], startPoint[1], 'A', radius, radius, 0, largeArcSweepFlag, sweepFlag, endPoint[0], endPoint[1], extraEnd);
189
208
  }
190
209
  else {
191
210
  const coords = Geometry.getCoords(item);
@@ -226,6 +226,7 @@ function renderScript(scriptData, outputPath, options) {
226
226
  showStats && console.log('Render took:', generateSvgTimer.lap());
227
227
  if (outputPath) {
228
228
  (0, fs_1.writeFileSync)(outputPath, svgOutput);
229
+ console.log('Generated file', outputPath);
229
230
  }
230
231
  }
231
232
  catch (err) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RenderJunction = exports.RenderFrameType = exports.RenderFrame = exports.RenderText = exports.RenderComponent = exports.RenderWire = exports.RenderObject = exports.getBounds = exports.LayoutEngine = void 0;
3
+ exports.CalculatePinPositions = exports.RenderJunction = exports.RenderFrameType = exports.RenderFrame = exports.RenderText = exports.RenderComponent = exports.RenderWire = exports.RenderObject = exports.getBounds = exports.LayoutEngine = void 0;
4
4
  const graphlib_1 = require("@dagrejs/graphlib");
5
5
  const draw_symbols_js_1 = require("./draw_symbols.js");
6
6
  const ExecutionScope_js_1 = require("./objects/ExecutionScope.js");
@@ -10,6 +10,7 @@ const geometry_js_1 = require("./geometry.js");
10
10
  const logger_js_1 = require("./logger.js");
11
11
  const Frame_js_1 = require("./objects/Frame.js");
12
12
  const utils_js_1 = require("./utils.js");
13
+ const types_js_1 = require("./objects/types.js");
13
14
  class LayoutEngine {
14
15
  constructor() {
15
16
  this.placeSubgraphVersion = 2;
@@ -938,16 +939,16 @@ function applyComponentParamsToSymbol(typeProp, component, symbol) {
938
939
  function calculateSymbolAngle(symbol, pin, direction) {
939
940
  let directionVector = 0;
940
941
  switch (direction) {
941
- case 'right':
942
+ case types_js_1.Direction.Right:
942
943
  directionVector = 0;
943
944
  break;
944
- case 'down':
945
+ case types_js_1.Direction.Down:
945
946
  directionVector = 90;
946
947
  break;
947
- case 'left':
948
+ case types_js_1.Direction.Left:
948
949
  directionVector = 180;
949
950
  break;
950
- case 'up':
951
+ case types_js_1.Direction.Up:
951
952
  directionVector = 270;
952
953
  break;
953
954
  }
@@ -1017,16 +1018,16 @@ class RenderWire extends RenderObject {
1017
1018
  this.segments.forEach(segment => {
1018
1019
  const { direction, value } = segment;
1019
1020
  let didAddPoint = false;
1020
- if (direction === 'down') {
1021
+ if (direction === types_js_1.Direction.Down) {
1021
1022
  tmpY += value;
1022
1023
  }
1023
- else if (direction === 'up') {
1024
+ else if (direction === types_js_1.Direction.Up) {
1024
1025
  tmpY -= value;
1025
1026
  }
1026
- else if (direction === 'left') {
1027
+ else if (direction === types_js_1.Direction.Left) {
1027
1028
  tmpX -= value;
1028
1029
  }
1029
- else if (direction === 'right') {
1030
+ else if (direction === types_js_1.Direction.Right) {
1030
1031
  tmpX += value;
1031
1032
  }
1032
1033
  else if (direction === 'auto' || direction === "auto_") {
@@ -1095,16 +1096,16 @@ class RenderWire extends RenderObject {
1095
1096
  let tmpY = this.y;
1096
1097
  excludeLastSegment.forEach(segment => {
1097
1098
  const { direction, value } = segment;
1098
- if (direction === 'down') {
1099
+ if (direction === types_js_1.Direction.Down) {
1099
1100
  tmpY += value;
1100
1101
  }
1101
- else if (direction === 'up') {
1102
+ else if (direction === types_js_1.Direction.Up) {
1102
1103
  tmpY -= value;
1103
1104
  }
1104
- else if (direction === 'left') {
1105
+ else if (direction === types_js_1.Direction.Left) {
1105
1106
  tmpX -= value;
1106
1107
  }
1107
- else if (direction === 'right') {
1108
+ else if (direction === types_js_1.Direction.Right) {
1108
1109
  tmpX += value;
1109
1110
  }
1110
1111
  });
@@ -1112,16 +1113,16 @@ class RenderWire extends RenderObject {
1112
1113
  let valueXY = null;
1113
1114
  const lastSegment = this.segments[this.segments.length - 1];
1114
1115
  switch (lastSegment.direction) {
1115
- case 'left':
1116
+ case types_js_1.Direction.Left:
1116
1117
  useValue = tmpX - untilX;
1117
1118
  break;
1118
- case 'right':
1119
+ case types_js_1.Direction.Right:
1119
1120
  useValue = untilX - tmpX;
1120
1121
  break;
1121
- case 'up':
1122
+ case types_js_1.Direction.Up:
1122
1123
  useValue = untilY - tmpY;
1123
1124
  break;
1124
- case 'down':
1125
+ case types_js_1.Direction.Down:
1125
1126
  useValue = tmpY - untilY;
1126
1127
  break;
1127
1128
  case 'auto':
@@ -1225,6 +1226,25 @@ class RenderJunction {
1225
1226
  }
1226
1227
  }
1227
1228
  exports.RenderJunction = RenderJunction;
1229
+ function CalculatePinPositions(component) {
1230
+ const pinPositionMapping = new Map();
1231
+ let tmpSymbol;
1232
+ if (component.displayProp !== null
1233
+ && component.displayProp instanceof draw_symbols_js_1.SymbolDrawing) {
1234
+ tmpSymbol = new draw_symbols_js_1.SymbolPlaceholder(component.displayProp);
1235
+ }
1236
+ else {
1237
+ const symbolPinDefinitions = generateLayoutPinDefinition(component);
1238
+ tmpSymbol = new draw_symbols_js_1.SymbolCustom(symbolPinDefinitions);
1239
+ }
1240
+ tmpSymbol.refreshDrawing();
1241
+ const pins = component.pins;
1242
+ pins.forEach((value, key) => {
1243
+ pinPositionMapping.set(key, tmpSymbol.pinPosition(key));
1244
+ });
1245
+ return pinPositionMapping;
1246
+ }
1247
+ exports.CalculatePinPositions = CalculatePinPositions;
1228
1248
  function isPointOverlap(x, y, other) {
1229
1249
  return (x >= other.x && y >= other.y && x <= (other.x + other.width) && y <= (other.y + other.height));
1230
1250
  }
@@ -17,6 +17,10 @@ class ClassComponent {
17
17
  this.widthProp = null;
18
18
  this.typeProp = null;
19
19
  this.copyProp = false;
20
+ this.angleProp = 0;
21
+ this.followWireOrientationProp = true;
22
+ this.wireOrientationAngle = 0;
23
+ this.useWireOrientationAngle = true;
20
24
  this.styles = {};
21
25
  this.assignedRefDes = null;
22
26
  this.instanceName = instanceName;
@@ -118,6 +122,9 @@ class ClassComponent {
118
122
  component.arrangeProps = this.arrangeProps;
119
123
  component.widthProp = this.widthProp;
120
124
  component.typeProp = this.typeProp;
125
+ component.angleProp = this.angleProp;
126
+ component.followWireOrientationProp = this.followWireOrientationProp;
127
+ component.useWireOrientationAngle = this.useWireOrientationAngle;
121
128
  if (this.displayProp) {
122
129
  if (typeof this.displayProp === "string") {
123
130
  component.displayProp = this.displayProp;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ParseSymbolType = exports.UndeclaredReference = void 0;
3
+ exports.Direction = exports.ParseSymbolType = exports.UndeclaredReference = void 0;
4
4
  class UndeclaredReference {
5
5
  constructor(reference) {
6
6
  this.reference = reference;
@@ -13,3 +13,10 @@ var ParseSymbolType;
13
13
  ParseSymbolType["Function"] = "function";
14
14
  ParseSymbolType["Undefined"] = "undefined";
15
15
  })(ParseSymbolType || (exports.ParseSymbolType = ParseSymbolType = {}));
16
+ var Direction;
17
+ (function (Direction) {
18
+ Direction["Left"] = "left";
19
+ Direction["Right"] = "right";
20
+ Direction["Down"] = "down";
21
+ Direction["Up"] = "up";
22
+ })(Direction || (exports.Direction = Direction = {}));
@@ -35,7 +35,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
35
35
  const ctxDataWithAssignmentExpr = ctx.data_expr_with_assignment();
36
36
  this.visit(ctxDataWithAssignmentExpr);
37
37
  const [component, pinValue] = this.getResult(ctxDataWithAssignmentExpr);
38
- return this.getExecutor().addComponentExisting(component, pinValue);
38
+ this.getExecutor().addComponentExisting(component, pinValue);
39
39
  };
40
40
  this.visitAt_component_expr = (ctx) => {
41
41
  if (ctx.Point()) {
@@ -142,12 +142,13 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
142
142
  properties.get('copy') : false;
143
143
  const width = properties.has('width') ?
144
144
  properties.get('width') : null;
145
+ const angle = properties.has('angle') ?
146
+ properties.get('angle') : null;
147
+ const followWireOrientation = properties.has('followWireOrientation') ?
148
+ properties.get('followWireOrientation') : true;
145
149
  const props = {
146
- arrange,
147
- display,
148
- type,
149
- width,
150
- copy
150
+ arrange, display, type, width, copy,
151
+ angle, followWireOrientation
151
152
  };
152
153
  this.setResult(ctx, this.getExecutor().createComponent(instanceName, pins, params, props));
153
154
  };
@@ -181,9 +182,20 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
181
182
  else {
182
183
  throw "Invalid command!";
183
184
  }
184
- const ctxParameters = ctx.parameters();
185
- this.visit(ctxParameters);
186
- const parameters = this.getResult(ctxParameters);
185
+ let parameters = [];
186
+ const ctxNestedProperties = ctx.nested_properties_inner();
187
+ if (ctxNestedProperties) {
188
+ this.visit(ctxNestedProperties);
189
+ const nestedKeyValues = this.getResult(ctxNestedProperties);
190
+ nestedKeyValues.forEach((value, key) => {
191
+ parameters.push(['keyword', key, value]);
192
+ });
193
+ }
194
+ else {
195
+ const ctxParameters = ctx.parameters();
196
+ this.visit(ctxParameters);
197
+ parameters = this.getResult(ctxParameters);
198
+ }
187
199
  this.setResult(ctx, [commandName, parameters]);
188
200
  };
189
201
  this.visitProperty_expr = (ctx) => {
@@ -212,7 +224,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
212
224
  }
213
225
  this.setResult(ctx, value);
214
226
  };
215
- this.visitNested_properties = (ctx) => {
227
+ this.visitNested_properties_inner = (ctx) => {
216
228
  const result = new Map();
217
229
  ctx.property_expr().forEach((item) => {
218
230
  this.visit(item);
@@ -223,6 +235,11 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
223
235
  });
224
236
  this.setResult(ctx, result);
225
237
  };
238
+ this.visitNested_properties = (ctx) => {
239
+ const ctxNested = ctx.nested_properties_inner();
240
+ this.visit(ctxNested);
241
+ this.setResult(ctx, this.getResult(ctxNested));
242
+ };
226
243
  this.visitProperty_key_expr = (ctx) => {
227
244
  const ctxID = ctx.ID();
228
245
  const ctxIntegerValue = ctx.INTEGER_VALUE();
@@ -272,18 +289,40 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
272
289
  else if (ctxID2) {
273
290
  result = ctxID2.getText();
274
291
  }
292
+ let shouldIgnoreWireOrientation = false;
275
293
  if (modifierText === 'flip') {
276
294
  const flipValue = result;
277
295
  if (flipValue.indexOf('x') !== -1) {
278
296
  component.setParam('flipX', 1);
297
+ shouldIgnoreWireOrientation = true;
279
298
  }
280
299
  if (flipValue.indexOf('y') !== -1) {
281
300
  component.setParam('flipY', 1);
301
+ shouldIgnoreWireOrientation = true;
282
302
  }
283
303
  }
284
304
  else if (modifierText === 'angle') {
285
305
  const angleValue = Number(result);
286
306
  component.setParam('angle', angleValue);
307
+ shouldIgnoreWireOrientation = true;
308
+ }
309
+ else if (modifierText === 'anchor') {
310
+ if (component.displayProp
311
+ && component.displayProp instanceof draw_symbols_js_1.SymbolDrawingCommands) {
312
+ const commands = (component.displayProp)
313
+ .getCommands();
314
+ commands.forEach(command => {
315
+ const positionParams = command[1];
316
+ const keywordParams = command[2];
317
+ if (command[0] === draw_symbols_js_1.PlaceHolderCommands.label
318
+ && positionParams[0] === 'value') {
319
+ keywordParams.set('anchor', result);
320
+ }
321
+ });
322
+ }
323
+ }
324
+ if (shouldIgnoreWireOrientation) {
325
+ component.useWireOrientationAngle = false;
287
326
  }
288
327
  });
289
328
  }