@elicdavis/node-flow 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +117 -101
- package/dist/index.d.ts +117 -101
- package/dist/index.js +349 -215
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +349 -215
- package/dist/index.mjs.map +1 -1
- package/index.html +46 -49
- package/package.json +1 -1
- package/src/graph.ts +7 -3
- package/src/input.ts +6 -8
- package/src/node.ts +98 -3
- package/src/port.ts +37 -2
- package/src/theme.ts +179 -179
- package/src/widgets/hidden_ports.ts +49 -0
- package/test/hidden_port.test.ts +6 -5
- package/test/hidden_ports_toggle.test.ts +102 -0
- package/test/pinch_zoom.test.ts +78 -0
package/dist/index.mjs
CHANGED
|
@@ -735,7 +735,7 @@ var ContextMenu = class _ContextMenu {
|
|
|
735
735
|
// src/input.ts
|
|
736
736
|
var LONG_PRESS_MS = 500;
|
|
737
737
|
var LONG_PRESS_SLOP = 12;
|
|
738
|
-
var
|
|
738
|
+
var WHEEL_ZOOM_PER_PIXEL = 5e-4;
|
|
739
739
|
var SUPPRESS_MOUSE_MS = 600;
|
|
740
740
|
var MouseObserver = class {
|
|
741
741
|
#clicked;
|
|
@@ -833,13 +833,12 @@ var MouseObserver = class {
|
|
|
833
833
|
} else if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
|
|
834
834
|
dy *= this.#ele.clientHeight;
|
|
835
835
|
}
|
|
836
|
-
|
|
837
|
-
if (amount === 0) {
|
|
836
|
+
if (dy === 0) {
|
|
838
837
|
return;
|
|
839
838
|
}
|
|
840
839
|
const anchor = this.#mousePos(event);
|
|
841
840
|
this.#moveCallback(anchor);
|
|
842
|
-
this.#zoomCallback(
|
|
841
|
+
this.#zoomCallback(Math.exp(-dy * WHEEL_ZOOM_PER_PIXEL), anchor);
|
|
843
842
|
}
|
|
844
843
|
#move(event) {
|
|
845
844
|
if (this.#fromTouch()) {
|
|
@@ -915,7 +914,7 @@ var MouseObserver = class {
|
|
|
915
914
|
const anchor = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
|
|
916
915
|
if (this.#pinchDist > 0) {
|
|
917
916
|
this.#moveCallback(anchor);
|
|
918
|
-
this.#zoomCallback(
|
|
917
|
+
this.#zoomCallback(dist / this.#pinchDist, anchor);
|
|
919
918
|
}
|
|
920
919
|
this.#pinchDist = dist;
|
|
921
920
|
return;
|
|
@@ -1610,6 +1609,7 @@ var Port = class {
|
|
|
1610
1609
|
#dataTypePopupElement;
|
|
1611
1610
|
#onConnectionAdded;
|
|
1612
1611
|
#onConnectionRemoved;
|
|
1612
|
+
#widget = null;
|
|
1613
1613
|
constructor(node, portType, config) {
|
|
1614
1614
|
this.#node = node;
|
|
1615
1615
|
this.#connections = new Array();
|
|
@@ -1760,14 +1760,31 @@ var Port = class {
|
|
|
1760
1760
|
this.#visibilityMayHaveChanged(was);
|
|
1761
1761
|
}
|
|
1762
1762
|
#visibilityMayHaveChanged(was) {
|
|
1763
|
-
if (was !== this.hidden() || this.#portType === "INPUTARRAY" /* InputArray */) {
|
|
1763
|
+
if (was !== this.hidden() || this.#portType === "INPUTARRAY" /* InputArray */ || this.#widget !== null) {
|
|
1764
1764
|
this.#node?.invalidateLayout();
|
|
1765
1765
|
}
|
|
1766
1766
|
}
|
|
1767
|
+
setWidget(widget) {
|
|
1768
|
+
this.#widget = widget;
|
|
1769
|
+
this.#node?.invalidateLayout();
|
|
1770
|
+
}
|
|
1771
|
+
widget() {
|
|
1772
|
+
return this.#widget;
|
|
1773
|
+
}
|
|
1774
|
+
/**
|
|
1775
|
+
* The widget stands in for a wire, so it leaves once one is connected.
|
|
1776
|
+
*/
|
|
1777
|
+
widgetShown() {
|
|
1778
|
+
return this.#widget !== null && this.#portType !== "OUTPUT" /* Output */ && this.#connections.length === 0 && !this.hidden() && !(this.#widget.Hidden?.() ?? false);
|
|
1779
|
+
}
|
|
1767
1780
|
/**
|
|
1768
|
-
* A port asked to hide still shows while anything is connected to it
|
|
1781
|
+
* A port asked to hide still shows while anything is connected to it,
|
|
1782
|
+
* and while its node is showing its hidden ports.
|
|
1769
1783
|
*/
|
|
1770
1784
|
hidden() {
|
|
1785
|
+
return this.tucked() && !(this.#node?.hiddenPortsShown() ?? false);
|
|
1786
|
+
}
|
|
1787
|
+
tucked() {
|
|
1771
1788
|
return this.#hidden && this.#connections.length === 0;
|
|
1772
1789
|
}
|
|
1773
1790
|
addConnectionRemovedListener(callback) {
|
|
@@ -1869,117 +1886,6 @@ var Port = class {
|
|
|
1869
1886
|
}
|
|
1870
1887
|
};
|
|
1871
1888
|
|
|
1872
|
-
// src/styles/stroke.ts
|
|
1873
|
-
function StrokeStyleWithFallback(input, fallback) {
|
|
1874
|
-
return {
|
|
1875
|
-
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
1876
|
-
size: input?.size === void 0 ? fallback?.size : input?.size
|
|
1877
|
-
};
|
|
1878
|
-
}
|
|
1879
|
-
var StrokeStyle = class {
|
|
1880
|
-
#size;
|
|
1881
|
-
#color;
|
|
1882
|
-
constructor(config) {
|
|
1883
|
-
this.#size = config?.size === void 0 ? 0.5 : config.size;
|
|
1884
|
-
this.#color = config?.color === void 0 ? "black" : config.color;
|
|
1885
|
-
}
|
|
1886
|
-
setupStyle(ctx, scale) {
|
|
1887
|
-
ctx.strokeStyle = this.#color;
|
|
1888
|
-
ctx.lineWidth = scale * this.#size;
|
|
1889
|
-
}
|
|
1890
|
-
setColor(newColor) {
|
|
1891
|
-
this.#color = newColor;
|
|
1892
|
-
}
|
|
1893
|
-
setSize(newSize) {
|
|
1894
|
-
this.#size = newSize;
|
|
1895
|
-
}
|
|
1896
|
-
size() {
|
|
1897
|
-
return this.#size;
|
|
1898
|
-
}
|
|
1899
|
-
};
|
|
1900
|
-
|
|
1901
|
-
// src/styles/box.ts
|
|
1902
|
-
function BoxStyleWithFallback(input, fallback) {
|
|
1903
|
-
return {
|
|
1904
|
-
radius: input?.radius === void 0 ? fallback?.radius : input?.radius,
|
|
1905
|
-
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
1906
|
-
border: StrokeStyleWithFallback(input?.border, fallback?.border)
|
|
1907
|
-
};
|
|
1908
|
-
}
|
|
1909
|
-
var BoxStyle = class {
|
|
1910
|
-
#border;
|
|
1911
|
-
#color;
|
|
1912
|
-
#radius;
|
|
1913
|
-
constructor(config) {
|
|
1914
|
-
this.#color = config?.color === void 0 ? "#CCCCCC" : config.color;
|
|
1915
|
-
this.#border = config?.border === void 0 ? null : new StrokeStyle(config.border);
|
|
1916
|
-
this.#radius = config?.radius === void 0 ? 2 : config.radius;
|
|
1917
|
-
}
|
|
1918
|
-
#box(ctx, box, scale, radius) {
|
|
1919
|
-
ctx.fillStyle = this.#color;
|
|
1920
|
-
this.#border?.setupStyle(ctx, scale);
|
|
1921
|
-
ctx.beginPath();
|
|
1922
|
-
ctx.roundRect(
|
|
1923
|
-
box.Position.x,
|
|
1924
|
-
box.Position.y,
|
|
1925
|
-
box.Size.x,
|
|
1926
|
-
box.Size.y,
|
|
1927
|
-
radius
|
|
1928
|
-
);
|
|
1929
|
-
ctx.fill();
|
|
1930
|
-
}
|
|
1931
|
-
#draw(ctx, box, scale, radius) {
|
|
1932
|
-
this.#box(ctx, box, scale, radius);
|
|
1933
|
-
ctx.stroke();
|
|
1934
|
-
}
|
|
1935
|
-
Outline(ctx, box, scale, radius) {
|
|
1936
|
-
this.#border?.setupStyle(ctx, scale);
|
|
1937
|
-
ctx.beginPath();
|
|
1938
|
-
ctx.roundRect(
|
|
1939
|
-
box.Position.x,
|
|
1940
|
-
box.Position.y,
|
|
1941
|
-
box.Size.x,
|
|
1942
|
-
box.Size.y,
|
|
1943
|
-
radius
|
|
1944
|
-
);
|
|
1945
|
-
ctx.stroke();
|
|
1946
|
-
}
|
|
1947
|
-
Draw(ctx, box, scale) {
|
|
1948
|
-
this.#draw(ctx, box, scale, this.#radius * scale);
|
|
1949
|
-
}
|
|
1950
|
-
DrawRoundedTopOnly(ctx, box, scale) {
|
|
1951
|
-
this.#draw(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
1952
|
-
}
|
|
1953
|
-
DrawUnderline(ctx, box, scale) {
|
|
1954
|
-
this.#box(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
1955
|
-
ctx.beginPath();
|
|
1956
|
-
ctx.moveTo(box.Position.x, box.Position.y + box.Size.y);
|
|
1957
|
-
ctx.lineTo(box.Position.x + box.Size.x, box.Position.y + box.Size.y);
|
|
1958
|
-
ctx.stroke();
|
|
1959
|
-
}
|
|
1960
|
-
borderSize() {
|
|
1961
|
-
if (this.#border === null) {
|
|
1962
|
-
return 0;
|
|
1963
|
-
}
|
|
1964
|
-
return this.#border.size();
|
|
1965
|
-
}
|
|
1966
|
-
radius() {
|
|
1967
|
-
return this.#radius;
|
|
1968
|
-
}
|
|
1969
|
-
setColor(color) {
|
|
1970
|
-
this.#color = color;
|
|
1971
|
-
}
|
|
1972
|
-
setBorderColor(color) {
|
|
1973
|
-
if (this.#border === null) {
|
|
1974
|
-
this.#border = new StrokeStyle({
|
|
1975
|
-
color
|
|
1976
|
-
});
|
|
1977
|
-
} else {
|
|
1978
|
-
this.#border.setColor(color);
|
|
1979
|
-
}
|
|
1980
|
-
}
|
|
1981
|
-
};
|
|
1982
|
-
|
|
1983
1889
|
// src/styles/cursor.ts
|
|
1984
1890
|
var CursorStyle = /* @__PURE__ */ ((CursorStyle2) => {
|
|
1985
1891
|
CursorStyle2["Default"] = "default";
|
|
@@ -2001,97 +1907,6 @@ var CursorStyle = /* @__PURE__ */ ((CursorStyle2) => {
|
|
|
2001
1907
|
return CursorStyle2;
|
|
2002
1908
|
})(CursorStyle || {});
|
|
2003
1909
|
|
|
2004
|
-
// src/styles/bevel.ts
|
|
2005
|
-
function drawBevel(ctx, box, scale, colors, sunken) {
|
|
2006
|
-
const width2 = Math.max(1, 2 * scale);
|
|
2007
|
-
const half = width2 / 2;
|
|
2008
|
-
const left = box.Position.x + half;
|
|
2009
|
-
const top = box.Position.y + half;
|
|
2010
|
-
const right = box.Position.x + box.Size.x - half;
|
|
2011
|
-
const bottom = box.Position.y + box.Size.y - half;
|
|
2012
|
-
ctx.save();
|
|
2013
|
-
ctx.lineWidth = width2;
|
|
2014
|
-
ctx.lineCap = "square";
|
|
2015
|
-
ctx.strokeStyle = sunken ? colors.Dark : colors.Light;
|
|
2016
|
-
ctx.beginPath();
|
|
2017
|
-
ctx.moveTo(left, bottom);
|
|
2018
|
-
ctx.lineTo(left, top);
|
|
2019
|
-
ctx.lineTo(right, top);
|
|
2020
|
-
ctx.stroke();
|
|
2021
|
-
ctx.strokeStyle = sunken ? colors.Light : colors.Dark;
|
|
2022
|
-
ctx.beginPath();
|
|
2023
|
-
ctx.moveTo(right, top);
|
|
2024
|
-
ctx.lineTo(right, bottom);
|
|
2025
|
-
ctx.lineTo(left, bottom);
|
|
2026
|
-
ctx.stroke();
|
|
2027
|
-
ctx.restore();
|
|
2028
|
-
}
|
|
2029
|
-
|
|
2030
|
-
// src/widgets/field.ts
|
|
2031
|
-
function widgetFont(scale) {
|
|
2032
|
-
return `${Theme.Widget.FontSize * scale}px ${Theme.FontFamily}`;
|
|
2033
|
-
}
|
|
2034
|
-
function fieldBackground(look) {
|
|
2035
|
-
if (look.background !== void 0) {
|
|
2036
|
-
return look.background;
|
|
2037
|
-
}
|
|
2038
|
-
if (look.input) {
|
|
2039
|
-
return look.hovered ? Theme.Widget.Input.HoverBackgroundColor : Theme.Widget.Input.BackgroundColor;
|
|
2040
|
-
}
|
|
2041
|
-
if (look.pressed) {
|
|
2042
|
-
return Theme.Widget.Button.Click.BackgroundColor;
|
|
2043
|
-
}
|
|
2044
|
-
return look.hovered ? Theme.Widget.Hover.BackgroundColor : Theme.Widget.BackgroundColor;
|
|
2045
|
-
}
|
|
2046
|
-
function drawFieldBox(ctx, box, scale, look) {
|
|
2047
|
-
ctx.fillStyle = fieldBackground(look);
|
|
2048
|
-
ctx.beginPath();
|
|
2049
|
-
ctx.roundRect(box.Position.x, box.Position.y, box.Size.x, box.Size.y, Theme.Widget.Border.Radius * scale);
|
|
2050
|
-
ctx.fill();
|
|
2051
|
-
if (Theme.Widget.Border.Size > 0) {
|
|
2052
|
-
ctx.strokeStyle = look.border ?? Theme.Widget.Border.Color;
|
|
2053
|
-
ctx.lineWidth = Theme.Widget.Border.Size * scale;
|
|
2054
|
-
ctx.stroke();
|
|
2055
|
-
}
|
|
2056
|
-
if (Theme.Widget.Bevel !== null) {
|
|
2057
|
-
drawBevel(ctx, box, scale, Theme.Widget.Bevel, look.input === true || look.pressed === true);
|
|
2058
|
-
}
|
|
2059
|
-
}
|
|
2060
|
-
function drawField(ctx, box, scale, look) {
|
|
2061
|
-
drawFieldBox(ctx, box, scale, look);
|
|
2062
|
-
drawFieldText(ctx, box, scale, look);
|
|
2063
|
-
}
|
|
2064
|
-
function drawFieldText(ctx, box, scale, look) {
|
|
2065
|
-
const padding = Theme.Widget.Padding * scale;
|
|
2066
|
-
const middle = box.Position.y + box.Size.y / 2;
|
|
2067
|
-
const textColor = look.textColor ?? (look.input ? Theme.Widget.Input.FontColor : Theme.Widget.FontColor);
|
|
2068
|
-
ctx.font = widgetFont(scale);
|
|
2069
|
-
ctx.textBaseline = "middle";
|
|
2070
|
-
if (look.label === void 0 || look.label === "") {
|
|
2071
|
-
ctx.textAlign = "center";
|
|
2072
|
-
ctx.fillStyle = textColor;
|
|
2073
|
-
ctx.fillText(
|
|
2074
|
-
fitString(ctx, look.value, box.Size.x - padding * 2),
|
|
2075
|
-
box.Position.x + box.Size.x / 2,
|
|
2076
|
-
middle
|
|
2077
|
-
);
|
|
2078
|
-
return;
|
|
2079
|
-
}
|
|
2080
|
-
const room = box.Size.x - padding * 2;
|
|
2081
|
-
const label = fitString(ctx, look.label, room / 2);
|
|
2082
|
-
const labelWidth = ctx.measureText(label).width;
|
|
2083
|
-
ctx.textAlign = "left";
|
|
2084
|
-
ctx.fillStyle = look.textColor ?? Theme.Widget.LabelColor;
|
|
2085
|
-
ctx.fillText(label, box.Position.x + padding, middle);
|
|
2086
|
-
ctx.textAlign = "right";
|
|
2087
|
-
ctx.fillStyle = textColor;
|
|
2088
|
-
ctx.fillText(
|
|
2089
|
-
fitString(ctx, look.value, room - labelWidth - padding),
|
|
2090
|
-
box.Position.x + box.Size.x - padding,
|
|
2091
|
-
middle
|
|
2092
|
-
);
|
|
2093
|
-
}
|
|
2094
|
-
|
|
2095
1910
|
// src/widgets/inplace.ts
|
|
2096
1911
|
var open = /* @__PURE__ */ new Set();
|
|
2097
1912
|
function placeEditsDuring(canvas, draw) {
|
|
@@ -2312,6 +2127,242 @@ function startingWidgetValue(node, property, configured, fallback) {
|
|
|
2312
2127
|
return fallback;
|
|
2313
2128
|
}
|
|
2314
2129
|
|
|
2130
|
+
// src/widgets/hidden_ports.ts
|
|
2131
|
+
var HiddenPortsToggle = class extends WidgetBase {
|
|
2132
|
+
constructor(owner) {
|
|
2133
|
+
super();
|
|
2134
|
+
this.owner = owner;
|
|
2135
|
+
}
|
|
2136
|
+
Size() {
|
|
2137
|
+
return { x: 150, y: 16 };
|
|
2138
|
+
}
|
|
2139
|
+
render(ctx, box, scale) {
|
|
2140
|
+
const label = this.owner.hiddenPortsShown() ? "\u25B4 less" : `\u25BE ${this.owner.hiddenPortCount()} more`;
|
|
2141
|
+
const midY = box.Position.y + box.Size.y / 2;
|
|
2142
|
+
const centerX = box.Position.x + box.Size.x / 2;
|
|
2143
|
+
ctx.font = `${11 * scale}px ${Theme.FontFamily}`;
|
|
2144
|
+
const half = ctx.measureText(label).width / 2 + 6 * scale;
|
|
2145
|
+
ctx.globalAlpha = this.hovered() ? 1 : 0.5;
|
|
2146
|
+
ctx.strokeStyle = Theme.Widget.FontColor;
|
|
2147
|
+
ctx.fillStyle = Theme.Widget.FontColor;
|
|
2148
|
+
ctx.lineWidth = Math.max(1, scale);
|
|
2149
|
+
ctx.beginPath();
|
|
2150
|
+
ctx.moveTo(box.Position.x, midY);
|
|
2151
|
+
ctx.lineTo(centerX - half, midY);
|
|
2152
|
+
ctx.moveTo(centerX + half, midY);
|
|
2153
|
+
ctx.lineTo(box.Position.x + box.Size.x, midY);
|
|
2154
|
+
ctx.stroke();
|
|
2155
|
+
ctx.textAlign = "center";
|
|
2156
|
+
ctx.textBaseline = "middle";
|
|
2157
|
+
ctx.fillText(label, centerX, midY);
|
|
2158
|
+
}
|
|
2159
|
+
onClick() {
|
|
2160
|
+
this.owner.setHiddenPortsShown(!this.owner.hiddenPortsShown());
|
|
2161
|
+
}
|
|
2162
|
+
};
|
|
2163
|
+
|
|
2164
|
+
// src/styles/stroke.ts
|
|
2165
|
+
function StrokeStyleWithFallback(input, fallback) {
|
|
2166
|
+
return {
|
|
2167
|
+
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
2168
|
+
size: input?.size === void 0 ? fallback?.size : input?.size
|
|
2169
|
+
};
|
|
2170
|
+
}
|
|
2171
|
+
var StrokeStyle = class {
|
|
2172
|
+
#size;
|
|
2173
|
+
#color;
|
|
2174
|
+
constructor(config) {
|
|
2175
|
+
this.#size = config?.size === void 0 ? 0.5 : config.size;
|
|
2176
|
+
this.#color = config?.color === void 0 ? "black" : config.color;
|
|
2177
|
+
}
|
|
2178
|
+
setupStyle(ctx, scale) {
|
|
2179
|
+
ctx.strokeStyle = this.#color;
|
|
2180
|
+
ctx.lineWidth = scale * this.#size;
|
|
2181
|
+
}
|
|
2182
|
+
setColor(newColor) {
|
|
2183
|
+
this.#color = newColor;
|
|
2184
|
+
}
|
|
2185
|
+
setSize(newSize) {
|
|
2186
|
+
this.#size = newSize;
|
|
2187
|
+
}
|
|
2188
|
+
size() {
|
|
2189
|
+
return this.#size;
|
|
2190
|
+
}
|
|
2191
|
+
};
|
|
2192
|
+
|
|
2193
|
+
// src/styles/box.ts
|
|
2194
|
+
function BoxStyleWithFallback(input, fallback) {
|
|
2195
|
+
return {
|
|
2196
|
+
radius: input?.radius === void 0 ? fallback?.radius : input?.radius,
|
|
2197
|
+
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
2198
|
+
border: StrokeStyleWithFallback(input?.border, fallback?.border)
|
|
2199
|
+
};
|
|
2200
|
+
}
|
|
2201
|
+
var BoxStyle = class {
|
|
2202
|
+
#border;
|
|
2203
|
+
#color;
|
|
2204
|
+
#radius;
|
|
2205
|
+
constructor(config) {
|
|
2206
|
+
this.#color = config?.color === void 0 ? "#CCCCCC" : config.color;
|
|
2207
|
+
this.#border = config?.border === void 0 ? null : new StrokeStyle(config.border);
|
|
2208
|
+
this.#radius = config?.radius === void 0 ? 2 : config.radius;
|
|
2209
|
+
}
|
|
2210
|
+
#box(ctx, box, scale, radius) {
|
|
2211
|
+
ctx.fillStyle = this.#color;
|
|
2212
|
+
this.#border?.setupStyle(ctx, scale);
|
|
2213
|
+
ctx.beginPath();
|
|
2214
|
+
ctx.roundRect(
|
|
2215
|
+
box.Position.x,
|
|
2216
|
+
box.Position.y,
|
|
2217
|
+
box.Size.x,
|
|
2218
|
+
box.Size.y,
|
|
2219
|
+
radius
|
|
2220
|
+
);
|
|
2221
|
+
ctx.fill();
|
|
2222
|
+
}
|
|
2223
|
+
#draw(ctx, box, scale, radius) {
|
|
2224
|
+
this.#box(ctx, box, scale, radius);
|
|
2225
|
+
ctx.stroke();
|
|
2226
|
+
}
|
|
2227
|
+
Outline(ctx, box, scale, radius) {
|
|
2228
|
+
this.#border?.setupStyle(ctx, scale);
|
|
2229
|
+
ctx.beginPath();
|
|
2230
|
+
ctx.roundRect(
|
|
2231
|
+
box.Position.x,
|
|
2232
|
+
box.Position.y,
|
|
2233
|
+
box.Size.x,
|
|
2234
|
+
box.Size.y,
|
|
2235
|
+
radius
|
|
2236
|
+
);
|
|
2237
|
+
ctx.stroke();
|
|
2238
|
+
}
|
|
2239
|
+
Draw(ctx, box, scale) {
|
|
2240
|
+
this.#draw(ctx, box, scale, this.#radius * scale);
|
|
2241
|
+
}
|
|
2242
|
+
DrawRoundedTopOnly(ctx, box, scale) {
|
|
2243
|
+
this.#draw(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
2244
|
+
}
|
|
2245
|
+
DrawUnderline(ctx, box, scale) {
|
|
2246
|
+
this.#box(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
2247
|
+
ctx.beginPath();
|
|
2248
|
+
ctx.moveTo(box.Position.x, box.Position.y + box.Size.y);
|
|
2249
|
+
ctx.lineTo(box.Position.x + box.Size.x, box.Position.y + box.Size.y);
|
|
2250
|
+
ctx.stroke();
|
|
2251
|
+
}
|
|
2252
|
+
borderSize() {
|
|
2253
|
+
if (this.#border === null) {
|
|
2254
|
+
return 0;
|
|
2255
|
+
}
|
|
2256
|
+
return this.#border.size();
|
|
2257
|
+
}
|
|
2258
|
+
radius() {
|
|
2259
|
+
return this.#radius;
|
|
2260
|
+
}
|
|
2261
|
+
setColor(color) {
|
|
2262
|
+
this.#color = color;
|
|
2263
|
+
}
|
|
2264
|
+
setBorderColor(color) {
|
|
2265
|
+
if (this.#border === null) {
|
|
2266
|
+
this.#border = new StrokeStyle({
|
|
2267
|
+
color
|
|
2268
|
+
});
|
|
2269
|
+
} else {
|
|
2270
|
+
this.#border.setColor(color);
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
};
|
|
2274
|
+
|
|
2275
|
+
// src/styles/bevel.ts
|
|
2276
|
+
function drawBevel(ctx, box, scale, colors, sunken) {
|
|
2277
|
+
const width2 = Math.max(1, 2 * scale);
|
|
2278
|
+
const half = width2 / 2;
|
|
2279
|
+
const left = box.Position.x + half;
|
|
2280
|
+
const top = box.Position.y + half;
|
|
2281
|
+
const right = box.Position.x + box.Size.x - half;
|
|
2282
|
+
const bottom = box.Position.y + box.Size.y - half;
|
|
2283
|
+
ctx.save();
|
|
2284
|
+
ctx.lineWidth = width2;
|
|
2285
|
+
ctx.lineCap = "square";
|
|
2286
|
+
ctx.strokeStyle = sunken ? colors.Dark : colors.Light;
|
|
2287
|
+
ctx.beginPath();
|
|
2288
|
+
ctx.moveTo(left, bottom);
|
|
2289
|
+
ctx.lineTo(left, top);
|
|
2290
|
+
ctx.lineTo(right, top);
|
|
2291
|
+
ctx.stroke();
|
|
2292
|
+
ctx.strokeStyle = sunken ? colors.Light : colors.Dark;
|
|
2293
|
+
ctx.beginPath();
|
|
2294
|
+
ctx.moveTo(right, top);
|
|
2295
|
+
ctx.lineTo(right, bottom);
|
|
2296
|
+
ctx.lineTo(left, bottom);
|
|
2297
|
+
ctx.stroke();
|
|
2298
|
+
ctx.restore();
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
// src/widgets/field.ts
|
|
2302
|
+
function widgetFont(scale) {
|
|
2303
|
+
return `${Theme.Widget.FontSize * scale}px ${Theme.FontFamily}`;
|
|
2304
|
+
}
|
|
2305
|
+
function fieldBackground(look) {
|
|
2306
|
+
if (look.background !== void 0) {
|
|
2307
|
+
return look.background;
|
|
2308
|
+
}
|
|
2309
|
+
if (look.input) {
|
|
2310
|
+
return look.hovered ? Theme.Widget.Input.HoverBackgroundColor : Theme.Widget.Input.BackgroundColor;
|
|
2311
|
+
}
|
|
2312
|
+
if (look.pressed) {
|
|
2313
|
+
return Theme.Widget.Button.Click.BackgroundColor;
|
|
2314
|
+
}
|
|
2315
|
+
return look.hovered ? Theme.Widget.Hover.BackgroundColor : Theme.Widget.BackgroundColor;
|
|
2316
|
+
}
|
|
2317
|
+
function drawFieldBox(ctx, box, scale, look) {
|
|
2318
|
+
ctx.fillStyle = fieldBackground(look);
|
|
2319
|
+
ctx.beginPath();
|
|
2320
|
+
ctx.roundRect(box.Position.x, box.Position.y, box.Size.x, box.Size.y, Theme.Widget.Border.Radius * scale);
|
|
2321
|
+
ctx.fill();
|
|
2322
|
+
if (Theme.Widget.Border.Size > 0) {
|
|
2323
|
+
ctx.strokeStyle = look.border ?? Theme.Widget.Border.Color;
|
|
2324
|
+
ctx.lineWidth = Theme.Widget.Border.Size * scale;
|
|
2325
|
+
ctx.stroke();
|
|
2326
|
+
}
|
|
2327
|
+
if (Theme.Widget.Bevel !== null) {
|
|
2328
|
+
drawBevel(ctx, box, scale, Theme.Widget.Bevel, look.input === true || look.pressed === true);
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
function drawField(ctx, box, scale, look) {
|
|
2332
|
+
drawFieldBox(ctx, box, scale, look);
|
|
2333
|
+
drawFieldText(ctx, box, scale, look);
|
|
2334
|
+
}
|
|
2335
|
+
function drawFieldText(ctx, box, scale, look) {
|
|
2336
|
+
const padding = Theme.Widget.Padding * scale;
|
|
2337
|
+
const middle = box.Position.y + box.Size.y / 2;
|
|
2338
|
+
const textColor = look.textColor ?? (look.input ? Theme.Widget.Input.FontColor : Theme.Widget.FontColor);
|
|
2339
|
+
ctx.font = widgetFont(scale);
|
|
2340
|
+
ctx.textBaseline = "middle";
|
|
2341
|
+
if (look.label === void 0 || look.label === "") {
|
|
2342
|
+
ctx.textAlign = "center";
|
|
2343
|
+
ctx.fillStyle = textColor;
|
|
2344
|
+
ctx.fillText(
|
|
2345
|
+
fitString(ctx, look.value, box.Size.x - padding * 2),
|
|
2346
|
+
box.Position.x + box.Size.x / 2,
|
|
2347
|
+
middle
|
|
2348
|
+
);
|
|
2349
|
+
return;
|
|
2350
|
+
}
|
|
2351
|
+
const room = box.Size.x - padding * 2;
|
|
2352
|
+
const label = fitString(ctx, look.label, room / 2);
|
|
2353
|
+
const labelWidth = ctx.measureText(label).width;
|
|
2354
|
+
ctx.textAlign = "left";
|
|
2355
|
+
ctx.fillStyle = look.textColor ?? Theme.Widget.LabelColor;
|
|
2356
|
+
ctx.fillText(label, box.Position.x + padding, middle);
|
|
2357
|
+
ctx.textAlign = "right";
|
|
2358
|
+
ctx.fillStyle = textColor;
|
|
2359
|
+
ctx.fillText(
|
|
2360
|
+
fitString(ctx, look.value, room - labelWidth - padding),
|
|
2361
|
+
box.Position.x + box.Size.x - padding,
|
|
2362
|
+
middle
|
|
2363
|
+
);
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2315
2366
|
// src/widgets/value.ts
|
|
2316
2367
|
var ValueWidget = class extends WidgetBase {
|
|
2317
2368
|
#node;
|
|
@@ -5079,6 +5130,7 @@ var FlowNode = class {
|
|
|
5079
5130
|
#inputPortPositions;
|
|
5080
5131
|
#outputPortPositions;
|
|
5081
5132
|
#widgetPositions;
|
|
5133
|
+
#portWidgetPositions = new List();
|
|
5082
5134
|
#data;
|
|
5083
5135
|
#registeredAnyPropertyChangeCallbacks;
|
|
5084
5136
|
#registeredPropertyChangeCallbacks;
|
|
@@ -5566,9 +5618,10 @@ var FlowNode = class {
|
|
|
5566
5618
|
}
|
|
5567
5619
|
this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
|
|
5568
5620
|
size.y += this.#portRowHeight(port, tempMeasurement.y) + this.#elementSpacing;
|
|
5569
|
-
size.x = Math.max(size.x, tempMeasurement.x + doublePadding);
|
|
5621
|
+
size.x = Math.max(size.x, this.#portRowWidth(port, tempMeasurement.x) + doublePadding);
|
|
5570
5622
|
}
|
|
5571
|
-
|
|
5623
|
+
const widgets = this.#hasHiddenPortsToggle() ? [this.#hiddenPortsToggle, ...this.#widgets] : this.#widgets;
|
|
5624
|
+
for (const widget of widgets) {
|
|
5572
5625
|
if (widget.Hidden?.()) {
|
|
5573
5626
|
continue;
|
|
5574
5627
|
}
|
|
@@ -5586,6 +5639,9 @@ var FlowNode = class {
|
|
|
5586
5639
|
}
|
|
5587
5640
|
addInput(config) {
|
|
5588
5641
|
const port = new Port(this, config.array ? "INPUTARRAY" /* InputArray */ : "INPUT" /* Input */, config);
|
|
5642
|
+
if (config.widget !== void 0) {
|
|
5643
|
+
port.setWidget(GlobalWidgetFactory.createFromConfig(this, config.widget));
|
|
5644
|
+
}
|
|
5589
5645
|
this.#input.push(port);
|
|
5590
5646
|
return port;
|
|
5591
5647
|
}
|
|
@@ -5594,6 +5650,31 @@ var FlowNode = class {
|
|
|
5594
5650
|
this.#output.push(port);
|
|
5595
5651
|
return port;
|
|
5596
5652
|
}
|
|
5653
|
+
#hiddenPortsShown = false;
|
|
5654
|
+
#hiddenPortsToggle = new HiddenPortsToggle(this);
|
|
5655
|
+
#hiddenPortsTogglePosition = null;
|
|
5656
|
+
hiddenPortsShown() {
|
|
5657
|
+
return this.#hiddenPortsShown;
|
|
5658
|
+
}
|
|
5659
|
+
setHiddenPortsShown(shown) {
|
|
5660
|
+
if (shown === this.#hiddenPortsShown) {
|
|
5661
|
+
return;
|
|
5662
|
+
}
|
|
5663
|
+
this.#hiddenPortsShown = shown;
|
|
5664
|
+
this.invalidateLayout();
|
|
5665
|
+
}
|
|
5666
|
+
hiddenPortCount() {
|
|
5667
|
+
let count = 0;
|
|
5668
|
+
for (const port of [...this.#input, ...this.#output]) {
|
|
5669
|
+
if (port.tucked()) {
|
|
5670
|
+
count++;
|
|
5671
|
+
}
|
|
5672
|
+
}
|
|
5673
|
+
return count;
|
|
5674
|
+
}
|
|
5675
|
+
#hasHiddenPortsToggle() {
|
|
5676
|
+
return this.hiddenPortCount() > 0;
|
|
5677
|
+
}
|
|
5597
5678
|
addWidget(widget) {
|
|
5598
5679
|
this.#widgets.push(widget);
|
|
5599
5680
|
requestRender();
|
|
@@ -5672,6 +5753,11 @@ var FlowNode = class {
|
|
|
5672
5753
|
intersection.Port = this.#output[i];
|
|
5673
5754
|
}
|
|
5674
5755
|
}
|
|
5756
|
+
if (this.#hiddenPortsTogglePosition !== null && InBox(this.#hiddenPortsTogglePosition, position)) {
|
|
5757
|
+
intersection.Node = this;
|
|
5758
|
+
intersection.Widget = this.#hiddenPortsToggle;
|
|
5759
|
+
intersection.WidgetBox = this.#hiddenPortsTogglePosition;
|
|
5760
|
+
}
|
|
5675
5761
|
for (let i = 0; i < this.#widgetPositions.Count(); i++) {
|
|
5676
5762
|
const widget = this.#widgets[i];
|
|
5677
5763
|
if (widget !== void 0 && !widget.Hidden?.() && InBox(this.#widgetPositions.At(i), position)) {
|
|
@@ -5681,6 +5767,17 @@ var FlowNode = class {
|
|
|
5681
5767
|
intersection.WidgetBox = this.#widgetPositions.At(i);
|
|
5682
5768
|
}
|
|
5683
5769
|
}
|
|
5770
|
+
for (let i = 0; i < this.#portWidgetPositions.Count(); i++) {
|
|
5771
|
+
const port = this.#input[i];
|
|
5772
|
+
if (port !== void 0 && port.widgetShown() && InBox(this.#portWidgetPositions.At(i), position)) {
|
|
5773
|
+
intersection.Node = this;
|
|
5774
|
+
intersection.Widget = port.widget();
|
|
5775
|
+
intersection.WidgetBox = this.#portWidgetPositions.At(i);
|
|
5776
|
+
intersection.Port = void 0;
|
|
5777
|
+
intersection.PortIndex = void 0;
|
|
5778
|
+
intersection.PortIsInput = void 0;
|
|
5779
|
+
}
|
|
5780
|
+
}
|
|
5684
5781
|
return intersection;
|
|
5685
5782
|
}
|
|
5686
5783
|
canEditTitle() {
|
|
@@ -5795,7 +5892,14 @@ var FlowNode = class {
|
|
|
5795
5892
|
}
|
|
5796
5893
|
#portRowHeight(port, textHeight) {
|
|
5797
5894
|
const slots = port.slots();
|
|
5798
|
-
|
|
5895
|
+
const widget = port.widgetShown() ? port.widget().Size().y : 0;
|
|
5896
|
+
return Math.max(slots > 1 ? slots * ARRAY_SLOT_PITCH : 0, textHeight, widget);
|
|
5897
|
+
}
|
|
5898
|
+
#portRowWidth(port, textWidth) {
|
|
5899
|
+
if (!port.widgetShown()) {
|
|
5900
|
+
return textWidth;
|
|
5901
|
+
}
|
|
5902
|
+
return textWidth + this.#elementSpacing + port.widget().Size().x;
|
|
5799
5903
|
}
|
|
5800
5904
|
hasBeenLaidOut() {
|
|
5801
5905
|
return this.#laidOut;
|
|
@@ -5817,6 +5921,7 @@ var FlowNode = class {
|
|
|
5817
5921
|
this.#inputPortPositions.Clear();
|
|
5818
5922
|
this.#outputPortPositions.Clear();
|
|
5819
5923
|
this.#widgetPositions.Clear();
|
|
5924
|
+
this.#portWidgetPositions.Clear();
|
|
5820
5925
|
const scaledPadding = this.#padding * camera.zoom;
|
|
5821
5926
|
const scaledElementSpacing = this.#elementSpacing * camera.zoom;
|
|
5822
5927
|
const nodeBounds = this.calculateBounds(ctx, camera);
|
|
@@ -5911,6 +6016,7 @@ var FlowNode = class {
|
|
|
5911
6016
|
const port = this.#input[i];
|
|
5912
6017
|
if (port.hidden()) {
|
|
5913
6018
|
this.#inputPortPositions.Push({ Position: { x: nodeBounds.Position.x, y: startY }, Size: { x: 0, y: 0 } });
|
|
6019
|
+
this.#portWidgetPositions.Push({ Position: { x: nodeBounds.Position.x, y: startY }, Size: { x: 0, y: 0 } });
|
|
5914
6020
|
continue;
|
|
5915
6021
|
}
|
|
5916
6022
|
this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
|
|
@@ -5920,6 +6026,19 @@ var FlowNode = class {
|
|
|
5920
6026
|
position.y = startY + portHeight / 2;
|
|
5921
6027
|
this.#portTextStyle.setupStyle(ctx, camera.zoom);
|
|
5922
6028
|
ctx.fillText(port.getDisplayName(), leftSide, position.y);
|
|
6029
|
+
if (port.widgetShown()) {
|
|
6030
|
+
const widget = port.widget();
|
|
6031
|
+
const widgetHeight = widget.Size().y * camera.zoom;
|
|
6032
|
+
const widgetLeft = leftSide + tempMeasurement.x * camera.zoom + scaledElementSpacing;
|
|
6033
|
+
const box = {
|
|
6034
|
+
Position: { x: widgetLeft, y: startY + (portHeight - widgetHeight) / 2 },
|
|
6035
|
+
Size: { x: nodeBounds.Position.x + nodeBounds.Size.x - scaledPadding - widgetLeft, y: widgetHeight }
|
|
6036
|
+
};
|
|
6037
|
+
widget.Draw(ctx, box, camera.zoom, mousePosition);
|
|
6038
|
+
this.#portWidgetPositions.Push(box);
|
|
6039
|
+
} else {
|
|
6040
|
+
this.#portWidgetPositions.Push({ Position: { x: nodeBounds.Position.x, y: startY }, Size: { x: 0, y: 0 } });
|
|
6041
|
+
}
|
|
5923
6042
|
this.#inputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));
|
|
5924
6043
|
startY += portHeight + scaledElementSpacing;
|
|
5925
6044
|
}
|
|
@@ -5941,6 +6060,16 @@ var FlowNode = class {
|
|
|
5941
6060
|
this.#outputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));
|
|
5942
6061
|
startY += portHeight + scaledElementSpacing;
|
|
5943
6062
|
}
|
|
6063
|
+
this.#hiddenPortsTogglePosition = null;
|
|
6064
|
+
if (this.#hasHiddenPortsToggle()) {
|
|
6065
|
+
const box = {
|
|
6066
|
+
Position: { x: nodeBounds.Position.x + scaledPadding, y: startY },
|
|
6067
|
+
Size: { x: nodeBounds.Size.x - scaledPadding * 2, y: this.#hiddenPortsToggle.Size().y * camera.zoom }
|
|
6068
|
+
};
|
|
6069
|
+
this.#hiddenPortsToggle.Draw(ctx, box, camera.zoom, mousePosition);
|
|
6070
|
+
this.#hiddenPortsTogglePosition = box;
|
|
6071
|
+
startY += box.Size.y + scaledElementSpacing;
|
|
6072
|
+
}
|
|
5944
6073
|
for (let i = 0; i < this.#widgets.length; i++) {
|
|
5945
6074
|
const widget = this.#widgets[i];
|
|
5946
6075
|
if (widget.Hidden?.()) {
|
|
@@ -5995,6 +6124,8 @@ var FlowNode = class {
|
|
|
5995
6124
|
return false;
|
|
5996
6125
|
}
|
|
5997
6126
|
this.#widgetPositions.Clear();
|
|
6127
|
+
this.#portWidgetPositions.Clear();
|
|
6128
|
+
this.#hiddenPortsTogglePosition = null;
|
|
5998
6129
|
return true;
|
|
5999
6130
|
}
|
|
6000
6131
|
placePorts(bounds, zoom) {
|
|
@@ -7655,8 +7786,8 @@ var NodeFlowGraph = class {
|
|
|
7655
7786
|
this.#clickEnd.bind(this),
|
|
7656
7787
|
this.#openContextMenu.bind(this),
|
|
7657
7788
|
this.#fileDrop.bind(this),
|
|
7658
|
-
(
|
|
7659
|
-
this
|
|
7789
|
+
(factor, anchor) => {
|
|
7790
|
+
this.#zoomBy(factor, anchor);
|
|
7660
7791
|
}
|
|
7661
7792
|
);
|
|
7662
7793
|
document.addEventListener(
|
|
@@ -7784,12 +7915,15 @@ var NodeFlowGraph = class {
|
|
|
7784
7915
|
this.#mainNoteSubsystem.addNoteDragStopListener(callback);
|
|
7785
7916
|
}
|
|
7786
7917
|
zoom(amount, anchor) {
|
|
7918
|
+
this.#zoomBy(1 + amount * 0.05, anchor);
|
|
7919
|
+
}
|
|
7920
|
+
#zoomBy(factor, anchor) {
|
|
7787
7921
|
const anchorPos = anchor ?? this.#mousePosition;
|
|
7788
7922
|
let oldPos = void 0;
|
|
7789
7923
|
if (anchorPos !== void 0) {
|
|
7790
7924
|
oldPos = this.#sceenPositionToGraphPosition(anchorPos);
|
|
7791
7925
|
}
|
|
7792
|
-
this.#camera.zoom
|
|
7926
|
+
this.#camera.zoom *= factor;
|
|
7793
7927
|
if (!oldPos || anchorPos === void 0) {
|
|
7794
7928
|
return;
|
|
7795
7929
|
}
|