@metadev/daga 3.1.4 → 4.0.0

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/index.cjs.js CHANGED
@@ -828,6 +828,64 @@ const numberOfRows = s => {
828
828
  return ((_a = s.match(/\n/g)) === null || _a === undefined ? undefined : _a.length) || 0;
829
829
  };
830
830
 
831
+ /******************************************************************************
832
+ Copyright (c) Microsoft Corporation.
833
+
834
+ Permission to use, copy, modify, and/or distribute this software for any
835
+ purpose with or without fee is hereby granted.
836
+
837
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
838
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
839
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
840
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
841
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
842
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
843
+ PERFORMANCE OF THIS SOFTWARE.
844
+ ***************************************************************************** */
845
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
846
+
847
+
848
+ function __rest(s, e) {
849
+ var t = {};
850
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
851
+ t[p] = s[p];
852
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
853
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
854
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
855
+ t[p[i]] = s[p[i]];
856
+ }
857
+ return t;
858
+ }
859
+
860
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
861
+ var e = new Error(message);
862
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
863
+ };
864
+
865
+ /**
866
+ * Converts a configuration for a look into an easier to consult object of fully qualified looks for each case.
867
+ *
868
+ * @param lookConfig A look configuration object
869
+ * @returns An object with four keys for a look with each possible state of being selected or not and being highlighted or not.
870
+ */
871
+ const extractLooksFromConfig = lookConfig => {
872
+ const {
873
+ selected,
874
+ highlighted
875
+ } = lookConfig,
876
+ rest = __rest(lookConfig, ["selected", "highlighted"]);
877
+ const defaultLook = rest;
878
+ const selectedLook = Object.assign(Object.assign({}, defaultLook), selected);
879
+ const highlightedLook = Object.assign(Object.assign({}, defaultLook), highlighted);
880
+ const selectedAndHighlightedLook = Object.assign(Object.assign(Object.assign({}, defaultLook), highlighted), selected);
881
+ return {
882
+ defaultLook,
883
+ selectedLook,
884
+ highlightedLook,
885
+ selectedAndHighlightedLook
886
+ };
887
+ };
888
+
831
889
  /**
832
890
  * Represents a collection of diagram entities of a type that exists as part of a diagram model.
833
891
  * @public
@@ -976,6 +1034,10 @@ const DEFAULT_PRIORITY = 0;
976
1034
  * @see DiagramCanvas
977
1035
  */
978
1036
  class DiagramElement {
1037
+ /**
1038
+ * Identifier that uniquely identifies this element within its diagram model. Cannot be an empty string.
1039
+ * @public
1040
+ */
979
1041
  get id() {
980
1042
  return this._id;
981
1043
  }
@@ -1244,7 +1306,6 @@ class ValueSet {
1244
1306
  constructor(propertySet, rootElement) {
1245
1307
  this.displayedProperties = [];
1246
1308
  this.hiddenProperties = [];
1247
- // TODO JC: make this private after reviewing how it's used from React
1248
1309
  this.values = {};
1249
1310
  this.valueSets = {};
1250
1311
  /**
@@ -1529,7 +1590,7 @@ class ValueSet {
1529
1590
  this.values[key] = structuredClone(property.defaultValue);
1530
1591
  }
1531
1592
  if (rootAttribute !== undefined && rootAttribute !== null) {
1532
- if (property.defaultValue !== undefined) {
1593
+ if (property.defaultValue !== undefined && !equals(this.values[key], property.defaultValue)) {
1533
1594
  this.setRootElementValue(rootAttribute, this.values[key]);
1534
1595
  } else {
1535
1596
  this.values[key] = this.getRootElementValue(rootAttribute);
@@ -1647,6 +1708,34 @@ const diff = (a, b) => {
1647
1708
  }
1648
1709
  return [aDiff, bDiff];
1649
1710
  };
1711
+ /**
1712
+ * Calculates the differences between the two given values of a valueset and returns two objects containing the differences in each relative to the other.
1713
+ *
1714
+ * @param a An object.
1715
+ * @param b An object.
1716
+ * @param valueSet A ValueSet to use as reference for the keys and types of each property.
1717
+ * @returns A tuple of two objects with each containing the keys that have a different value in the corresponding argument compared to the other argument.
1718
+ */
1719
+ const diffProperties = (a, b, valueSet) => {
1720
+ const aDiff = {};
1721
+ const bDiff = {};
1722
+ for (const key in valueSet.propertySet.propertyMap) {
1723
+ if (valueSet.propertySet.propertyMap[key].type === exports.Type.Object) {
1724
+ const diffAB = diffProperties(a[key], b[key], valueSet.getSubValueSet(key));
1725
+ // only add the key if differences are detected
1726
+ if (Object.keys(diffAB[0]).length > 0 && Object.keys(diffAB[1]).length > 0) {
1727
+ aDiff[key] = diffAB[0];
1728
+ bDiff[key] = diffAB[1];
1729
+ }
1730
+ } else {
1731
+ if (!equals(a[key], b[key])) {
1732
+ aDiff[key] = a[key];
1733
+ bDiff[key] = b[key];
1734
+ }
1735
+ }
1736
+ }
1737
+ return [aDiff, bDiff];
1738
+ };
1650
1739
  /**
1651
1740
  * Checks if the given value is an object.
1652
1741
  * @public
@@ -1662,16 +1751,24 @@ const isObject = x => x !== undefined && x !== null && x.constructor === Object;
1662
1751
  */
1663
1752
  const DIAGRAM_CONNECTION_TYPE_DEFAULTS = {
1664
1753
  name: '',
1665
- width: 1,
1666
- shape: exports.LineShape.Straight,
1667
- style: exports.LineStyle.Solid,
1668
1754
  label: null,
1669
- defaultStartMarkerLook: null,
1670
- defaultEndMarkerLook: null,
1755
+ look: {
1756
+ lookType: 'connection-look',
1757
+ color: '#000000',
1758
+ thickness: 1,
1759
+ shape: exports.LineShape.Straight,
1760
+ style: exports.LineStyle.Solid,
1761
+ selected: {
1762
+ color: '#AA00AA'
1763
+ },
1764
+ highlighted: {
1765
+ thickness: 2
1766
+ }
1767
+ },
1768
+ startMarkerLook: undefined,
1769
+ endMarkerLook: undefined,
1671
1770
  startTypes: [],
1672
1771
  endTypes: [],
1673
- color: '#000000',
1674
- selectedColor: '#000000',
1675
1772
  properties: []
1676
1773
  };
1677
1774
  /**
@@ -1684,16 +1781,38 @@ class DiagramConnectionType {
1684
1781
  const values = Object.assign(Object.assign({}, DIAGRAM_CONNECTION_TYPE_DEFAULTS), options);
1685
1782
  this.id = values.id;
1686
1783
  this.name = values.name;
1687
- this.width = values.width;
1688
- this.shape = values.shape;
1689
- this.style = values.style;
1690
1784
  this.label = values.label;
1691
- this.defaultStartMarkerLook = values.defaultStartMarkerLook;
1692
- this.defaultEndMarkerLook = values.defaultEndMarkerLook;
1785
+ const looks = extractLooksFromConfig(values.look);
1786
+ this.defaultLook = looks.defaultLook;
1787
+ this.selectedLook = looks.selectedLook;
1788
+ this.highlightedLook = looks.highlightedLook;
1789
+ this.selectedAndHighlightedLook = looks.selectedAndHighlightedLook;
1790
+ if (values.startMarkerLook !== undefined) {
1791
+ const startMarkerLooks = extractLooksFromConfig(values.startMarkerLook);
1792
+ this.defaultStartMarkerLook = startMarkerLooks.defaultLook;
1793
+ this.selectedStartMarkerLook = startMarkerLooks.selectedLook;
1794
+ this.highlightedStartMarkerLook = startMarkerLooks.highlightedLook;
1795
+ this.selectedAndHighlightedStartMarkerLook = startMarkerLooks.selectedAndHighlightedLook;
1796
+ } else {
1797
+ this.defaultStartMarkerLook = null;
1798
+ this.selectedStartMarkerLook = null;
1799
+ this.highlightedStartMarkerLook = null;
1800
+ this.selectedAndHighlightedStartMarkerLook = null;
1801
+ }
1802
+ if (values.endMarkerLook !== undefined) {
1803
+ const endMarkerLooks = extractLooksFromConfig(values.endMarkerLook);
1804
+ this.defaultEndMarkerLook = endMarkerLooks.defaultLook;
1805
+ this.selectedEndMarkerLook = endMarkerLooks.selectedLook;
1806
+ this.highlightedEndMarkerLook = endMarkerLooks.highlightedLook;
1807
+ this.selectedAndHighlightedEndMarkerLook = endMarkerLooks.selectedAndHighlightedLook;
1808
+ } else {
1809
+ this.defaultEndMarkerLook = null;
1810
+ this.selectedEndMarkerLook = null;
1811
+ this.highlightedEndMarkerLook = null;
1812
+ this.selectedAndHighlightedEndMarkerLook = null;
1813
+ }
1693
1814
  this.startTypes = values.startTypes;
1694
1815
  this.endTypes = values.endTypes;
1695
- this.color = values.color;
1696
- this.selectedColor = values.selectedColor;
1697
1816
  this.propertySet = new PropertySet(values.properties);
1698
1817
  }
1699
1818
  canStartFromType(type) {
@@ -1709,6 +1828,27 @@ class DiagramConnectionType {
1709
1828
  * @see DiagramPort
1710
1829
  */
1711
1830
  class DiagramConnection extends DiagramElement {
1831
+ get type() {
1832
+ return this._type;
1833
+ }
1834
+ set type(type) {
1835
+ var _a, _b;
1836
+ (_b = (_a = this.model.canvas) === null || _a === undefined ? undefined : _a.userSelection) === null || _b === undefined ? undefined : _b.openInPropertyEditor(undefined);
1837
+ this._type = type;
1838
+ if (this.valueSet) {
1839
+ this.valueSet = new ValueSet(type.propertySet, this);
1840
+ }
1841
+ this.updateInView();
1842
+ }
1843
+ get typeString() {
1844
+ return this.type.id;
1845
+ }
1846
+ set typeString(typeString) {
1847
+ const type = this.model.connections.types.get(typeString);
1848
+ if (type) {
1849
+ this.type = type;
1850
+ }
1851
+ }
1712
1852
  /**
1713
1853
  * Name of this connection. Alias for this connection's middle label.
1714
1854
  * @public
@@ -1719,10 +1859,127 @@ class DiagramConnection extends DiagramElement {
1719
1859
  set name(name) {
1720
1860
  this.middleLabel = name;
1721
1861
  }
1862
+ /**
1863
+ * Current look of the connection.
1864
+ * @private
1865
+ */
1866
+ get look() {
1867
+ if (this.selected) {
1868
+ if (this.highlighted) {
1869
+ return this._selectedAndHighlightedLook !== undefined ? this._selectedAndHighlightedLook : this.type.selectedAndHighlightedLook;
1870
+ } else {
1871
+ return this._selectedLook !== undefined ? this._selectedLook : this.type.selectedLook;
1872
+ }
1873
+ } else {
1874
+ if (this.highlighted) {
1875
+ return this._highlightedLook !== undefined ? this._highlightedLook : this.type.highlightedLook;
1876
+ } else {
1877
+ return this._defaultLook !== undefined ? this._defaultLook : this.type.defaultLook;
1878
+ }
1879
+ }
1880
+ }
1881
+ /**
1882
+ * Sets the look configuration of the connection to override the one determined by the type.
1883
+ * `undefined` resets it to the one determined by the type.
1884
+ * @private
1885
+ */
1886
+ set look(look) {
1887
+ if (look) {
1888
+ const looks = extractLooksFromConfig(look);
1889
+ this._defaultLook = Object.assign(Object.assign({}, this._defaultLook), looks.defaultLook);
1890
+ this._selectedLook = Object.assign(Object.assign({}, this._selectedLook), looks.selectedLook);
1891
+ this._highlightedLook = Object.assign(Object.assign({}, this._highlightedLook), looks.highlightedLook);
1892
+ this._selectedAndHighlightedLook = Object.assign(Object.assign({}, this._selectedAndHighlightedLook), looks.selectedAndHighlightedLook);
1893
+ } else {
1894
+ this._defaultLook = look;
1895
+ this._selectedLook = look;
1896
+ this._highlightedLook = look;
1897
+ this._selectedAndHighlightedLook = look;
1898
+ }
1899
+ }
1900
+ /**
1901
+ * Current look of the start marker.
1902
+ * @private
1903
+ */
1904
+ get startMarkerLook() {
1905
+ if (this.selected) {
1906
+ if (this.highlighted) {
1907
+ return this._selectedAndHighlightedStartMarkerLook !== undefined ? this._selectedAndHighlightedStartMarkerLook : this.type.selectedAndHighlightedStartMarkerLook;
1908
+ } else {
1909
+ return this._selectedStartMarkerLook !== undefined ? this._selectedStartMarkerLook : this.type.selectedStartMarkerLook;
1910
+ }
1911
+ } else {
1912
+ if (this.highlighted) {
1913
+ return this._highlightedStartMarkerLook !== undefined ? this._highlightedStartMarkerLook : this.type.highlightedStartMarkerLook;
1914
+ } else {
1915
+ return this._defaultStartMarkerLook !== undefined ? this._defaultStartMarkerLook : this.type.defaultStartMarkerLook;
1916
+ }
1917
+ }
1918
+ }
1919
+ /**
1920
+ * Sets the look configuration of the start marker to override the one determined by the type.
1921
+ * `null` stands for no marker and `undefined` resets it to the one determined by the type.
1922
+ * @private
1923
+ */
1924
+ set startMarkerLook(startMarkerLook) {
1925
+ if (startMarkerLook) {
1926
+ const looks = extractLooksFromConfig(startMarkerLook);
1927
+ this._defaultStartMarkerLook = Object.assign(Object.assign({}, this._defaultStartMarkerLook), looks.defaultLook);
1928
+ this._selectedStartMarkerLook = Object.assign(Object.assign({}, this._selectedStartMarkerLook), looks.selectedLook);
1929
+ this._highlightedStartMarkerLook = Object.assign(Object.assign({}, this._highlightedStartMarkerLook), looks.highlightedLook);
1930
+ this._selectedAndHighlightedStartMarkerLook = Object.assign(Object.assign({}, this._selectedAndHighlightedStartMarkerLook), looks.selectedAndHighlightedLook);
1931
+ } else {
1932
+ this._defaultStartMarkerLook = startMarkerLook;
1933
+ this._selectedStartMarkerLook = startMarkerLook;
1934
+ this._highlightedStartMarkerLook = startMarkerLook;
1935
+ this._selectedAndHighlightedStartMarkerLook = startMarkerLook;
1936
+ }
1937
+ }
1938
+ /**
1939
+ * Current look of the end marker.
1940
+ * @private
1941
+ */
1942
+ get endMarkerLook() {
1943
+ if (this.selected) {
1944
+ if (this.highlighted) {
1945
+ return this._selectedAndHighlightedEndMarkerLook !== undefined ? this._selectedAndHighlightedEndMarkerLook : this.type.selectedAndHighlightedEndMarkerLook;
1946
+ } else {
1947
+ return this._selectedEndMarkerLook !== undefined ? this._selectedEndMarkerLook : this.type.selectedEndMarkerLook;
1948
+ }
1949
+ } else {
1950
+ if (this.highlighted) {
1951
+ return this._highlightedEndMarkerLook !== undefined ? this._highlightedEndMarkerLook : this.type.highlightedEndMarkerLook;
1952
+ } else {
1953
+ return this._defaultEndMarkerLook !== undefined ? this._defaultEndMarkerLook : this.type.defaultEndMarkerLook;
1954
+ }
1955
+ }
1956
+ }
1957
+ /**
1958
+ * Sets the look configuration of the end marker to override the one determined by the type.
1959
+ * `null` stands for no marker and `undefined` resets it to the one determined by the type.
1960
+ * @private
1961
+ */
1962
+ set endMarkerLook(endMarkerLook) {
1963
+ if (endMarkerLook) {
1964
+ const looks = extractLooksFromConfig(endMarkerLook);
1965
+ this._defaultEndMarkerLook = Object.assign(Object.assign({}, this._defaultEndMarkerLook), looks.defaultLook);
1966
+ this._selectedEndMarkerLook = Object.assign(Object.assign({}, this._selectedEndMarkerLook), looks.selectedLook);
1967
+ this._highlightedEndMarkerLook = Object.assign(Object.assign({}, this._highlightedEndMarkerLook), looks.highlightedLook);
1968
+ this._selectedAndHighlightedEndMarkerLook = Object.assign(Object.assign({}, this._selectedAndHighlightedEndMarkerLook), looks.selectedAndHighlightedLook);
1969
+ } else {
1970
+ this._defaultEndMarkerLook = endMarkerLook;
1971
+ this._selectedEndMarkerLook = endMarkerLook;
1972
+ this._highlightedEndMarkerLook = endMarkerLook;
1973
+ this._selectedAndHighlightedEndMarkerLook = endMarkerLook;
1974
+ }
1975
+ }
1722
1976
  constructor(model, type, start, end, id) {
1723
1977
  if (model.connections.get(id) !== undefined) {
1724
1978
  throw new Error(`DiagramConnection with id "${id}" already exists`);
1725
1979
  }
1980
+ if (!id) {
1981
+ throw new Error(`DiagramConnection cannot have an empty or null id`);
1982
+ }
1726
1983
  super(model, id);
1727
1984
  /**
1728
1985
  * Coordinates of the start point of this connection.
@@ -1754,11 +2011,9 @@ class DiagramConnection extends DiagramElement {
1754
2011
  * @public
1755
2012
  */
1756
2013
  this.points = [];
1757
- this.type = type;
2014
+ this._type = type;
1758
2015
  this.valueSet = new ValueSet(type.propertySet, this);
1759
2016
  this.originalData = {};
1760
- this.startMarkerLook = type.defaultStartMarkerLook;
1761
- this.endMarkerLook = type.defaultEndMarkerLook;
1762
2017
  this.setStart(start);
1763
2018
  this.setEnd(end);
1764
2019
  }
@@ -1788,11 +2043,11 @@ class DiagramConnection extends DiagramElement {
1788
2043
  if (start !== undefined) {
1789
2044
  start.outgoingConnections.push(this);
1790
2045
  this.startDirection = start === null || start === undefined ? undefined : start.direction;
1791
- this.startCoords = (start === null || start === undefined ? undefined : start.coords) || [0, 0];
2046
+ this.startCoords = (start === null || start === undefined ? undefined : start.connectionPoint) || [0, 0];
1792
2047
  }
1793
2048
  } else {
1794
2049
  this.startDirection = start === null || start === undefined ? undefined : start.direction;
1795
- this.startCoords = (start === null || start === undefined ? undefined : start.coords) || [0, 0];
2050
+ this.startCoords = (start === null || start === undefined ? undefined : start.connectionPoint) || [0, 0];
1796
2051
  }
1797
2052
  this.updateInView();
1798
2053
  }
@@ -1811,11 +2066,11 @@ class DiagramConnection extends DiagramElement {
1811
2066
  if (end !== undefined) {
1812
2067
  end.incomingConnections.push(this);
1813
2068
  this.endDirection = end === null || end === undefined ? undefined : end.direction;
1814
- this.endCoords = (end === null || end === undefined ? undefined : end.coords) || [0, 0];
2069
+ this.endCoords = (end === null || end === undefined ? undefined : end.connectionPoint) || [0, 0];
1815
2070
  }
1816
2071
  } else {
1817
2072
  this.endDirection = end === null || end === undefined ? undefined : end.direction;
1818
- this.endCoords = (end === null || end === undefined ? undefined : end.coords) || [0, 0];
2073
+ this.endCoords = (end === null || end === undefined ? undefined : end.connectionPoint) || [0, 0];
1819
2074
  }
1820
2075
  this.updateInView();
1821
2076
  }
@@ -1833,6 +2088,10 @@ class DiagramConnection extends DiagramElement {
1833
2088
  // alternative start port not valid, it is the same as the end port
1834
2089
  continue checkAlternativeStartPorts;
1835
2090
  }
2091
+ if (!alternativeStartPort.allowsOutgoing) {
2092
+ // alternative start port not valid, it doesn't allow outgoing connections
2093
+ continue checkAlternativeStartPorts;
2094
+ }
1836
2095
  {
1837
2096
  for (const connection of alternativeStartPort.outgoingConnections) {
1838
2097
  if (connection !== this && connection.end === this.end) {
@@ -1860,24 +2119,28 @@ class DiagramConnection extends DiagramElement {
1860
2119
  const alternativeEndPortsSortedByDistanceAscending = this.end.rootElement.ports.map(p => [p, p.distanceTo(this.start.coords)]).sort((a, b) => a[1] - b[1]).map(a => a[0]);
1861
2120
  checkAlternativeEndPorts: for (const alternativeEndPort of alternativeEndPortsSortedByDistanceAscending) {
1862
2121
  if (alternativeEndPort === this.start) {
1863
- // alternative start port not valid, it is the same as the end port
2122
+ // alternative end port not valid, it is the same as the end port
2123
+ continue checkAlternativeEndPorts;
2124
+ }
2125
+ if (!alternativeEndPort.allowsIncoming) {
2126
+ // alternative end port not valid, it doesn't allow incoming connections
1864
2127
  continue checkAlternativeEndPorts;
1865
2128
  }
1866
2129
  {
1867
2130
  for (const connection of alternativeEndPort.incomingConnections) {
1868
2131
  if (connection !== this && connection.start === this.start) {
1869
- // alternative start port not valid, there is a connection whose start and end matches the alternative end port and this connection's start
2132
+ // alternative end port not valid, there is a connection whose start and end matches the alternative end port and this connection's start
1870
2133
  continue checkAlternativeEndPorts;
1871
2134
  }
1872
2135
  }
1873
2136
  for (const connection of alternativeEndPort.outgoingConnections) {
1874
2137
  if (connection !== this && connection.end === this.start) {
1875
- // alternative start port not valid, there is a connection whose start and end matches the alternative end port and this connection's start
2138
+ // alternative end port not valid, there is a connection whose start and end matches the alternative end port and this connection's start
1876
2139
  continue checkAlternativeEndPorts;
1877
2140
  }
1878
2141
  }
1879
2142
  }
1880
- // found a valid start port
2143
+ // found a valid end port
1881
2144
  if (alternativeEndPort === this.end) {
1882
2145
  break checkAlternativeEndPorts;
1883
2146
  } else {
@@ -1923,7 +2186,7 @@ class DiagramConnectionSet extends DiagramElementSet {
1923
2186
  * @param type The type of the connection given as either the type itself or the id of the type.
1924
2187
  * @param start The start port of the connection.
1925
2188
  * @param end The end port of the connection.
1926
- * @param id The id of the connection.
2189
+ * @param id The id of the connection. Cannot be an empty string.
1927
2190
  * @returns The instanced connection.
1928
2191
  */
1929
2192
  new(type, start, end, id) {
@@ -2249,30 +2512,6 @@ const getTopPadding$1 = config => {
2249
2512
  }
2250
2513
  };
2251
2514
 
2252
- /**
2253
- * Default values of the look of a diagram section.
2254
- * @private
2255
- * @see DIAGRAM_SECTION_DEFAULTS
2256
- */
2257
- const DIAGRAM_SECTION_LOOK_DEFAULTS = {
2258
- lookType: 'shaped-look',
2259
- shape: exports.ClosedShape.Rectangle,
2260
- fillColor: '#FFFFFF',
2261
- borderColor: '#000000',
2262
- selectedFillColor: '#FFFFFF',
2263
- selectedBorderColor: '#000000'
2264
- };
2265
- /**
2266
- * Default values of the parameters of a diagram section.
2267
- * @private
2268
- * @see DiagramSection
2269
- */
2270
- const DIAGRAM_SECTION_DEFAULTS = {
2271
- label: null,
2272
- ports: [],
2273
- look: DIAGRAM_SECTION_LOOK_DEFAULTS,
2274
- priority: DEFAULT_PRIORITY
2275
- };
2276
2515
  /**
2277
2516
  * Default value of the default width of a diagram section.
2278
2517
  * @private
@@ -2297,6 +2536,41 @@ const DIAGRAM_SECTION_MIN_WIDTH = 1;
2297
2536
  * @see DiagramSection
2298
2537
  */
2299
2538
  const DIAGRAM_SECTION_MIN_HEIGHT = 1;
2539
+ /**
2540
+ * A grid of sections which a node has.
2541
+ * @public
2542
+ * @see DiagramNode
2543
+ * @see SectionGridConfig
2544
+ */
2545
+ class DiagramSectionGrid {
2546
+ constructor(options) {
2547
+ this.margin = options.margin || 0;
2548
+ this.defaultWidths = options.defaultWidths || null;
2549
+ this.defaultHeights = options.defaultHeights || null;
2550
+ this.minWidths = options.minWidths || null;
2551
+ this.minHeights = options.minHeights || null;
2552
+ this.sections = [];
2553
+ for (const sectionRow of options.sections) {
2554
+ const sectionList = [];
2555
+ this.sections.push(sectionList);
2556
+ for (const section of sectionRow) {
2557
+ sectionList.push(new DiagramSectionType(section));
2558
+ }
2559
+ }
2560
+ }
2561
+ }
2562
+ class DiagramSectionType {
2563
+ constructor(options) {
2564
+ this.label = options.label || null;
2565
+ this.ports = options.ports || [];
2566
+ this.priority = options.priority || DEFAULT_PRIORITY;
2567
+ const looks = extractLooksFromConfig(options.look || DIAGRAM_NODE_LOOK_DEFAULTS);
2568
+ this.defaultLook = looks.defaultLook;
2569
+ this.selectedLook = looks.selectedLook;
2570
+ this.highlightedLook = looks.highlightedLook;
2571
+ this.selectedAndHighlightedLook = looks.selectedAndHighlightedLook;
2572
+ }
2573
+ }
2300
2574
  /**
2301
2575
  * A section of a node which can have connections and display a property of the node.
2302
2576
  * @public
@@ -2318,10 +2592,52 @@ class DiagramSection extends DiagramElement {
2318
2592
  this.label.text = name;
2319
2593
  }
2320
2594
  }
2595
+ /**
2596
+ * Current look of this port.
2597
+ * @private
2598
+ */
2599
+ get look() {
2600
+ var _a, _b, _c, _d, _e, _f, _g, _h;
2601
+ if (this.selected) {
2602
+ if (this.highlighted) {
2603
+ return this._selectedAndHighlightedLook !== undefined ? this._selectedAndHighlightedLook : ((_a = this.type) === null || _a === undefined ? undefined : _a.selectedAndHighlightedLook) || ((_b = this.node) === null || _b === undefined ? undefined : _b.look);
2604
+ } else {
2605
+ return this._selectedLook !== undefined ? this._selectedLook : ((_c = this.type) === null || _c === undefined ? undefined : _c.selectedLook) || ((_d = this.node) === null || _d === undefined ? undefined : _d.look);
2606
+ }
2607
+ } else {
2608
+ if (this.highlighted) {
2609
+ return this._highlightedLook !== undefined ? this._highlightedLook : ((_e = this.type) === null || _e === undefined ? undefined : _e.highlightedLook) || ((_f = this.node) === null || _f === undefined ? undefined : _f.look);
2610
+ } else {
2611
+ return this._defaultLook !== undefined ? this._defaultLook : ((_g = this.type) === null || _g === undefined ? undefined : _g.defaultLook) || ((_h = this.node) === null || _h === undefined ? undefined : _h.look);
2612
+ }
2613
+ }
2614
+ }
2615
+ /**
2616
+ * Sets the look configuration of the look to override the one determined by the type.
2617
+ * `undefined` resets it to the one determined by the type.
2618
+ * @private
2619
+ */
2620
+ set look(look) {
2621
+ if (look) {
2622
+ const looks = extractLooksFromConfig(look);
2623
+ this._defaultLook = Object.assign(Object.assign({}, this._defaultLook), looks.defaultLook);
2624
+ this._selectedLook = Object.assign(Object.assign({}, this._selectedLook), looks.selectedLook);
2625
+ this._highlightedLook = Object.assign(Object.assign({}, this._highlightedLook), looks.highlightedLook);
2626
+ this._selectedAndHighlightedLook = Object.assign(Object.assign({}, this._selectedAndHighlightedLook), looks.selectedAndHighlightedLook);
2627
+ } else {
2628
+ this._defaultLook = look;
2629
+ this._selectedLook = look;
2630
+ this._highlightedLook = look;
2631
+ this._selectedAndHighlightedLook = look;
2632
+ }
2633
+ }
2321
2634
  constructor(model, node, indexXInNode, indexYInNode, coords, width, height, id) {
2322
2635
  if (model.sections.get(id) !== undefined) {
2323
2636
  throw new Error(`DiagramSection with id "${id}" already exists`);
2324
2637
  }
2638
+ if (!id) {
2639
+ throw new Error(`DiagramSection cannot have an empty or null id`);
2640
+ }
2325
2641
  super(model, id);
2326
2642
  /**
2327
2643
  * Ports of this section.
@@ -2360,7 +2676,7 @@ class DiagramSection extends DiagramElement {
2360
2676
  decorator.raise();
2361
2677
  }
2362
2678
  }
2363
- getConfig() {
2679
+ get type() {
2364
2680
  var _a, _b, _c, _d, _e;
2365
2681
  return (_e = (_d = (_c = (_b = (_a = this.node) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.sectionGrid) === null || _c === undefined ? undefined : _c.sections) === null || _d === undefined ? undefined : _d[this.indexYInNode]) === null || _e === undefined ? undefined : _e[this.indexXInNode];
2366
2682
  }
@@ -2374,7 +2690,7 @@ class DiagramSection extends DiagramElement {
2374
2690
  }
2375
2691
  getPriority() {
2376
2692
  var _a, _b, _c, _d, _e, _f;
2377
- return ((_f = (_e = (_d = (_c = (_b = (_a = this.node) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.sectionGrid) === null || _c === undefined ? undefined : _c.sections) === null || _d === undefined ? undefined : _d[this.indexYInNode]) === null || _e === undefined ? undefined : _e[this.indexXInNode]) === null || _f === undefined ? undefined : _f.priority) || DIAGRAM_SECTION_DEFAULTS.priority;
2693
+ return ((_f = (_e = (_d = (_c = (_b = (_a = this.node) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.sectionGrid) === null || _c === undefined ? undefined : _c.sections) === null || _d === undefined ? undefined : _d[this.indexYInNode]) === null || _e === undefined ? undefined : _e[this.indexXInNode]) === null || _f === undefined ? undefined : _f.priority) || DEFAULT_PRIORITY;
2378
2694
  }
2379
2695
  /**
2380
2696
  * Get the port of this section which is closest to the given coordinates.
@@ -2525,7 +2841,6 @@ class DiagramSection extends DiagramElement {
2525
2841
  * @public
2526
2842
  */
2527
2843
  setGeometry(geometry) {
2528
- var _a, _b, _c, _d, _e, _f;
2529
2844
  const oldCoordsX = [this.coords[0], this.coords[0] + this.width];
2530
2845
  const oldCoordsY = [this.coords[1], this.coords[1] + this.height];
2531
2846
  this.coords = [...geometry.coords];
@@ -2538,10 +2853,11 @@ class DiagramSection extends DiagramElement {
2538
2853
  port.move(translatePoint(port.coords, oldCoordsX, oldCoordsY, newCoordsX, newCoordsY));
2539
2854
  }
2540
2855
  // Set label's dimensions as a function of ours.
2856
+ const type = this.type;
2541
2857
  if (this.label) {
2542
- this.label.coords = [this.coords[0] + getLeftMargin((_a = this.getConfig()) === null || _a === undefined ? undefined : _a.label), this.coords[1] + getTopMargin((_b = this.getConfig()) === null || _b === undefined ? undefined : _b.label)];
2543
- this.label.width = this.width - getLeftMargin((_c = this.getConfig()) === null || _c === undefined ? undefined : _c.label) - getRightMargin((_d = this.getConfig()) === null || _d === undefined ? undefined : _d.label);
2544
- this.label.height = this.height - getTopMargin((_e = this.getConfig()) === null || _e === undefined ? undefined : _e.label) - getBottomMargin((_f = this.getConfig()) === null || _f === undefined ? undefined : _f.label);
2858
+ this.label.coords = [this.coords[0] + getLeftMargin(type === null || type === undefined ? undefined : type.label), this.coords[1] + getTopMargin(type === null || type === undefined ? undefined : type.label)];
2859
+ this.label.width = this.width - getLeftMargin(type === null || type === undefined ? undefined : type.label) - getRightMargin(type === null || type === undefined ? undefined : type.label);
2860
+ this.label.height = this.height - getTopMargin(type === null || type === undefined ? undefined : type.label) - getBottomMargin(type === null || type === undefined ? undefined : type.label);
2545
2861
  this.label.updateInView();
2546
2862
  }
2547
2863
  // Move decorators to match the new coords.
@@ -2579,25 +2895,25 @@ class DiagramSectionSet extends DiagramElementSet {
2579
2895
  if (sectionPorts && sectionPorts.length > 0) {
2580
2896
  for (let i = 0; i < sectionPorts.length; ++i) {
2581
2897
  const portConfig = sectionPorts[i];
2582
- const port = this.model.ports.new(section, [section.coords[0] + (((_e = portConfig === null || portConfig === undefined ? undefined : portConfig.coords) === null || _e === undefined ? undefined : _e[0]) || 0), section.coords[1] + (((_f = portConfig === null || portConfig === undefined ? undefined : portConfig.coords) === null || _f === undefined ? undefined : _f[1]) || 0)], portConfig === null || portConfig === undefined ? undefined : portConfig.direction, `${section.id}_${i}`);
2583
- if (portConfig.label) {
2584
- const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), portConfig.label);
2898
+ const port = this.model.ports.new(portConfig.type !== undefined ? this.model.ports.types.get(portConfig.type) : undefined, section, [section.coords[0] + (portConfig.coords[0] || 0), section.coords[1] + (portConfig.coords[1] || 0)], portConfig.connectionPoint !== undefined ? [section.coords[0] + (portConfig.connectionPoint[0] || 0), section.coords[1] + (portConfig.connectionPoint[1] || 0)] : undefined, portConfig === null || portConfig === undefined ? undefined : portConfig.direction, `${section.id}_${i}`);
2899
+ if ((_e = port.type) === null || _e === undefined ? undefined : _e.label) {
2900
+ const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), (_f = port.type) === null || _f === undefined ? undefined : _f.label);
2901
+ const labelWidth = 6 * labelConfiguration.fontSize + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
2902
+ const labelHeight = labelConfiguration.fontSize + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
2585
2903
  let labelCoords;
2586
2904
  switch (port.direction) {
2587
- case exports.Side.Top:
2588
- case exports.Side.Left:
2589
- labelCoords = [port.coords[0] - labelConfiguration.fontSize, port.coords[1] - labelConfiguration.fontSize];
2590
- break;
2591
2905
  case exports.Side.Bottom:
2592
- labelCoords = [port.coords[0] - labelConfiguration.fontSize, port.coords[1] + labelConfiguration.fontSize];
2593
- break;
2906
+ case exports.Side.Left:
2594
2907
  case exports.Side.Right:
2595
- labelCoords = [port.coords[0] + labelConfiguration.fontSize, port.coords[1] - labelConfiguration.fontSize];
2908
+ labelCoords = [port.coords[0] - labelWidth / 2, port.coords[1] - labelHeight - getBottomMargin(labelConfiguration)];
2909
+ break;
2910
+ case exports.Side.Top:
2911
+ labelCoords = [port.coords[0] - labelWidth / 2, port.coords[1] + getTopMargin(labelConfiguration)];
2596
2912
  break;
2597
2913
  default:
2598
2914
  labelCoords = port.coords;
2599
2915
  }
2600
- this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, '', labelConfiguration.editable, labelConfiguration.fit);
2916
+ this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, '', labelConfiguration.editable, labelConfiguration.fit);
2601
2917
  }
2602
2918
  }
2603
2919
  }
@@ -2642,8 +2958,14 @@ const DIAGRAM_NODE_LOOK_DEFAULTS = {
2642
2958
  shape: exports.ClosedShape.Rectangle,
2643
2959
  fillColor: '#FFFFFF',
2644
2960
  borderColor: '#000000',
2645
- selectedFillColor: '#FFFFFF',
2646
- selectedBorderColor: '#000000'
2961
+ borderThickness: 1,
2962
+ selected: {
2963
+ fillColor: '#FFAAFF',
2964
+ borderColor: '#AA00AA'
2965
+ },
2966
+ highlighted: {
2967
+ borderThickness: 3
2968
+ }
2647
2969
  };
2648
2970
  /**
2649
2971
  * Default values of the parameters of a diagram node.
@@ -2691,8 +3013,12 @@ class DiagramNodeType {
2691
3013
  this.topPadding = getTopPadding(values);
2692
3014
  this.label = values.label;
2693
3015
  this.ports = values.ports;
2694
- this.sectionGrid = values.sectionGrid;
2695
- this.look = values.look;
3016
+ this.sectionGrid = values.sectionGrid ? new DiagramSectionGrid(values.sectionGrid) : null;
3017
+ const looks = extractLooksFromConfig(values.look);
3018
+ this.defaultLook = looks.defaultLook;
3019
+ this.selectedLook = looks.selectedLook;
3020
+ this.highlightedLook = looks.highlightedLook;
3021
+ this.selectedAndHighlightedLook = looks.selectedAndHighlightedLook;
2696
3022
  this.isUnique = values.isUnique;
2697
3023
  this.canBeParentless = values.canBeParentless;
2698
3024
  this.childrenTypes = values.childrenTypes;
@@ -2708,6 +3034,27 @@ class DiagramNodeType {
2708
3034
  * @see DiagramSection
2709
3035
  */
2710
3036
  class DiagramNode extends DiagramElement {
3037
+ get type() {
3038
+ return this._type;
3039
+ }
3040
+ set type(type) {
3041
+ var _a, _b;
3042
+ (_b = (_a = this.model.canvas) === null || _a === undefined ? undefined : _a.userSelection) === null || _b === undefined ? undefined : _b.openInPropertyEditor(undefined);
3043
+ this._type = type;
3044
+ if (this.valueSet) {
3045
+ this.valueSet = new ValueSet(type.propertySet, this);
3046
+ }
3047
+ this.updateInView();
3048
+ }
3049
+ get typeString() {
3050
+ return this.type.id;
3051
+ }
3052
+ set typeString(typeString) {
3053
+ const type = this.model.nodes.types.get(typeString);
3054
+ if (type) {
3055
+ this.type = type;
3056
+ }
3057
+ }
2711
3058
  /**
2712
3059
  * Name of this node. Alias for this node's label's text.
2713
3060
  * @public
@@ -2721,10 +3068,51 @@ class DiagramNode extends DiagramElement {
2721
3068
  this.label.text = name;
2722
3069
  }
2723
3070
  }
3071
+ /**
3072
+ * Current look of this port.
3073
+ * @private
3074
+ */
3075
+ get look() {
3076
+ if (this.selected) {
3077
+ if (this.highlighted) {
3078
+ return this._selectedAndHighlightedLook !== undefined ? this._selectedAndHighlightedLook : this.type.selectedAndHighlightedLook;
3079
+ } else {
3080
+ return this._selectedLook !== undefined ? this._selectedLook : this.type.selectedLook;
3081
+ }
3082
+ } else {
3083
+ if (this.highlighted) {
3084
+ return this._highlightedLook !== undefined ? this._highlightedLook : this.type.highlightedLook;
3085
+ } else {
3086
+ return this._defaultLook !== undefined ? this._defaultLook : this.type.defaultLook;
3087
+ }
3088
+ }
3089
+ }
3090
+ /**
3091
+ * Sets the look configuration of the look to override the one determined by the type.
3092
+ * `undefined` resets it to the one determined by the type.
3093
+ * @private
3094
+ */
3095
+ set look(look) {
3096
+ if (look) {
3097
+ const looks = extractLooksFromConfig(look);
3098
+ this._defaultLook = Object.assign(Object.assign({}, this._defaultLook), looks.defaultLook);
3099
+ this._selectedLook = Object.assign(Object.assign({}, this._selectedLook), looks.selectedLook);
3100
+ this._highlightedLook = Object.assign(Object.assign({}, this._highlightedLook), looks.highlightedLook);
3101
+ this._selectedAndHighlightedLook = Object.assign(Object.assign({}, this._selectedAndHighlightedLook), looks.selectedAndHighlightedLook);
3102
+ } else {
3103
+ this._defaultLook = look;
3104
+ this._selectedLook = look;
3105
+ this._highlightedLook = look;
3106
+ this._selectedAndHighlightedLook = look;
3107
+ }
3108
+ }
2724
3109
  constructor(model, type, coords = [0, 0], id) {
2725
3110
  if (model.nodes.get(id) !== undefined) {
2726
3111
  throw new Error(`DiagramNode with id "${id}" already exists`);
2727
3112
  }
3113
+ if (!id) {
3114
+ throw new Error(`DiagramNode cannot have an empty or null id`);
3115
+ }
2728
3116
  super(model, id);
2729
3117
  /**
2730
3118
  * Nodes contained within this node.
@@ -2751,7 +3139,7 @@ class DiagramNode extends DiagramElement {
2751
3139
  * @public
2752
3140
  */
2753
3141
  this.geometryTimestamp = null;
2754
- this.type = type;
3142
+ this._type = type;
2755
3143
  this.valueSet = new ValueSet(type.propertySet, this);
2756
3144
  this.originalData = {};
2757
3145
  this.coords = coords;
@@ -3230,11 +3618,11 @@ class DiagramNodeSet extends DiagramElementSet {
3230
3618
  * @public
3231
3619
  * @param type The type of the node given as either the type itself or the id of the type.
3232
3620
  * @param coords The coordinates of the top left corner of the node in the diagram.
3233
- * @param id The id of the node.
3621
+ * @param id The id of the node. Cannot be an empty string.
3234
3622
  * @returns The instanced node.
3235
3623
  */
3236
3624
  new(type, coords, id) {
3237
- var _a, _b, _c, _d, _e;
3625
+ var _a, _b, _c, _d, _e, _f, _g;
3238
3626
  let nodeType;
3239
3627
  if (type instanceof DiagramNodeType) {
3240
3628
  nodeType = type;
@@ -3265,25 +3653,26 @@ class DiagramNodeSet extends DiagramElementSet {
3265
3653
  if (nodeType.ports.length > 0) {
3266
3654
  for (let i = 0; i < nodeType.ports.length; ++i) {
3267
3655
  const portConfig = nodeType.ports[i];
3268
- const port = this.model.ports.new(node, [node.coords[0] + portConfig.coords[0], node.coords[1] + portConfig.coords[1]], portConfig.direction, `${node.id}_${i}`);
3269
- if (portConfig.label) {
3270
- const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), portConfig.label);
3656
+ const portType = portConfig.type !== undefined ? this.model.ports.types.get(portConfig.type) : undefined;
3657
+ const port = this.model.ports.new(portType, node, [node.coords[0] + portConfig.coords[0], node.coords[1] + portConfig.coords[1]], portConfig.connectionPoint !== undefined ? [node.coords[0] + (portConfig.connectionPoint[0] || 0), node.coords[1] + (portConfig.connectionPoint[1] || 0)] : undefined, portConfig.direction, `${node.id}_${i}`);
3658
+ if ((_e = port.type) === null || _e === undefined ? undefined : _e.label) {
3659
+ const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), (_f = port.type) === null || _f === undefined ? undefined : _f.label);
3660
+ const labelWidth = 6 * labelConfiguration.fontSize + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
3661
+ const labelHeight = labelConfiguration.fontSize + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
3271
3662
  let labelCoords;
3272
3663
  switch (port.direction) {
3273
- case exports.Side.Top:
3274
- case exports.Side.Left:
3275
- labelCoords = [port.coords[0] - labelConfiguration.fontSize, port.coords[1] - labelConfiguration.fontSize];
3276
- break;
3277
3664
  case exports.Side.Bottom:
3278
- labelCoords = [port.coords[0] - labelConfiguration.fontSize, port.coords[1] + labelConfiguration.fontSize];
3279
- break;
3665
+ case exports.Side.Left:
3280
3666
  case exports.Side.Right:
3281
- labelCoords = [port.coords[0] + labelConfiguration.fontSize, port.coords[1] - labelConfiguration.fontSize];
3667
+ labelCoords = [port.coords[0] - labelWidth / 2, port.coords[1] - labelHeight - getBottomMargin(labelConfiguration)];
3668
+ break;
3669
+ case exports.Side.Top:
3670
+ labelCoords = [port.coords[0] - labelWidth / 2, port.coords[1] + getTopMargin(labelConfiguration)];
3282
3671
  break;
3283
3672
  default:
3284
3673
  labelCoords = port.coords;
3285
3674
  }
3286
- this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, '', labelConfiguration.editable, labelConfiguration.fit);
3675
+ this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, '', labelConfiguration.editable, labelConfiguration.fit);
3287
3676
  }
3288
3677
  }
3289
3678
  }
@@ -3293,7 +3682,7 @@ class DiagramNodeSet extends DiagramElementSet {
3293
3682
  this.model.fields.new(node, [node.coords[0] + getLeftMargin(labelConfiguration), node.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, node.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), node.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, '', labelConfiguration.editable, labelConfiguration.fit);
3294
3683
  }
3295
3684
  node.valueSet.resetValues();
3296
- (_e = node.model.canvas) === null || _e === undefined ? undefined : _e.fitNodeInView(node.id);
3685
+ (_g = node.model.canvas) === null || _g === undefined ? undefined : _g.fitNodeInView(node.id);
3297
3686
  return node;
3298
3687
  }
3299
3688
  remove(id) {
@@ -3461,16 +3850,59 @@ const getTopPadding = config => {
3461
3850
  }
3462
3851
  };
3463
3852
 
3853
+ /**
3854
+ * Default values of the look of a diagram port.
3855
+ * @private
3856
+ * @see DIAGRAM_NODE_TYPE_DEFAULTS
3857
+ */
3858
+ const DIAGRAM_PORT_LOOK_DEFAULTS = {
3859
+ lookType: 'shaped-look',
3860
+ shape: exports.ClosedShape.Ellipse,
3861
+ fillColor: 'transparent',
3862
+ borderColor: 'transparent',
3863
+ borderThickness: 0,
3864
+ selected: {
3865
+ fillColor: 'rgba(255, 0, 255, 0.5)'
3866
+ },
3867
+ highlighted: {
3868
+ fillColor: 'rgba(0, 255, 255, 0.5)'
3869
+ }
3870
+ };
3871
+ const DIAGRAM_PORT_LOOKS = extractLooksFromConfig(DIAGRAM_PORT_LOOK_DEFAULTS);
3464
3872
  /**
3465
3873
  * Default values of the parameters of a diagram port.
3466
3874
  * @private
3467
3875
  * @see DiagramPort
3468
3876
  */
3469
- const DIAGRAM_PORT_DEFAULTS = {
3470
- radius: 12,
3471
- highlightedColor: 'cyan',
3472
- selectedColor: 'violet'
3877
+ const DIAGRAM_PORT_TYPE_DEFAULTS = {
3878
+ name: '',
3879
+ label: null,
3880
+ allowsOutgoing: true,
3881
+ allowsIncoming: true,
3882
+ width: 24,
3883
+ look: DIAGRAM_PORT_LOOK_DEFAULTS
3473
3884
  };
3885
+ /**
3886
+ * A port type, which holds properties that ports of this type share in common.
3887
+ * @public
3888
+ * @see PortTypeConfig
3889
+ */
3890
+ class DiagramPortType {
3891
+ constructor(options) {
3892
+ const values = Object.assign(Object.assign({}, DIAGRAM_PORT_TYPE_DEFAULTS), options);
3893
+ this.id = values.id;
3894
+ this.name = values.name;
3895
+ this.label = values.label;
3896
+ this.allowsOutgoing = values.allowsOutgoing;
3897
+ this.allowsIncoming = values.allowsIncoming;
3898
+ this.width = values.width;
3899
+ const looks = extractLooksFromConfig(values.look);
3900
+ this.defaultLook = looks.defaultLook;
3901
+ this.selectedLook = looks.selectedLook;
3902
+ this.highlightedLook = looks.highlightedLook;
3903
+ this.selectedAndHighlightedLook = looks.selectedAndHighlightedLook;
3904
+ }
3905
+ }
3474
3906
  /**
3475
3907
  * A port which is part of a node or section and at which connections can start or end.
3476
3908
  * @public
@@ -3479,10 +3911,115 @@ const DIAGRAM_PORT_DEFAULTS = {
3479
3911
  * @see DiagramSection
3480
3912
  */
3481
3913
  class DiagramPort extends DiagramElement {
3482
- constructor(model, rootElement, coords, direction, id) {
3914
+ get type() {
3915
+ return this._type;
3916
+ }
3917
+ set type(type) {
3918
+ this._type = type;
3919
+ this.updateInView();
3920
+ }
3921
+ get typeString() {
3922
+ var _a;
3923
+ return (_a = this.type) === null || _a === undefined ? undefined : _a.id;
3924
+ }
3925
+ set typeString(typeString) {
3926
+ if (typeString === undefined) {
3927
+ this.type = undefined;
3928
+ } else {
3929
+ const type = this.model.ports.types.get(typeString);
3930
+ if (type) {
3931
+ this.type = type;
3932
+ }
3933
+ }
3934
+ }
3935
+ /**
3936
+ * Whether this port can be used as a connection start point.
3937
+ */
3938
+ get allowsOutgoing() {
3939
+ var _a, _b;
3940
+ return ((_a = this.type) === null || _a === undefined ? undefined : _a.allowsOutgoing) !== undefined ? (_b = this.type) === null || _b === undefined ? undefined : _b.allowsOutgoing : true;
3941
+ }
3942
+ /**
3943
+ * Whether this port can be used as a connection end point.
3944
+ */
3945
+ get allowsIncoming() {
3946
+ var _a, _b;
3947
+ return ((_a = this.type) === null || _a === undefined ? undefined : _a.allowsIncoming) !== undefined ? (_b = this.type) === null || _b === undefined ? undefined : _b.allowsIncoming : true;
3948
+ }
3949
+ /**
3950
+ * Name of this port. Alias for this port's label's text.
3951
+ * @public
3952
+ */
3953
+ get name() {
3954
+ var _a;
3955
+ return ((_a = this.label) === null || _a === undefined ? undefined : _a.text) || '';
3956
+ }
3957
+ set name(name) {
3958
+ if (this.label) {
3959
+ this.label.text = name;
3960
+ }
3961
+ }
3962
+ /**
3963
+ * Current look of this port.
3964
+ * @private
3965
+ */
3966
+ get look() {
3967
+ var _a, _b, _c, _d;
3968
+ if (this.selected) {
3969
+ if (this.highlighted) {
3970
+ return this._selectedAndHighlightedLook !== undefined ? this._selectedAndHighlightedLook : (_a = this.type || DIAGRAM_PORT_LOOKS) === null || _a === undefined ? undefined : _a.selectedAndHighlightedLook;
3971
+ } else {
3972
+ return this._selectedLook !== undefined ? this._selectedLook : (_b = this.type || DIAGRAM_PORT_LOOKS) === null || _b === undefined ? undefined : _b.selectedLook;
3973
+ }
3974
+ } else {
3975
+ if (this.highlighted) {
3976
+ return this._highlightedLook !== undefined ? this._highlightedLook : (_c = this.type || DIAGRAM_PORT_LOOKS) === null || _c === undefined ? undefined : _c.highlightedLook;
3977
+ } else {
3978
+ return this._defaultLook !== undefined ? this._defaultLook : (_d = this.type || DIAGRAM_PORT_LOOKS) === null || _d === undefined ? undefined : _d.defaultLook;
3979
+ }
3980
+ }
3981
+ }
3982
+ /**
3983
+ * Sets the look configuration of the look to override the one determined by the type.
3984
+ * `undefined` resets it to the one determined by the type.
3985
+ * @private
3986
+ */
3987
+ set look(look) {
3988
+ if (look) {
3989
+ const looks = extractLooksFromConfig(look);
3990
+ this._defaultLook = Object.assign(Object.assign({}, this._defaultLook), looks.defaultLook);
3991
+ this._selectedLook = Object.assign(Object.assign({}, this._selectedLook), looks.selectedLook);
3992
+ this._highlightedLook = Object.assign(Object.assign({}, this._highlightedLook), looks.highlightedLook);
3993
+ this._selectedAndHighlightedLook = Object.assign(Object.assign({}, this._selectedAndHighlightedLook), looks.selectedAndHighlightedLook);
3994
+ } else {
3995
+ this._defaultLook = look;
3996
+ this._selectedLook = look;
3997
+ this._highlightedLook = look;
3998
+ this._selectedAndHighlightedLook = look;
3999
+ }
4000
+ }
4001
+ /**
4002
+ * Current width of this port.
4003
+ * @private
4004
+ */
4005
+ get width() {
4006
+ var _a;
4007
+ return ((_a = this.type) === null || _a === undefined ? undefined : _a.width) || DIAGRAM_PORT_TYPE_DEFAULTS.width;
4008
+ }
4009
+ /**
4010
+ * Current height of this port. Same as the width.
4011
+ * @private
4012
+ */
4013
+ get height() {
4014
+ return this.width;
4015
+ }
4016
+ constructor(model, type, rootElement, coords, connectionPoint, direction, id) {
3483
4017
  if (model.ports.get(id) !== undefined) {
3484
4018
  throw new Error(`DiagramPort with id "${id}" already exists`);
3485
4019
  }
4020
+ if (!id) {
4021
+ throw new Error(`DiagramPort cannot have an empty or null id`);
4022
+ }
3486
4023
  super(model, id);
3487
4024
  /**
3488
4025
  * Connections that start at this port.
@@ -3494,8 +4031,10 @@ class DiagramPort extends DiagramElement {
3494
4031
  * @public
3495
4032
  */
3496
4033
  this.incomingConnections = [];
4034
+ this._type = type;
3497
4035
  this.rootElement = rootElement;
3498
4036
  this.coords = coords;
4037
+ this.connectionPoint = connectionPoint || coords;
3499
4038
  this.direction = direction;
3500
4039
  }
3501
4040
  get removed() {
@@ -3508,6 +4047,9 @@ class DiagramPort extends DiagramElement {
3508
4047
  raise() {
3509
4048
  var _a;
3510
4049
  (_a = this.select()) === null || _a === undefined ? undefined : _a.raise();
4050
+ if (this.label) {
4051
+ this.label.raise();
4052
+ }
3511
4053
  for (const connection of this.incomingConnections) {
3512
4054
  connection.raise();
3513
4055
  }
@@ -3556,6 +4098,8 @@ class DiagramPort extends DiagramElement {
3556
4098
  move(coords) {
3557
4099
  const coordDifferences = [coords[0] - this.coords[0], coords[1] - this.coords[1]];
3558
4100
  this.coords = coords;
4101
+ this.connectionPoint[0] = this.connectionPoint[0] + coordDifferences[0];
4102
+ this.connectionPoint[1] = this.connectionPoint[1] + coordDifferences[1];
3559
4103
  for (const connection of this.outgoingConnections) {
3560
4104
  connection.setStart(this);
3561
4105
  }
@@ -3578,14 +4122,19 @@ class DiagramPortSet extends DiagramElementSet {
3578
4122
  */
3579
4123
  constructor(model) {
3580
4124
  super();
4125
+ /**
4126
+ * Set of the possible types of port that the ports of this set can have.
4127
+ * @public
4128
+ */
4129
+ this.types = new DiagramEntitySet();
3581
4130
  this.model = model;
3582
4131
  }
3583
4132
  /**
3584
4133
  * Instance a new port and add it to this set. This method is normally called when instancing an element with a port and it is rarely called by itself.
3585
4134
  * @private
3586
4135
  */
3587
- new(rootElement, coords, direction, id) {
3588
- const port = new DiagramPort(this.model, rootElement, coords, direction, id);
4136
+ new(type, rootElement, coords, connectionPoint, direction, id) {
4137
+ const port = new DiagramPort(this.model, type, rootElement, coords, connectionPoint, direction, id);
3589
4138
  super.add(port);
3590
4139
  port.updateInView();
3591
4140
  // add this port to its root element
@@ -3694,13 +4243,14 @@ class DagaImporter {
3694
4243
  }
3695
4244
  let portCounter = 0;
3696
4245
  for (const port of section.ports || []) {
3697
- const newPort = new DiagramPort(model, newSection, port.coords, port.direction, port.id);
4246
+ const newPortType = port.type !== undefined ? model.ports.types.get(port.type) : undefined;
4247
+ const newPort = new DiagramPort(model, newPortType, newSection, port.coords, port.connectionPoint, port.direction, port.id);
3698
4248
  newSection.ports.push(newPort);
3699
4249
  model.ports.add(newPort);
3700
4250
  if (port.label) {
3701
4251
  // add port label
3702
- if (newNodeType.ports.length > portCounter && newNodeType.ports[portCounter].label) {
3703
- const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newNodeType.ports[portCounter].label);
4252
+ if (newNodeType.ports.length > portCounter && (newPortType === null || newPortType === undefined ? undefined : newPortType.label)) {
4253
+ const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newPortType === null || newPortType === undefined ? undefined : newPortType.label);
3704
4254
  let labelCoords;
3705
4255
  switch (newPort.direction) {
3706
4256
  case exports.Side.Top:
@@ -3740,13 +4290,14 @@ class DagaImporter {
3740
4290
  }
3741
4291
  let portCounter = 0;
3742
4292
  for (const port of node.ports || []) {
3743
- const newPort = new DiagramPort(model, newNode, port.coords, port.direction, port.id);
4293
+ const newPortType = port.type !== undefined ? model.ports.types.get(port.type) : undefined;
4294
+ const newPort = new DiagramPort(model, newPortType, newNode, port.coords, port.connectionPoint, port.direction, port.id);
3744
4295
  newNode.ports.push(newPort);
3745
4296
  model.ports.add(newPort);
3746
4297
  if (port.label) {
3747
4298
  // add port label
3748
- if (newNodeType.ports.length > portCounter && newNodeType.ports[portCounter].label) {
3749
- const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newNodeType.ports[portCounter].label);
4299
+ if (newNodeType.ports.length > portCounter && (newPortType === null || newPortType === undefined ? undefined : newPortType.label)) {
4300
+ const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newPortType === null || newPortType === undefined ? undefined : newPortType.label);
3750
4301
  let labelCoords;
3751
4302
  switch (newPort.direction) {
3752
4303
  case exports.Side.Top:
@@ -3788,6 +4339,8 @@ class DagaImporter {
3788
4339
  newNode.valueSet.setTimestamps(node.collabMeta.dataTimestamps);
3789
4340
  }
3790
4341
  newNode.updateInView();
4342
+ // raise node to sort the render order of the node and its components
4343
+ newNode.raise();
3791
4344
  return newNode;
3792
4345
  }
3793
4346
  return undefined;
@@ -3810,6 +4363,8 @@ class DagaImporter {
3810
4363
  newConnection.valueSet.setTimestamps(connection.collabMeta.dataTimestamps);
3811
4364
  }
3812
4365
  newConnection.updateInView();
4366
+ // raise connection just in case it is necessary to sort the render order
4367
+ newConnection.raise();
3813
4368
  return newConnection;
3814
4369
  }
3815
4370
  return undefined;
@@ -5067,7 +5622,10 @@ class DiagramHighlightedEvent extends DiagramEvent {
5067
5622
  class DiagramDecorator extends DiagramElement {
5068
5623
  constructor(model, rootElement, coords, width, height, priority, html, id) {
5069
5624
  if (model.objects.get(id) !== undefined) {
5070
- throw new Error(`DiagramObject with id "${id}" already exists`);
5625
+ throw new Error(`DiagramDecorator with id "${id}" already exists`);
5626
+ }
5627
+ if (!id) {
5628
+ throw new Error(`DiagramDecorator cannot have an empty or null id`);
5071
5629
  }
5072
5630
  super(model, id);
5073
5631
  this.rootElement = rootElement;
@@ -5116,7 +5674,14 @@ class DiagramDecoratorSet extends DiagramElementSet {
5116
5674
  }
5117
5675
  /**
5118
5676
  * Instance a new decorator and add it to this set.
5119
- * @private
5677
+ * @public
5678
+ * @param coords The coordinates of the top left corner of the decorator in the diagram.
5679
+ * @param width The dimension of the decorator along the x axis.
5680
+ * @param height The dimension of the decorator along the y axis.
5681
+ * @param priority The priority of the decorator. Used when filtering by priority.
5682
+ * @param html The html contents of the decorator.
5683
+ * @param id The id of the decorator. Cannot be an empty string.
5684
+ * @returns The instanced decorator.
5120
5685
  */
5121
5686
  new(rootElement, coords, width, height, priority, html, id) {
5122
5687
  const decorator = new DiagramDecorator(this.model, rootElement, coords, width, height, priority, html, id);
@@ -5153,6 +5718,9 @@ class DiagramObject extends DiagramElement {
5153
5718
  if (model.objects.get(id) !== undefined) {
5154
5719
  throw new Error(`DiagramObject with id "${id}" already exists`);
5155
5720
  }
5721
+ if (!id) {
5722
+ throw new Error(`DiagramObject cannot have an empty or null id`);
5723
+ }
5156
5724
  super(model, id);
5157
5725
  this.coords = coords;
5158
5726
  this.width = width;
@@ -5199,7 +5767,14 @@ class DiagramObjectSet extends DiagramElementSet {
5199
5767
  }
5200
5768
  /**
5201
5769
  * Instance a new object and add it to this set.
5202
- * @private
5770
+ * @public
5771
+ * @param coords The coordinates of the top left corner of the object in the diagram.
5772
+ * @param width The dimension of the object along the x axis.
5773
+ * @param height The dimension of the object along the y axis.
5774
+ * @param priority The priority of the object. Used when filtering by priority.
5775
+ * @param html The html contents of the object.
5776
+ * @param id The id of the object. Cannot be an empty string.
5777
+ * @returns The instanced object.
5203
5778
  */
5204
5779
  new(coords, width, height, priority, html, id) {
5205
5780
  const object = new DiagramObject(this.model, coords, width, height, priority, html, id);
@@ -5302,6 +5877,68 @@ class DiagramModel {
5302
5877
  }
5303
5878
  }
5304
5879
 
5880
+ /**
5881
+ * Checks if the given mouse event was produced with a secondary button press.
5882
+ * @private
5883
+ * @param event A mouse event.
5884
+ * @returns `true` if the given mouse event was produced with a secondary button press, `false` otherwise.
5885
+ */
5886
+ const isSecondaryButton = event => {
5887
+ return !!event.button;
5888
+ };
5889
+ /**
5890
+ * Get the SVG path of a diagram connection.
5891
+ * @private
5892
+ * @see linePath
5893
+ */
5894
+ const getConnectionPath = (shape, startCoords, endCoords, startDirection, endDirection, width, startMarkerWidth, endMarkerWidth) => {
5895
+ return linePath(shape, [startCoords, endCoords], startDirection, endDirection, Math.max(
5896
+ // reasonable value for the minimumDistanceBeforeTurn relative to the line width
5897
+ 10, startMarkerWidth || 0, endMarkerWidth || 0) * width);
5898
+ };
5899
+ const setCursorStyle = style => {
5900
+ if (!style) {
5901
+ d3__namespace.select('body').style('cursor', exports.CursorStyle.Auto);
5902
+ } else {
5903
+ d3__namespace.select('body').style('cursor', style);
5904
+ }
5905
+ };
5906
+ const getRelatedNodeOrItself = element => {
5907
+ if (element instanceof DiagramNode) {
5908
+ return element;
5909
+ }
5910
+ if (element instanceof DiagramSection) {
5911
+ return element.node || element;
5912
+ }
5913
+ return element.rootElement instanceof DiagramNode || element.rootElement instanceof DiagramSection || element.rootElement instanceof DiagramPort ? getRelatedNodeOrItself(element.rootElement) : element;
5914
+ };
5915
+ const initializeLook = selection => {
5916
+ selection.filter('.shaped-look').append('path');
5917
+ selection.filter('.image-look').append('image').attr('preserveAspectRatio', 'none');
5918
+ selection.filter('.stretchable-image-look').append('image').attr('class', 'top-left-image').attr('preserveAspectRatio', 'none');
5919
+ selection.filter('.stretchable-image-look').append('image').attr('class', 'top-image').attr('preserveAspectRatio', 'none');
5920
+ selection.filter('.stretchable-image-look').append('image').attr('class', 'top-right-image').attr('preserveAspectRatio', 'none');
5921
+ selection.filter('.stretchable-image-look').append('image').attr('class', 'left-image').attr('preserveAspectRatio', 'none');
5922
+ selection.filter('.stretchable-image-look').append('image').attr('class', 'center-image').attr('preserveAspectRatio', 'none');
5923
+ selection.filter('.stretchable-image-look').append('image').attr('class', 'right-image').attr('preserveAspectRatio', 'none');
5924
+ selection.filter('.stretchable-image-look').append('image').attr('class', 'bottom-left-image').attr('preserveAspectRatio', 'none');
5925
+ selection.filter('.stretchable-image-look').append('image').attr('class', 'bottom-image').attr('preserveAspectRatio', 'none');
5926
+ selection.filter('.stretchable-image-look').append('image').attr('class', 'bottom-right-image').attr('preserveAspectRatio', 'none');
5927
+ };
5928
+ const updateLook = selection => {
5929
+ selection.filter('.shaped-look').select('path').attr('d', d => generalClosedPath(d.look.shape, 0, 0, d.width, d.height)).attr('fill', d => d.look.fillColor).attr('stroke', d => d.look.borderColor).attr('stroke-width', d => `${d.look.borderThickness}px`);
5930
+ selection.filter('.image-look').select('image').attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('href', d => d.look.backgroundImage);
5931
+ selection.filter('.stretchable-image-look').select('image.top-left-image').attr('x', 0).attr('y', 0).attr('width', d => d.look.leftMargin).attr('height', d => d.look.topMargin).attr('href', d => d.look.backgroundImageTopLeft);
5932
+ selection.filter('.stretchable-image-look').select('image.top-image').attr('x', d => d.look.leftMargin).attr('y', 0).attr('width', d => d.width - d.look.rightMargin - d.look.leftMargin).attr('height', d => d.look.topMargin).attr('href', d => d.look.backgroundImageTop);
5933
+ selection.filter('.stretchable-image-look').select('image.top-right-image').attr('x', d => d.width - d.look.rightMargin).attr('y', 0).attr('width', d => d.look.rightMargin).attr('height', d => d.look.topMargin).attr('href', d => d.look.backgroundImageTopRight);
5934
+ selection.filter('.stretchable-image-look').select('image.left-image').attr('x', 0).attr('y', d => d.look.topMargin).attr('width', d => d.look.leftMargin).attr('height', d => d.height - d.look.bottomMargin - d.look.topMargin).attr('href', d => d.look.backgroundImageLeft);
5935
+ selection.filter('.stretchable-image-look').select('image.center-image').attr('x', d => d.look.leftMargin).attr('y', d => d.look.topMargin).attr('width', d => d.width - d.look.rightMargin - d.look.leftMargin).attr('height', d => d.height - d.look.bottomMargin - d.look.topMargin).attr('href', d => d.look.backgroundImageCenter);
5936
+ selection.filter('.stretchable-image-look').select('image.right-image').attr('x', d => d.width - d.look.rightMargin).attr('y', d => d.look.topMargin).attr('width', d => d.look.rightMargin).attr('height', d => d.height - d.look.bottomMargin - d.look.topMargin).attr('href', d => d.look.backgroundImageRight);
5937
+ selection.filter('.stretchable-image-look').select('image.bottom-left-image').attr('x', 0).attr('y', d => d.height - d.look.bottomMargin).attr('width', d => d.look.leftMargin).attr('height', d => d.look.bottomMargin).attr('href', d => d.look.backgroundImageBottomLeft);
5938
+ selection.filter('.stretchable-image-look').select('image.bottom-image').attr('x', d => d.look.leftMargin).attr('y', d => d.height - d.look.bottomMargin).attr('width', d => d.width - d.look.rightMargin - d.look.leftMargin).attr('height', d => d.look.bottomMargin).attr('href', d => d.look.backgroundImageBottom);
5939
+ selection.filter('.stretchable-image-look').select('image.bottom-right-image').attr('x', d => d.width - d.look.rightMargin).attr('y', d => d.height - d.look.bottomMargin).attr('width', d => d.look.rightMargin).attr('height', d => d.look.bottomMargin).attr('href', d => d.look.backgroundImageBottomRight);
5940
+ };
5941
+
5305
5942
  const CONTEXT_MENU_MENU_RADIUS = 96;
5306
5943
  const CONTEXT_MENU_BUTTON_RADIUS = 32;
5307
5944
  const CONTEXT_MENU_TOTAL_RADIUS = CONTEXT_MENU_MENU_RADIUS + CONTEXT_MENU_BUTTON_RADIUS;
@@ -5552,7 +6189,7 @@ class DagaExporter {
5552
6189
  return result;
5553
6190
  }
5554
6191
  exportNode(node, includeCollabMeta = false) {
5555
- var _a, _b, _c, _d;
6192
+ var _a, _b, _c, _d, _e, _f;
5556
6193
  const children = [];
5557
6194
  for (const child of node.children) {
5558
6195
  children.push(this.exportNode(child, includeCollabMeta));
@@ -5563,9 +6200,11 @@ class DagaExporter {
5563
6200
  for (const port of section.ports) {
5564
6201
  ports.push(Object.assign({
5565
6202
  id: port.id,
6203
+ type: (_a = port.type) === null || _a === undefined ? undefined : _a.id,
5566
6204
  coords: roundPoint(port.coords),
6205
+ connectionPoint: roundPoint(port.connectionPoint),
5567
6206
  direction: port.direction,
5568
- label: ((_a = port.label) === null || _a === undefined ? undefined : _a.text) || ''
6207
+ label: ((_b = port.label) === null || _b === undefined ? undefined : _b.text) || ''
5569
6208
  }, includeCollabMeta ? {
5570
6209
  collabMeta: Object.assign({
5571
6210
  removed: port.removed,
@@ -5577,7 +6216,7 @@ class DagaExporter {
5577
6216
  sections.push(Object.assign({
5578
6217
  id: section.id,
5579
6218
  ports,
5580
- label: ((_b = section.label) === null || _b === undefined ? undefined : _b.text) || '',
6219
+ label: ((_c = section.label) === null || _c === undefined ? undefined : _c.text) || '',
5581
6220
  indexXInNode: section.indexXInNode,
5582
6221
  indexYInNode: section.indexYInNode,
5583
6222
  coords: roundPoint(section.coords),
@@ -5595,9 +6234,11 @@ class DagaExporter {
5595
6234
  for (const port of node.ports) {
5596
6235
  ports.push(Object.assign({
5597
6236
  id: port.id,
6237
+ type: (_d = port.type) === null || _d === undefined ? undefined : _d.id,
5598
6238
  coords: roundPoint(port.coords),
6239
+ connectionPoint: roundPoint(port.connectionPoint),
5599
6240
  direction: port.direction,
5600
- label: ((_c = port.label) === null || _c === undefined ? undefined : _c.text) || ''
6241
+ label: ((_e = port.label) === null || _e === undefined ? undefined : _e.text) || ''
5601
6242
  }, includeCollabMeta ? {
5602
6243
  collabMeta: Object.assign({
5603
6244
  removed: port.removed,
@@ -5612,7 +6253,7 @@ class DagaExporter {
5612
6253
  children,
5613
6254
  sections,
5614
6255
  ports,
5615
- label: ((_d = node.label) === null || _d === undefined ? undefined : _d.text) || '',
6256
+ label: ((_f = node.label) === null || _f === undefined ? undefined : _f.text) || '',
5616
6257
  coords: roundPoint(node.coords),
5617
6258
  width: node.width,
5618
6259
  height: node.height,
@@ -5892,7 +6533,7 @@ class DiagramUserSelection extends DiagramElementSet {
5892
6533
  }
5893
6534
  }
5894
6535
  makeUpdateValuesAction() {
5895
- var _a, _b;
6536
+ var _a, _b, _c;
5896
6537
  if (this.propertyEditorSelection === undefined || this.propertyEditorValues === undefined) {
5897
6538
  return;
5898
6539
  }
@@ -5904,7 +6545,7 @@ class DiagramUserSelection extends DiagramElementSet {
5904
6545
  }
5905
6546
  const from = this.propertyEditorValues;
5906
6547
  const to = structuredClone((_b = this.propertyEditorSelection) === null || _b === undefined ? undefined : _b.valueSet.getValues());
5907
- const [fromDiff, toDiff] = diff(from, to);
6548
+ const [fromDiff, toDiff] = diffProperties(from, to, (_c = this.propertyEditorSelection) === null || _c === undefined ? undefined : _c.valueSet);
5908
6549
  const currentAction = new UpdateValuesAction(this.canvas, previousSelectionId, fromDiff, toDiff);
5909
6550
  currentAction.do();
5910
6551
  this.canvas.actionStack.add(currentAction);
@@ -5988,6 +6629,13 @@ class DiagramCanvas {
5988
6629
  this.model.nodes.types.add(nodeType);
5989
6630
  }
5990
6631
  }
6632
+ // load port types
6633
+ if (config.portTypes) {
6634
+ for (const portTypeConfig of config.portTypes) {
6635
+ const portType = new DiagramPortType(Object.assign(Object.assign({}, config.portTypeDefaults), portTypeConfig));
6636
+ this.model.ports.types.add(portType);
6637
+ }
6638
+ }
5991
6639
  // load connection types
5992
6640
  if (config.connectionTypes) {
5993
6641
  for (const connectionTypeConfig of config.connectionTypes) {
@@ -6240,9 +6888,10 @@ class DiagramCanvas {
6240
6888
  }
6241
6889
  }
6242
6890
  center() {
6891
+ var _a;
6243
6892
  // if there are no nodes, we have nothing to do here
6244
6893
  if (this.model.nodes.length > 0) {
6245
- const canvasViewBoundingBox = this.selectCanvasView().select('rect').node().getBBox();
6894
+ const canvasViewBoundingBox = (_a = this.selectCanvasView().select('rect').node()) === null || _a === undefined ? undefined : _a.getBBox();
6246
6895
  const nonRemovedNodes = this.model.nodes.all();
6247
6896
  const minimumX = Math.min(...nonRemovedNodes.map(n => n.coords[0]));
6248
6897
  const maximumX = Math.max(...nonRemovedNodes.map(n => n.coords[0] + n.width));
@@ -6319,7 +6968,7 @@ class DiagramCanvas {
6319
6968
  updateNodesInView(...ids) {
6320
6969
  let updateSelection = this.selectCanvasElements().selectAll('g.diagram-node').data(this.model.nodes.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
6321
6970
  const exitSelection = updateSelection.exit();
6322
- const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', d => `diagram-node${d.type.resizableX ? ' resizable-x' : ''}${d.type.resizableY ? ' resizable-y' : ''} ${d.type.look.lookType}`);
6971
+ const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', d => `diagram-node${d.type.resizableX ? ' resizable-x' : ''}${d.type.resizableY ? ' resizable-y' : ''} ${d.type.defaultLook.lookType}`);
6323
6972
  if (ids && ids.length > 0) {
6324
6973
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
6325
6974
  }
@@ -6381,17 +7030,7 @@ class DiagramCanvas {
6381
7030
  }
6382
7031
  this.secondaryButton = false;
6383
7032
  }));
6384
- enterSelection.filter('.shaped-look').append('path');
6385
- enterSelection.filter('.image-look').append('image').attr('preserveAspectRatio', 'none');
6386
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'top-left-image').attr('preserveAspectRatio', 'none');
6387
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'top-image').attr('preserveAspectRatio', 'none');
6388
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'top-right-image').attr('preserveAspectRatio', 'none');
6389
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'left-image').attr('preserveAspectRatio', 'none');
6390
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'center-image').attr('preserveAspectRatio', 'none');
6391
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'right-image').attr('preserveAspectRatio', 'none');
6392
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'bottom-left-image').attr('preserveAspectRatio', 'none');
6393
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'bottom-image').attr('preserveAspectRatio', 'none');
6394
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'bottom-right-image').attr('preserveAspectRatio', 'none');
7033
+ initializeLook(enterSelection);
6395
7034
  enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(exports.Events.MouseOver, (_event, d) => {
6396
7035
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.type.resizableX && !d.removed) {
6397
7036
  setCursorStyle(exports.CursorStyle.EWResize);
@@ -6529,17 +7168,7 @@ class DiagramCanvas {
6529
7168
  setCursorStyle();
6530
7169
  }));
6531
7170
  mergeSelection.attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).attr('opacity', d => d.removed ? 0.5 : 1);
6532
- mergeSelection.filter('.shaped-look').select('path').attr('d', d => generalClosedPath(d.type.look.shape, 0, 0, d.width, d.height)).attr('fill', d => d.selected ? d.type.look.selectedFillColor : d.type.look.fillColor).attr('stroke', d => d.selected ? d.type.look.selectedBorderColor : d.type.look.borderColor).attr('stroke-width', d => `${d.highlighted ? 3 : 1}px`);
6533
- mergeSelection.filter('.image-look').select('image').attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('href', d => d.selected ? d.type.look.selectedBackgroundImage : d.type.look.backgroundImage);
6534
- mergeSelection.filter('.stretchable-image-look').select('image.top-left-image').attr('x', 0).attr('y', 0).attr('width', d => d.type.look.leftMargin).attr('height', d => d.type.look.topMargin).attr('href', d => d.selected ? d.type.look.selectedBackgroundImageTopLeft : d.type.look.backgroundImageTopLeft);
6535
- mergeSelection.filter('.stretchable-image-look').select('image.top-image').attr('x', d => d.type.look.leftMargin).attr('y', 0).attr('width', d => d.width - d.type.look.rightMargin - d.type.look.leftMargin).attr('height', d => d.type.look.topMargin).attr('href', d => d.selected ? d.type.look.selectedBackgroundImageTop : d.type.look.backgroundImageTop);
6536
- mergeSelection.filter('.stretchable-image-look').select('image.top-right-image').attr('x', d => d.width - d.type.look.rightMargin).attr('y', 0).attr('width', d => d.type.look.rightMargin).attr('height', d => d.type.look.topMargin).attr('href', d => d.selected ? d.type.look.selectedBackgroundImageTopRight : d.type.look.backgroundImageTopRight);
6537
- mergeSelection.filter('.stretchable-image-look').select('image.left-image').attr('x', 0).attr('y', d => d.type.look.topMargin).attr('width', d => d.type.look.leftMargin).attr('height', d => d.height - d.type.look.bottomMargin - d.type.look.topMargin).attr('href', d => d.selected ? d.type.look.selectedBackgroundImageLeft : d.type.look.backgroundImageLeft);
6538
- mergeSelection.filter('.stretchable-image-look').select('image.center-image').attr('x', d => d.type.look.leftMargin).attr('y', d => d.type.look.topMargin).attr('width', d => d.width - d.type.look.rightMargin - d.type.look.leftMargin).attr('height', d => d.height - d.type.look.bottomMargin - d.type.look.topMargin).attr('href', d => d.selected ? d.type.look.selectedBackgroundImageCenter : d.type.look.backgroundImageCenter);
6539
- mergeSelection.filter('.stretchable-image-look').select('image.right-image').attr('x', d => d.width - d.type.look.rightMargin).attr('y', d => d.type.look.topMargin).attr('width', d => d.type.look.rightMargin).attr('height', d => d.height - d.type.look.bottomMargin - d.type.look.topMargin).attr('href', d => d.selected ? d.type.look.selectedBackgroundImageRight : d.type.look.backgroundImageRight);
6540
- mergeSelection.filter('.stretchable-image-look').select('image.bottom-left-image').attr('x', 0).attr('y', d => d.height - d.type.look.bottomMargin).attr('width', d => d.type.look.leftMargin).attr('height', d => d.type.look.bottomMargin).attr('href', d => d.selected ? d.type.look.selectedBackgroundImageBottomLeft : d.type.look.backgroundImageBottomLeft);
6541
- mergeSelection.filter('.stretchable-image-look').select('image.bottom-image').attr('x', d => d.type.look.leftMargin).attr('y', d => d.height - d.type.look.bottomMargin).attr('width', d => d.width - d.type.look.rightMargin - d.type.look.leftMargin).attr('height', d => d.type.look.bottomMargin).attr('href', d => d.selected ? d.type.look.selectedBackgroundImageBottom : d.type.look.backgroundImageBottom);
6542
- mergeSelection.filter('.stretchable-image-look').select('image.bottom-right-image').attr('x', d => d.width - d.type.look.rightMargin).attr('y', d => d.height - d.type.look.bottomMargin).attr('width', d => d.type.look.rightMargin).attr('height', d => d.type.look.bottomMargin).attr('href', d => d.selected ? d.type.look.selectedBackgroundImageBottomRight : d.type.look.backgroundImageBottomRight);
7171
+ updateLook(mergeSelection);
6543
7172
  mergeSelection.filter('.resizable-x').select('line.left-resizer').attr('x1', RESIZER_THICKNESS / 2).attr('x2', RESIZER_THICKNESS / 2).attr('y1', 0).attr('y2', d => d.height);
6544
7173
  mergeSelection.filter('.resizable-y').select('line.top-resizer').attr('x1', 0).attr('x2', d => d.width).attr('y1', RESIZER_THICKNESS / 2).attr('y2', RESIZER_THICKNESS / 2);
6545
7174
  mergeSelection.filter('.resizable-x').select('line.right-resizer').attr('x1', d => d.width - RESIZER_THICKNESS / 2).attr('x2', d => d.width - RESIZER_THICKNESS / 2).attr('y1', 0).attr('y2', d => d.height);
@@ -6549,8 +7178,8 @@ class DiagramCanvas {
6549
7178
  let updateSelection = this.selectCanvasElements().selectAll('g.diagram-section').data(this.model.sections.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
6550
7179
  const exitSelection = updateSelection.exit();
6551
7180
  const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', d => {
6552
- var _a, _b, _c, _d, _e, _f;
6553
- return `diagram-section${((_b = (_a = d.node) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.resizableX) ? ' resizable-x' : ''}${((_d = (_c = d.node) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.resizableY) ? ' resizable-y' : ''} ${(_f = (_e = d.getConfig()) === null || _e === undefined ? undefined : _e.look) === null || _f === undefined ? undefined : _f.lookType}`;
7181
+ var _a, _b, _c, _d, _e;
7182
+ return `diagram-section${((_b = (_a = d.node) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.resizableX) ? ' resizable-x' : ''}${((_d = (_c = d.node) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.resizableY) ? ' resizable-y' : ''} ${(_e = d.look) === null || _e === undefined ? undefined : _e.lookType}`;
6554
7183
  });
6555
7184
  if (ids && ids.length > 0) {
6556
7185
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
@@ -6630,17 +7259,7 @@ class DiagramCanvas {
6630
7259
  }
6631
7260
  this.secondaryButton = false;
6632
7261
  }));
6633
- enterSelection.filter('.shaped-look').append('path');
6634
- enterSelection.filter('.image-look').append('image').attr('preserveAspectRatio', 'none');
6635
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'top-left-image').attr('preserveAspectRatio', 'none');
6636
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'top-image').attr('preserveAspectRatio', 'none');
6637
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'top-right-image').attr('preserveAspectRatio', 'none');
6638
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'left-image').attr('preserveAspectRatio', 'none');
6639
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'center-image').attr('preserveAspectRatio', 'none');
6640
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'right-image').attr('preserveAspectRatio', 'none');
6641
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'bottom-left-image').attr('preserveAspectRatio', 'none');
6642
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'bottom-image').attr('preserveAspectRatio', 'none');
6643
- enterSelection.filter('.stretchable-image-look').append('image').attr('class', 'bottom-right-image').attr('preserveAspectRatio', 'none');
7262
+ initializeLook(enterSelection);
6644
7263
  enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(exports.Events.MouseOver, (_event, d) => {
6645
7264
  var _a, _b;
6646
7265
  if (this.canUserPerformAction(exports.DiagramActions.StretchSection) && ((_b = (_a = d.node) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.resizableX) && !d.removed) {
@@ -6798,146 +7417,7 @@ class DiagramCanvas {
6798
7417
  setCursorStyle();
6799
7418
  }));
6800
7419
  mergeSelection.attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).attr('opacity', d => d.removed ? 0.5 : 1);
6801
- mergeSelection.filter('.shaped-look').select('path').attr('d', d => {
6802
- var _a;
6803
- return generalClosedPath(((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).shape, 0, 0, d.width, d.height);
6804
- }).attr('fill', d => {
6805
- var _a, _b;
6806
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedFillColor : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).fillColor;
6807
- }).attr('stroke', d => {
6808
- var _a, _b;
6809
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBorderColor : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).borderColor;
6810
- }).attr('stroke-width', d => `${d.highlighted ? 3 : 1}px`);
6811
- mergeSelection.filter('.image-look').select('image').attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('href', d => {
6812
- var _a, _b;
6813
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImage : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).backgroundImage;
6814
- });
6815
- mergeSelection.filter('.stretchable-image-look').select('image.top-left-image').attr('x', 0).attr('y', 0).attr('width', d => {
6816
- var _a;
6817
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).leftMargin;
6818
- }).attr('height', d => {
6819
- var _a;
6820
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).topMargin;
6821
- }).attr('href', d => {
6822
- var _a, _b;
6823
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImageTopLeft : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).backgroundImageTopLeft;
6824
- });
6825
- mergeSelection.filter('.stretchable-image-look').select('image.top-image').attr('x', d => {
6826
- var _a;
6827
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).leftMargin;
6828
- }).attr('y', 0).attr('width', d => {
6829
- var _a, _b;
6830
- return d.width - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).rightMargin - ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).leftMargin;
6831
- }).attr('height', d => {
6832
- var _a;
6833
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).topMargin;
6834
- }).attr('href', d => {
6835
- var _a, _b;
6836
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImageTop : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).backgroundImageTop;
6837
- });
6838
- mergeSelection.filter('.stretchable-image-look').select('image.top-right-image').attr('x', d => {
6839
- var _a;
6840
- return d.width - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).rightMargin;
6841
- }).attr('y', 0).attr('width', d => {
6842
- var _a;
6843
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).rightMargin;
6844
- }).attr('height', d => {
6845
- var _a;
6846
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).topMargin;
6847
- }).attr('href', d => {
6848
- var _a, _b;
6849
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImageTopRight : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).backgroundImageTopRight;
6850
- });
6851
- mergeSelection.filter('.stretchable-image-look').select('image.left-image').attr('x', 0).attr('y', d => {
6852
- var _a;
6853
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).topMargin;
6854
- }).attr('width', d => {
6855
- var _a;
6856
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).leftMargin;
6857
- }).attr('height', d => {
6858
- var _a, _b;
6859
- return d.height - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).bottomMargin - ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).topMargin;
6860
- }).attr('href', d => {
6861
- var _a, _b;
6862
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImageLeft : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).backgroundImageLeft;
6863
- });
6864
- mergeSelection.filter('.stretchable-image-look').select('image.center-image').attr('x', d => {
6865
- var _a;
6866
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).leftMargin;
6867
- }).attr('y', d => {
6868
- var _a;
6869
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).topMargin;
6870
- }).attr('width', d => {
6871
- var _a, _b;
6872
- return d.width - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).rightMargin - ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).leftMargin;
6873
- }).attr('height', d => {
6874
- var _a, _b;
6875
- return d.height - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).bottomMargin - ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).topMargin;
6876
- }).attr('href', d => {
6877
- var _a, _b;
6878
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImageCenter : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).backgroundImageCenter;
6879
- });
6880
- mergeSelection.filter('.stretchable-image-look').select('image.right-image').attr('x', d => {
6881
- var _a;
6882
- return d.width - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).rightMargin;
6883
- }).attr('y', d => {
6884
- var _a;
6885
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).topMargin;
6886
- }).attr('width', d => {
6887
- var _a;
6888
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).rightMargin;
6889
- }).attr('height', d => {
6890
- var _a, _b;
6891
- return d.height - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).bottomMargin - ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).topMargin;
6892
- }).attr('href', d => {
6893
- var _a, _b;
6894
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImageRight : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).backgroundImageRight;
6895
- });
6896
- mergeSelection.filter('.stretchable-image-look').select('image.bottom-left-image').attr('x', 0).attr('y', d => {
6897
- var _a;
6898
- return d.height - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).bottomMargin;
6899
- }).attr('width', d => {
6900
- var _a;
6901
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).leftMargin;
6902
- }).attr('height', d => {
6903
- var _a;
6904
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).bottomMargin;
6905
- }).attr('href', d => {
6906
- var _a, _b;
6907
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImageBottomLeft : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).backgroundImageBottomLeft;
6908
- });
6909
- mergeSelection.filter('.stretchable-image-look').select('image.bottom-image').attr('x', d => {
6910
- var _a;
6911
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).leftMargin;
6912
- }).attr('y', d => {
6913
- var _a;
6914
- return d.height - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).bottomMargin;
6915
- }).attr('width', d => {
6916
- var _a, _b;
6917
- return d.width - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).rightMargin - ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).leftMargin;
6918
- }).attr('height', d => {
6919
- var _a;
6920
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).bottomMargin;
6921
- }).attr('href', d => {
6922
- var _a, _b;
6923
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImageBottom : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).backgroundImageBottom;
6924
- });
6925
- mergeSelection.filter('.stretchable-image-look').select('image.bottom-right-image').attr('x', d => {
6926
- var _a;
6927
- return d.width - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).rightMargin;
6928
- }).attr('y', d => {
6929
- var _a;
6930
- return d.height - ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).bottomMargin;
6931
- }).attr('width', d => {
6932
- var _a;
6933
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).rightMargin;
6934
- }).attr('height', d => {
6935
- var _a;
6936
- return ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).bottomMargin;
6937
- }).attr('href', d => {
6938
- var _a, _b;
6939
- return d.selected ? ((_a = d.getConfig()) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImageBottomRight : ((_b = d.getConfig()) === null || _b === undefined ? undefined : _b.look).backgroundImageBottomRight;
6940
- });
7420
+ updateLook(mergeSelection);
6941
7421
  mergeSelection.filter('.resizable-x').select('line.left-resizer').attr('x1', RESIZER_THICKNESS / 2).attr('x2', RESIZER_THICKNESS / 2).attr('y1', 0).attr('y2', d => d.height);
6942
7422
  mergeSelection.filter('.resizable-y').select('line.top-resizer').attr('x1', 0).attr('x2', d => d.width).attr('y1', RESIZER_THICKNESS / 2).attr('y2', RESIZER_THICKNESS / 2);
6943
7423
  mergeSelection.filter('.resizable-x').select('line.right-resizer').attr('x1', d => d.width - RESIZER_THICKNESS / 2).attr('x2', d => d.width - RESIZER_THICKNESS / 2).attr('y1', 0).attr('y2', d => d.height);
@@ -6946,21 +7426,29 @@ class DiagramCanvas {
6946
7426
  updatePortsInView(...ids) {
6947
7427
  let updateSelection = this.selectCanvasElements().selectAll('g.diagram-port').data(this.model.ports.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
6948
7428
  const exitSelection = updateSelection.exit();
6949
- const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', 'diagram-port');
7429
+ const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', d => `diagram-port ${d.look.lookType}`);
6950
7430
  if (ids && ids.length > 0) {
6951
7431
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
6952
7432
  }
6953
7433
  const mergeSelection = enterSelection.merge(updateSelection);
6954
7434
  exitSelection.remove();
6955
7435
  enterSelection.on(exports.Events.MouseOver, (_event, d) => {
6956
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
7436
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
6957
7437
  if (!this.unfinishedConnection && !this.dragging) {
6958
7438
  // if there is an unfinished connection, the port will be highlighted automatically if the pointer is close
6959
7439
  this.userHighlight.focusOn(d);
6960
7440
  this.diagramEvent$.next(new DiagramHighlightedEvent(d));
6961
7441
  }
6962
7442
  if (this.unfinishedConnection) {
6963
- const canConnectionFinishAtThisPort = this.unfinishedConnection.type.canStartFromType(((_c = (_b = (_a = this.unfinishedConnection.start) === null || _a === undefined ? undefined : _a.getNode()) === null || _b === undefined ? undefined : _b.type) === null || _c === undefined ? undefined : _c.id) || '') && this.unfinishedConnection.type.canFinishOnType(((_e = (_d = d.getNode()) === null || _d === undefined ? undefined : _d.type) === null || _e === undefined ? undefined : _e.id) || '') || this.unfinishedConnection.type.canStartFromType(((_g = (_f = d.getNode()) === null || _f === undefined ? undefined : _f.type) === null || _g === undefined ? undefined : _g.id) || '') && this.unfinishedConnection.type.canFinishOnType(((_k = (_j = (_h = this.unfinishedConnection.start) === null || _h === undefined ? undefined : _h.getNode()) === null || _j === undefined ? undefined : _j.type) === null || _k === undefined ? undefined : _k.id) || '');
7443
+ const canConnectionFinishAtThisPort =
7444
+ // can start at the starting port
7445
+ this.unfinishedConnection.type.canStartFromType(((_c = (_b = (_a = this.unfinishedConnection.start) === null || _a === undefined ? undefined : _a.getNode()) === null || _b === undefined ? undefined : _b.type) === null || _c === undefined ? undefined : _c.id) || '') && ((_d = this.unfinishedConnection.start) === null || _d === undefined ? undefined : _d.allowsOutgoing) &&
7446
+ // can end at the ending port
7447
+ this.unfinishedConnection.type.canFinishOnType(((_f = (_e = d.getNode()) === null || _e === undefined ? undefined : _e.type) === null || _f === undefined ? undefined : _f.id) || '') && d.allowsIncoming ||
7448
+ // can start at the ending port
7449
+ this.unfinishedConnection.type.canStartFromType(((_h = (_g = d.getNode()) === null || _g === undefined ? undefined : _g.type) === null || _h === undefined ? undefined : _h.id) || '') && d.allowsOutgoing &&
7450
+ // can end at the starting port
7451
+ this.unfinishedConnection.type.canFinishOnType(((_l = (_k = (_j = this.unfinishedConnection.start) === null || _j === undefined ? undefined : _j.getNode()) === null || _k === undefined ? undefined : _k.type) === null || _l === undefined ? undefined : _l.id) || '') && ((_m = this.unfinishedConnection.start) === null || _m === undefined ? undefined : _m.allowsIncoming);
6964
7452
  if (!canConnectionFinishAtThisPort) {
6965
7453
  setCursorStyle(exports.CursorStyle.NoDrop);
6966
7454
  }
@@ -7025,7 +7513,7 @@ class DiagramCanvas {
7025
7513
  if (this.canUserPerformAction(exports.DiagramActions.AddConnection) && !d.removed) {
7026
7514
  if (this.unfinishedConnection !== undefined) {
7027
7515
  const endCoords = [event.x, event.y];
7028
- (_a = this.unfinishedConnectionTracer) === null || _a === undefined ? undefined : _a.attr('d', getConnectionPath(this.unfinishedConnection.type.shape, this.unfinishedConnection.startCoords, endCoords, this.unfinishedConnection.startDirection, this.unfinishedConnection.endDirection, this.unfinishedConnection.type.width, (_b = this.unfinishedConnection.startMarkerLook) === null || _b === undefined ? undefined : _b.markerWidth, (_c = this.unfinishedConnection.endMarkerLook) === null || _c === undefined ? undefined : _c.markerWidth));
7516
+ (_a = this.unfinishedConnectionTracer) === null || _a === undefined ? undefined : _a.attr('d', getConnectionPath(this.unfinishedConnection.look.shape, this.unfinishedConnection.startCoords, endCoords, this.unfinishedConnection.startDirection, this.unfinishedConnection.endDirection, this.unfinishedConnection.look.thickness, (_b = this.unfinishedConnection.startMarkerLook) === null || _b === undefined ? undefined : _b.width, (_c = this.unfinishedConnection.endMarkerLook) === null || _c === undefined ? undefined : _c.width));
7029
7517
  const unfinishedConnectionGhostNode = (_d = this.unfinishedConnectionTracer) === null || _d === undefined ? undefined : _d.node();
7030
7518
  if (unfinishedConnectionGhostNode) {
7031
7519
  let margin = 2;
@@ -7097,8 +7585,10 @@ class DiagramCanvas {
7097
7585
  }
7098
7586
  this.secondaryButton = false;
7099
7587
  }));
7100
- enterSelection.append('circle');
7101
- mergeSelection.attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).attr('opacity', d => d.removed ? 0.5 : 1).select('circle').attr('cx', 0).attr('cy', 0).attr('r', DIAGRAM_PORT_DEFAULTS.radius).attr('fill', d => d.selected ? DIAGRAM_PORT_DEFAULTS.selectedColor : DIAGRAM_PORT_DEFAULTS.highlightedColor).attr('opacity', d => d.highlighted || d.selected ? 0.5 : 0);
7588
+ enterSelection.filter('.image-look').append('image');
7589
+ initializeLook(enterSelection);
7590
+ mergeSelection.attr('transform', d => `translate(${d.coords[0] - d.width / 2},${d.coords[1] - d.width / 2})`).attr('opacity', d => d.removed ? 0.5 : 1);
7591
+ updateLook(mergeSelection);
7102
7592
  }
7103
7593
  updateConnectionsInView(...ids) {
7104
7594
  const connectionList = this.model.connections.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true);
@@ -7171,14 +7661,14 @@ class DiagramCanvas {
7171
7661
  enterSelection.select('g.diagram-connection-end-label').append('text').style('user-select', 'none');
7172
7662
  mergeSelection.attr('opacity', d => d.removed ? 0.5 : 1).select('path.diagram-connection-path').attr('d', d => {
7173
7663
  var _a, _b;
7174
- return getConnectionPath(d.type.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.type.width, (_a = d.startMarkerLook) === null || _a === undefined ? undefined : _a.markerWidth, (_b = d.endMarkerLook) === null || _b === undefined ? undefined : _b.markerWidth);
7175
- }).attr('marker-start', d => `url(#${d.id}-start-marker)`).attr('marker-end', d => `url(#${d.id}-end-marker)`).attr('stroke', d => d.selected ? d.type.selectedColor : d.type.color).attr('stroke-width', d => `${d.highlighted ? d.type.width + 1 : d.type.width}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.type.style, d.type.width)).attr('fill', 'none');
7664
+ return getConnectionPath(d.look.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.look.thickness, (_a = d.startMarkerLook) === null || _a === undefined ? undefined : _a.width, (_b = d.endMarkerLook) === null || _b === undefined ? undefined : _b.width);
7665
+ }).attr('marker-start', d => `url(#${d.id}-start-marker)`).attr('marker-end', d => `url(#${d.id}-end-marker)`).attr('stroke', d => d.look.color).attr('stroke-width', d => `${d.look.thickness}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style, d.look.thickness)).attr('fill', 'none');
7176
7666
  mergeSelection.select('path.diagram-connection-path-box').attr('d', d => {
7177
7667
  var _a, _b;
7178
- return getConnectionPath(d.type.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.type.width, (_a = d.startMarkerLook) === null || _a === undefined ? undefined : _a.markerWidth, (_b = d.endMarkerLook) === null || _b === undefined ? undefined : _b.markerWidth);
7668
+ return getConnectionPath(d.look.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.look.thickness, (_a = d.startMarkerLook) === null || _a === undefined ? undefined : _a.width, (_b = d.endMarkerLook) === null || _b === undefined ? undefined : _b.width);
7179
7669
  }).attr('stroke', 'transparent')
7180
7670
  // allow generating pointer events even when it is transparent
7181
- .attr('pointer-events', 'stroke').attr('stroke-width', d => `${d.type.width + CONNECTION_PATH_BOX_THICKNESS}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.type.style, d.type.width)).attr('fill', 'none');
7671
+ .attr('pointer-events', 'stroke').attr('stroke-width', d => `${d.look.thickness + CONNECTION_PATH_BOX_THICKNESS}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style, d.look.thickness)).attr('fill', 'none');
7182
7672
  mergeSelection.data().forEach(connection => {
7183
7673
  this.updateConnectionLabelsInView(connection);
7184
7674
  this.updateConnectionMarkersInView(connection);
@@ -7387,7 +7877,7 @@ class DiagramCanvas {
7387
7877
  const boundingWidth = !connection.startLabel ? 0 : startLabelBoundingRect.width / this.zoomTransform.k + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
7388
7878
  const boundingHeight = !connection.startLabel ? 0 : startLabelBoundingRect.height / this.zoomTransform.k + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
7389
7879
  const pathStartLabelPoint = pathNode.getPointAtLength(Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
7390
- connectionSelection.select('g.diagram-connection-start-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', connection.selected ? connection.type.selectedColor : connection.type.color).attr('stroke', 'none');
7880
+ connectionSelection.select('g.diagram-connection-start-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', connection.look.color).attr('stroke', 'none');
7391
7881
  connectionSelection.select('g.diagram-connection-start-label').attr('transform', `translate(${pathStartLabelPoint.x},${pathStartLabelPoint.y})`);
7392
7882
  }
7393
7883
  // bind middle labels
@@ -7398,7 +7888,7 @@ class DiagramCanvas {
7398
7888
  const boundingWidth = !connection.middleLabel ? 0 : middleLabelBoundingRect.width / this.zoomTransform.k + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
7399
7889
  const boundingHeight = !connection.middleLabel ? 0 : middleLabelBoundingRect.height / this.zoomTransform.k + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
7400
7890
  const pathMiddleLabelPoint = pathNode.getPointAtLength(pathLength / 2);
7401
- connectionSelection.select('g.diagram-connection-middle-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', connection.selected ? connection.type.selectedColor : connection.type.color).attr('stroke', 'none');
7891
+ connectionSelection.select('g.diagram-connection-middle-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', connection.look.color).attr('stroke', 'none');
7402
7892
  connectionSelection.select('g.diagram-connection-middle-label').attr('transform', `translate(${pathMiddleLabelPoint.x},${pathMiddleLabelPoint.y})`);
7403
7893
  }
7404
7894
  // bind end labels
@@ -7409,7 +7899,7 @@ class DiagramCanvas {
7409
7899
  const boundingWidth = !connection.endLabel ? 0 : endLabelBoundingRect.width / this.zoomTransform.k + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
7410
7900
  const boundingHeight = !connection.endLabel ? 0 : endLabelBoundingRect.height / this.zoomTransform.k + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
7411
7901
  const pathEndLabelPoint = pathNode.getPointAtLength(pathLength - Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
7412
- connectionSelection.select('g.diagram-connection-end-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', connection.selected ? connection.type.selectedColor : connection.type.color).attr('stroke', 'none');
7902
+ connectionSelection.select('g.diagram-connection-end-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', connection.look.color).attr('stroke', 'none');
7413
7903
  connectionSelection.select('g.diagram-connection-end-label').attr('transform', `translate(${pathEndLabelPoint.x},${pathEndLabelPoint.y})`);
7414
7904
  }
7415
7905
  }
@@ -7419,18 +7909,18 @@ class DiagramCanvas {
7419
7909
  const startMarkerSelection = connectionSelection.select('marker.diagram-connection-start-marker');
7420
7910
  const endMarkerSelection = connectionSelection.select('marker.diagram-connection-end-marker');
7421
7911
  if (connection.startMarkerLook !== null) {
7422
- startMarkerSelection.attr('orient', 'auto-start-reverse').attr('markerWidth', connection.startMarkerLook.markerWidth).attr('markerHeight', connection.startMarkerLook.markerHeight).attr('refX', connection.startMarkerLook.markerRefX).attr('refY', connection.startMarkerLook.markerRefY).select('image').attr('href', connection.selected ? connection.startMarkerLook.selectedImage : connection.startMarkerLook.image).attr('width', connection.startMarkerLook.markerWidth).attr('height', connection.startMarkerLook.markerHeight);
7912
+ startMarkerSelection.attr('orient', 'auto-start-reverse').attr('markerWidth', connection.startMarkerLook.width).attr('markerHeight', connection.startMarkerLook.height).attr('refX', connection.startMarkerLook.refX).attr('refY', connection.startMarkerLook.refY).select('image').attr('href', connection.startMarkerLook.image).attr('width', connection.startMarkerLook.width).attr('height', connection.startMarkerLook.height);
7423
7913
  } else {
7424
7914
  startMarkerSelection.attr('orient', 'auto-start-reverse').attr('markerWidth', 0).attr('markerHeight', 0);
7425
7915
  }
7426
7916
  if (connection.endMarkerLook !== null) {
7427
- endMarkerSelection.attr('orient', 'auto-start-reverse').attr('markerWidth', connection.endMarkerLook.markerWidth).attr('markerHeight', connection.endMarkerLook.markerHeight).attr('refX', connection.endMarkerLook.markerRefX).attr('refY', connection.endMarkerLook.markerRefY).select('image').attr('href', connection.selected ? connection.endMarkerLook.selectedImage : connection.endMarkerLook.image).attr('width', connection.endMarkerLook.markerWidth).attr('height', connection.endMarkerLook.markerHeight);
7917
+ endMarkerSelection.attr('orient', 'auto-start-reverse').attr('markerWidth', connection.endMarkerLook.width).attr('markerHeight', connection.endMarkerLook.height).attr('refX', connection.endMarkerLook.refX).attr('refY', connection.endMarkerLook.refY).select('image').attr('href', connection.endMarkerLook.image).attr('width', connection.endMarkerLook.width).attr('height', connection.endMarkerLook.height);
7428
7918
  } else {
7429
7919
  endMarkerSelection.attr('orient', 'auto-start-reverse').attr('markerWidth', 0).attr('markerHeight', 0);
7430
7920
  }
7431
7921
  }
7432
7922
  fitFieldRootInView(id) {
7433
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
7923
+ var _a, _b, _c;
7434
7924
  const field = this.model.fields.get(id);
7435
7925
  if (!field) {
7436
7926
  return;
@@ -7472,8 +7962,9 @@ class DiagramCanvas {
7472
7962
  if (fieldDimensions[1] < minimumFieldHeight) {
7473
7963
  fieldDimensions[1] = minimumFieldHeight;
7474
7964
  }
7475
- let stretchX = fieldDimensions[0] + getLeftMargin((_c = (_b = field.rootElement) === null || _b === undefined ? undefined : _b.getConfig()) === null || _c === undefined ? undefined : _c.label) + getRightMargin((_e = (_d = field.rootElement) === null || _d === undefined ? undefined : _d.getConfig()) === null || _e === undefined ? undefined : _e.label) - field.rootElement.width;
7476
- let stretchY = fieldDimensions[1] + getTopMargin((_g = (_f = field.rootElement) === null || _f === undefined ? undefined : _f.getConfig()) === null || _g === undefined ? undefined : _g.label) + getBottomMargin((_j = (_h = field.rootElement) === null || _h === undefined ? undefined : _h.getConfig()) === null || _j === undefined ? undefined : _j.label) - field.rootElement.height;
7965
+ const type = field.rootElement.type;
7966
+ let stretchX = fieldDimensions[0] + getLeftMargin(type === null || type === undefined ? undefined : type.label) + getRightMargin(type === null || type === undefined ? undefined : type.label) - field.rootElement.width;
7967
+ let stretchY = fieldDimensions[1] + getTopMargin(type === null || type === undefined ? undefined : type.label) + getBottomMargin(type === null || type === undefined ? undefined : type.label) - field.rootElement.height;
7477
7968
  if (this.snapToGrid) {
7478
7969
  stretchX = Math.ceil(stretchX / this.gridSize) * this.gridSize;
7479
7970
  stretchY = Math.ceil(stretchY / this.gridSize) * this.gridSize;
@@ -7485,8 +7976,8 @@ class DiagramCanvas {
7485
7976
  if (field.rootElement.height + stretchY < (field.rootElement.getMinHeight() || 0)) {
7486
7977
  stretchY = (field.rootElement.getMinHeight() || 0) - field.rootElement.height;
7487
7978
  }
7488
- (_k = field.rootElement.node) === null || _k === undefined ? undefined : _k.stretchSections(exports.Side.Right, stretchX, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
7489
- (_l = field.rootElement.node) === null || _l === undefined ? undefined : _l.stretchSections(exports.Side.Bottom, stretchY, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
7979
+ (_b = field.rootElement.node) === null || _b === undefined ? undefined : _b.stretchSections(exports.Side.Right, stretchX, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
7980
+ (_c = field.rootElement.node) === null || _c === undefined ? undefined : _c.stretchSections(exports.Side.Bottom, stretchY, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
7490
7981
  }
7491
7982
  }
7492
7983
  fitNodeInView(id) {
@@ -7529,39 +8020,41 @@ class DiagramCanvas {
7529
8020
  // User actions
7530
8021
  startConnection(port) {
7531
8022
  var _a, _b, _c, _d;
7532
- if (this.connectionType && (this.connectionType.canStartFromType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '') || this.connectionType.canFinishOnType(((_d = (_c = port.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || ''))) {
7533
- this.unfinishedConnection = new DiagramConnection(this.model, this.connectionType, port, undefined, UNFINISHED_CONNECTION_ID);
7534
- } else {
7535
- if (this.inferConnectionType) {
7536
- let differentConnectionType = this.model.connections.types.all().find(t => {
7537
- var _a, _b;
7538
- return t.canStartFromType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '');
7539
- });
7540
- if (differentConnectionType === undefined) {
7541
- differentConnectionType = this.model.connections.types.all().find(t => {
8023
+ if (port.allowsOutgoing || port.allowsIncoming) {
8024
+ if (this.connectionType && (this.connectionType.canStartFromType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '') && port.allowsOutgoing || this.connectionType.canFinishOnType(((_d = (_c = port.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && port.allowsIncoming)) {
8025
+ this.unfinishedConnection = new DiagramConnection(this.model, this.connectionType, port, undefined, UNFINISHED_CONNECTION_ID);
8026
+ } else {
8027
+ if (this.inferConnectionType) {
8028
+ let differentConnectionType = this.model.connections.types.all().find(t => {
7542
8029
  var _a, _b;
7543
- return t.canFinishOnType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '');
8030
+ return port.allowsOutgoing && t.canStartFromType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '');
7544
8031
  });
7545
- }
7546
- if (differentConnectionType !== undefined) {
7547
- this.unfinishedConnection = new DiagramConnection(this.model, differentConnectionType, port, undefined, UNFINISHED_CONNECTION_ID);
8032
+ if (differentConnectionType === undefined) {
8033
+ differentConnectionType = this.model.connections.types.all().find(t => {
8034
+ var _a, _b;
8035
+ return port.allowsIncoming && t.canFinishOnType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '');
8036
+ });
8037
+ }
8038
+ if (differentConnectionType !== undefined) {
8039
+ this.unfinishedConnection = new DiagramConnection(this.model, differentConnectionType, port, undefined, UNFINISHED_CONNECTION_ID);
8040
+ }
7548
8041
  }
7549
8042
  }
7550
8043
  }
7551
8044
  }
7552
8045
  finishConnection(port) {
7553
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
8046
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
7554
8047
  this.userHighlight.clear();
7555
8048
  if (this.unfinishedConnection !== undefined) {
7556
8049
  if (this.unfinishedConnection.start !== port) {
7557
- if (this.unfinishedConnection.type.canStartFromType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && this.unfinishedConnection.type.canFinishOnType(((_f = (_e = port.getNode()) === null || _e === undefined ? undefined : _e.type) === null || _f === undefined ? undefined : _f.id) || '')) {
7558
- const addConnectionAction = new AddConnectionAction(this, this.unfinishedConnection.type, (_g = this.unfinishedConnection.start) === null || _g === undefined ? undefined : _g.id, port.id);
8050
+ if (this.unfinishedConnection.type.canStartFromType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && ((_f = (_e = this.unfinishedConnection) === null || _e === undefined ? undefined : _e.start) === null || _f === undefined ? undefined : _f.allowsOutgoing) && this.unfinishedConnection.type.canFinishOnType(((_h = (_g = port.getNode()) === null || _g === undefined ? undefined : _g.type) === null || _h === undefined ? undefined : _h.id) || '') && port.allowsIncoming) {
8051
+ const addConnectionAction = new AddConnectionAction(this, this.unfinishedConnection.type, (_j = this.unfinishedConnection.start) === null || _j === undefined ? undefined : _j.id, port.id);
7559
8052
  // clean up the previous unfinished connection
7560
8053
  this.dropConnection();
7561
8054
  addConnectionAction.do();
7562
8055
  this.actionStack.add(addConnectionAction);
7563
- } else if (this.unfinishedConnection.type.canFinishOnType(((_l = (_k = (_j = (_h = this.unfinishedConnection) === null || _h === undefined ? undefined : _h.start) === null || _j === undefined ? undefined : _j.getNode()) === null || _k === undefined ? undefined : _k.type) === null || _l === undefined ? undefined : _l.id) || '') && this.unfinishedConnection.type.canStartFromType(((_o = (_m = port.getNode()) === null || _m === undefined ? undefined : _m.type) === null || _o === undefined ? undefined : _o.id) || '')) {
7564
- const addConnectionAction = new AddConnectionAction(this, this.unfinishedConnection.type, port.id, (_p = this.unfinishedConnection.start) === null || _p === undefined ? undefined : _p.id);
8056
+ } else if (this.unfinishedConnection.type.canFinishOnType(((_o = (_m = (_l = (_k = this.unfinishedConnection) === null || _k === undefined ? undefined : _k.start) === null || _l === undefined ? undefined : _l.getNode()) === null || _m === undefined ? undefined : _m.type) === null || _o === undefined ? undefined : _o.id) || '') && ((_q = (_p = this.unfinishedConnection) === null || _p === undefined ? undefined : _p.start) === null || _q === undefined ? undefined : _q.allowsIncoming) && this.unfinishedConnection.type.canStartFromType(((_s = (_r = port.getNode()) === null || _r === undefined ? undefined : _r.type) === null || _s === undefined ? undefined : _s.id) || '') && port.allowsOutgoing) {
8057
+ const addConnectionAction = new AddConnectionAction(this, this.unfinishedConnection.type, port.id, (_t = this.unfinishedConnection.start) === null || _t === undefined ? undefined : _t.id);
7565
8058
  // clean up the previous unfinished connection
7566
8059
  this.dropConnection();
7567
8060
  addConnectionAction.do();
@@ -7569,19 +8062,19 @@ class DiagramCanvas {
7569
8062
  } else {
7570
8063
  if (this.inferConnectionType) {
7571
8064
  let differentConnectionType = this.model.connections.types.all().find(t => {
7572
- var _a, _b, _c, _d, _e, _f;
7573
- return t.canStartFromType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && t.canFinishOnType(((_f = (_e = port.getNode()) === null || _e === undefined ? undefined : _e.type) === null || _f === undefined ? undefined : _f.id) || '');
8065
+ var _a, _b, _c, _d, _e, _f, _g, _h;
8066
+ return t.canStartFromType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && ((_f = (_e = this.unfinishedConnection) === null || _e === undefined ? undefined : _e.start) === null || _f === undefined ? undefined : _f.allowsOutgoing) && t.canFinishOnType(((_h = (_g = port.getNode()) === null || _g === undefined ? undefined : _g.type) === null || _h === undefined ? undefined : _h.id) || '') && port.allowsIncoming;
7574
8067
  });
7575
8068
  let invertConnection = false;
7576
8069
  if (differentConnectionType === undefined) {
7577
8070
  differentConnectionType = this.model.connections.types.all().find(t => {
7578
- var _a, _b, _c, _d, _e, _f;
7579
- return t.canFinishOnType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && t.canStartFromType(((_f = (_e = port.getNode()) === null || _e === undefined ? undefined : _e.type) === null || _f === undefined ? undefined : _f.id) || '');
8071
+ var _a, _b, _c, _d, _e, _f, _g, _h;
8072
+ return t.canFinishOnType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && ((_f = (_e = this.unfinishedConnection) === null || _e === undefined ? undefined : _e.start) === null || _f === undefined ? undefined : _f.allowsIncoming) && t.canStartFromType(((_h = (_g = port.getNode()) === null || _g === undefined ? undefined : _g.type) === null || _h === undefined ? undefined : _h.id) || '') && port.allowsOutgoing;
7580
8073
  });
7581
8074
  invertConnection = true;
7582
8075
  }
7583
8076
  if (differentConnectionType !== undefined) {
7584
- const addConnectionAction = new AddConnectionAction(this, differentConnectionType, invertConnection ? port.id : (_q = this.unfinishedConnection.start) === null || _q === undefined ? undefined : _q.id, invertConnection ? (_r = this.unfinishedConnection.start) === null || _r === undefined ? undefined : _r.id : port.id);
8077
+ const addConnectionAction = new AddConnectionAction(this, differentConnectionType, invertConnection ? port.id : (_u = this.unfinishedConnection.start) === null || _u === undefined ? undefined : _u.id, invertConnection ? (_v = this.unfinishedConnection.start) === null || _v === undefined ? undefined : _v.id : port.id);
7585
8078
  // clean up the previous unfinished connection
7586
8079
  this.dropConnection();
7587
8080
  addConnectionAction.do();
@@ -7815,41 +8308,6 @@ class DiagramCanvas {
7815
8308
  }
7816
8309
  }
7817
8310
  DiagramCanvas.canvasCount = 0;
7818
- /**
7819
- * Checks if the given mouse event was produced with a secondary button press.
7820
- * @private
7821
- * @param event A mouse event.
7822
- * @returns `true` if the given mouse event was produced with a secondary button press, `false` otherwise.
7823
- */
7824
- const isSecondaryButton = event => {
7825
- return !!event.button;
7826
- };
7827
- /**
7828
- * Get the SVG path of a diagram connection.
7829
- * @private
7830
- * @see linePath
7831
- */
7832
- const getConnectionPath = (shape, startCoords, endCoords, startDirection, endDirection, width, startMarkerWidth, endMarkerWidth) => {
7833
- return linePath(shape, [startCoords, endCoords], startDirection, endDirection, Math.max(
7834
- // reasonable value for the minimumDistanceBeforeTurn relative to the line width
7835
- 10, startMarkerWidth || 0, endMarkerWidth || 0) * width);
7836
- };
7837
- const setCursorStyle = style => {
7838
- if (!style) {
7839
- d3__namespace.select('body').style('cursor', exports.CursorStyle.Auto);
7840
- } else {
7841
- d3__namespace.select('body').style('cursor', style);
7842
- }
7843
- };
7844
- const getRelatedNodeOrItself = element => {
7845
- if (element instanceof DiagramNode) {
7846
- return element;
7847
- }
7848
- if (element instanceof DiagramSection) {
7849
- return element.node || element;
7850
- }
7851
- return element.rootElement instanceof DiagramNode || element.rootElement instanceof DiagramSection || element.rootElement instanceof DiagramPort ? getRelatedNodeOrItself(element.rootElement) : element;
7852
- };
7853
8311
 
7854
8312
  const VERSION = '0.0.1';
7855
8313
  /**
@@ -8765,6 +9223,7 @@ exports.DiagramObject = DiagramObject;
8765
9223
  exports.DiagramObjectSet = DiagramObjectSet;
8766
9224
  exports.DiagramPort = DiagramPort;
8767
9225
  exports.DiagramPortSet = DiagramPortSet;
9226
+ exports.DiagramPortType = DiagramPortType;
8768
9227
  exports.DiagramSecondaryClickEvent = DiagramSecondaryClickEvent;
8769
9228
  exports.DiagramSection = DiagramSection;
8770
9229
  exports.DiagramSectionSet = DiagramSectionSet;