@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.js
CHANGED
|
@@ -805,7 +805,7 @@ var ContextMenu = class _ContextMenu {
|
|
|
805
805
|
// src/input.ts
|
|
806
806
|
var LONG_PRESS_MS = 500;
|
|
807
807
|
var LONG_PRESS_SLOP = 12;
|
|
808
|
-
var
|
|
808
|
+
var WHEEL_ZOOM_PER_PIXEL = 5e-4;
|
|
809
809
|
var SUPPRESS_MOUSE_MS = 600;
|
|
810
810
|
var MouseObserver = class {
|
|
811
811
|
#clicked;
|
|
@@ -903,13 +903,12 @@ var MouseObserver = class {
|
|
|
903
903
|
} else if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
|
|
904
904
|
dy *= this.#ele.clientHeight;
|
|
905
905
|
}
|
|
906
|
-
|
|
907
|
-
if (amount === 0) {
|
|
906
|
+
if (dy === 0) {
|
|
908
907
|
return;
|
|
909
908
|
}
|
|
910
909
|
const anchor = this.#mousePos(event);
|
|
911
910
|
this.#moveCallback(anchor);
|
|
912
|
-
this.#zoomCallback(
|
|
911
|
+
this.#zoomCallback(Math.exp(-dy * WHEEL_ZOOM_PER_PIXEL), anchor);
|
|
913
912
|
}
|
|
914
913
|
#move(event) {
|
|
915
914
|
if (this.#fromTouch()) {
|
|
@@ -985,7 +984,7 @@ var MouseObserver = class {
|
|
|
985
984
|
const anchor = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
|
|
986
985
|
if (this.#pinchDist > 0) {
|
|
987
986
|
this.#moveCallback(anchor);
|
|
988
|
-
this.#zoomCallback(
|
|
987
|
+
this.#zoomCallback(dist / this.#pinchDist, anchor);
|
|
989
988
|
}
|
|
990
989
|
this.#pinchDist = dist;
|
|
991
990
|
return;
|
|
@@ -1680,6 +1679,7 @@ var Port = class {
|
|
|
1680
1679
|
#dataTypePopupElement;
|
|
1681
1680
|
#onConnectionAdded;
|
|
1682
1681
|
#onConnectionRemoved;
|
|
1682
|
+
#widget = null;
|
|
1683
1683
|
constructor(node, portType, config) {
|
|
1684
1684
|
this.#node = node;
|
|
1685
1685
|
this.#connections = new Array();
|
|
@@ -1830,14 +1830,31 @@ var Port = class {
|
|
|
1830
1830
|
this.#visibilityMayHaveChanged(was);
|
|
1831
1831
|
}
|
|
1832
1832
|
#visibilityMayHaveChanged(was) {
|
|
1833
|
-
if (was !== this.hidden() || this.#portType === "INPUTARRAY" /* InputArray */) {
|
|
1833
|
+
if (was !== this.hidden() || this.#portType === "INPUTARRAY" /* InputArray */ || this.#widget !== null) {
|
|
1834
1834
|
this.#node?.invalidateLayout();
|
|
1835
1835
|
}
|
|
1836
1836
|
}
|
|
1837
|
+
setWidget(widget) {
|
|
1838
|
+
this.#widget = widget;
|
|
1839
|
+
this.#node?.invalidateLayout();
|
|
1840
|
+
}
|
|
1841
|
+
widget() {
|
|
1842
|
+
return this.#widget;
|
|
1843
|
+
}
|
|
1844
|
+
/**
|
|
1845
|
+
* The widget stands in for a wire, so it leaves once one is connected.
|
|
1846
|
+
*/
|
|
1847
|
+
widgetShown() {
|
|
1848
|
+
return this.#widget !== null && this.#portType !== "OUTPUT" /* Output */ && this.#connections.length === 0 && !this.hidden() && !(this.#widget.Hidden?.() ?? false);
|
|
1849
|
+
}
|
|
1837
1850
|
/**
|
|
1838
|
-
* A port asked to hide still shows while anything is connected to it
|
|
1851
|
+
* A port asked to hide still shows while anything is connected to it,
|
|
1852
|
+
* and while its node is showing its hidden ports.
|
|
1839
1853
|
*/
|
|
1840
1854
|
hidden() {
|
|
1855
|
+
return this.tucked() && !(this.#node?.hiddenPortsShown() ?? false);
|
|
1856
|
+
}
|
|
1857
|
+
tucked() {
|
|
1841
1858
|
return this.#hidden && this.#connections.length === 0;
|
|
1842
1859
|
}
|
|
1843
1860
|
addConnectionRemovedListener(callback) {
|
|
@@ -1939,117 +1956,6 @@ var Port = class {
|
|
|
1939
1956
|
}
|
|
1940
1957
|
};
|
|
1941
1958
|
|
|
1942
|
-
// src/styles/stroke.ts
|
|
1943
|
-
function StrokeStyleWithFallback(input, fallback) {
|
|
1944
|
-
return {
|
|
1945
|
-
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
1946
|
-
size: input?.size === void 0 ? fallback?.size : input?.size
|
|
1947
|
-
};
|
|
1948
|
-
}
|
|
1949
|
-
var StrokeStyle = class {
|
|
1950
|
-
#size;
|
|
1951
|
-
#color;
|
|
1952
|
-
constructor(config) {
|
|
1953
|
-
this.#size = config?.size === void 0 ? 0.5 : config.size;
|
|
1954
|
-
this.#color = config?.color === void 0 ? "black" : config.color;
|
|
1955
|
-
}
|
|
1956
|
-
setupStyle(ctx, scale) {
|
|
1957
|
-
ctx.strokeStyle = this.#color;
|
|
1958
|
-
ctx.lineWidth = scale * this.#size;
|
|
1959
|
-
}
|
|
1960
|
-
setColor(newColor) {
|
|
1961
|
-
this.#color = newColor;
|
|
1962
|
-
}
|
|
1963
|
-
setSize(newSize) {
|
|
1964
|
-
this.#size = newSize;
|
|
1965
|
-
}
|
|
1966
|
-
size() {
|
|
1967
|
-
return this.#size;
|
|
1968
|
-
}
|
|
1969
|
-
};
|
|
1970
|
-
|
|
1971
|
-
// src/styles/box.ts
|
|
1972
|
-
function BoxStyleWithFallback(input, fallback) {
|
|
1973
|
-
return {
|
|
1974
|
-
radius: input?.radius === void 0 ? fallback?.radius : input?.radius,
|
|
1975
|
-
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
1976
|
-
border: StrokeStyleWithFallback(input?.border, fallback?.border)
|
|
1977
|
-
};
|
|
1978
|
-
}
|
|
1979
|
-
var BoxStyle = class {
|
|
1980
|
-
#border;
|
|
1981
|
-
#color;
|
|
1982
|
-
#radius;
|
|
1983
|
-
constructor(config) {
|
|
1984
|
-
this.#color = config?.color === void 0 ? "#CCCCCC" : config.color;
|
|
1985
|
-
this.#border = config?.border === void 0 ? null : new StrokeStyle(config.border);
|
|
1986
|
-
this.#radius = config?.radius === void 0 ? 2 : config.radius;
|
|
1987
|
-
}
|
|
1988
|
-
#box(ctx, box, scale, radius) {
|
|
1989
|
-
ctx.fillStyle = this.#color;
|
|
1990
|
-
this.#border?.setupStyle(ctx, scale);
|
|
1991
|
-
ctx.beginPath();
|
|
1992
|
-
ctx.roundRect(
|
|
1993
|
-
box.Position.x,
|
|
1994
|
-
box.Position.y,
|
|
1995
|
-
box.Size.x,
|
|
1996
|
-
box.Size.y,
|
|
1997
|
-
radius
|
|
1998
|
-
);
|
|
1999
|
-
ctx.fill();
|
|
2000
|
-
}
|
|
2001
|
-
#draw(ctx, box, scale, radius) {
|
|
2002
|
-
this.#box(ctx, box, scale, radius);
|
|
2003
|
-
ctx.stroke();
|
|
2004
|
-
}
|
|
2005
|
-
Outline(ctx, box, scale, radius) {
|
|
2006
|
-
this.#border?.setupStyle(ctx, scale);
|
|
2007
|
-
ctx.beginPath();
|
|
2008
|
-
ctx.roundRect(
|
|
2009
|
-
box.Position.x,
|
|
2010
|
-
box.Position.y,
|
|
2011
|
-
box.Size.x,
|
|
2012
|
-
box.Size.y,
|
|
2013
|
-
radius
|
|
2014
|
-
);
|
|
2015
|
-
ctx.stroke();
|
|
2016
|
-
}
|
|
2017
|
-
Draw(ctx, box, scale) {
|
|
2018
|
-
this.#draw(ctx, box, scale, this.#radius * scale);
|
|
2019
|
-
}
|
|
2020
|
-
DrawRoundedTopOnly(ctx, box, scale) {
|
|
2021
|
-
this.#draw(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
2022
|
-
}
|
|
2023
|
-
DrawUnderline(ctx, box, scale) {
|
|
2024
|
-
this.#box(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
2025
|
-
ctx.beginPath();
|
|
2026
|
-
ctx.moveTo(box.Position.x, box.Position.y + box.Size.y);
|
|
2027
|
-
ctx.lineTo(box.Position.x + box.Size.x, box.Position.y + box.Size.y);
|
|
2028
|
-
ctx.stroke();
|
|
2029
|
-
}
|
|
2030
|
-
borderSize() {
|
|
2031
|
-
if (this.#border === null) {
|
|
2032
|
-
return 0;
|
|
2033
|
-
}
|
|
2034
|
-
return this.#border.size();
|
|
2035
|
-
}
|
|
2036
|
-
radius() {
|
|
2037
|
-
return this.#radius;
|
|
2038
|
-
}
|
|
2039
|
-
setColor(color) {
|
|
2040
|
-
this.#color = color;
|
|
2041
|
-
}
|
|
2042
|
-
setBorderColor(color) {
|
|
2043
|
-
if (this.#border === null) {
|
|
2044
|
-
this.#border = new StrokeStyle({
|
|
2045
|
-
color
|
|
2046
|
-
});
|
|
2047
|
-
} else {
|
|
2048
|
-
this.#border.setColor(color);
|
|
2049
|
-
}
|
|
2050
|
-
}
|
|
2051
|
-
};
|
|
2052
|
-
|
|
2053
1959
|
// src/styles/cursor.ts
|
|
2054
1960
|
var CursorStyle = /* @__PURE__ */ ((CursorStyle2) => {
|
|
2055
1961
|
CursorStyle2["Default"] = "default";
|
|
@@ -2071,97 +1977,6 @@ var CursorStyle = /* @__PURE__ */ ((CursorStyle2) => {
|
|
|
2071
1977
|
return CursorStyle2;
|
|
2072
1978
|
})(CursorStyle || {});
|
|
2073
1979
|
|
|
2074
|
-
// src/styles/bevel.ts
|
|
2075
|
-
function drawBevel(ctx, box, scale, colors, sunken) {
|
|
2076
|
-
const width2 = Math.max(1, 2 * scale);
|
|
2077
|
-
const half = width2 / 2;
|
|
2078
|
-
const left = box.Position.x + half;
|
|
2079
|
-
const top = box.Position.y + half;
|
|
2080
|
-
const right = box.Position.x + box.Size.x - half;
|
|
2081
|
-
const bottom = box.Position.y + box.Size.y - half;
|
|
2082
|
-
ctx.save();
|
|
2083
|
-
ctx.lineWidth = width2;
|
|
2084
|
-
ctx.lineCap = "square";
|
|
2085
|
-
ctx.strokeStyle = sunken ? colors.Dark : colors.Light;
|
|
2086
|
-
ctx.beginPath();
|
|
2087
|
-
ctx.moveTo(left, bottom);
|
|
2088
|
-
ctx.lineTo(left, top);
|
|
2089
|
-
ctx.lineTo(right, top);
|
|
2090
|
-
ctx.stroke();
|
|
2091
|
-
ctx.strokeStyle = sunken ? colors.Light : colors.Dark;
|
|
2092
|
-
ctx.beginPath();
|
|
2093
|
-
ctx.moveTo(right, top);
|
|
2094
|
-
ctx.lineTo(right, bottom);
|
|
2095
|
-
ctx.lineTo(left, bottom);
|
|
2096
|
-
ctx.stroke();
|
|
2097
|
-
ctx.restore();
|
|
2098
|
-
}
|
|
2099
|
-
|
|
2100
|
-
// src/widgets/field.ts
|
|
2101
|
-
function widgetFont(scale) {
|
|
2102
|
-
return `${Theme.Widget.FontSize * scale}px ${Theme.FontFamily}`;
|
|
2103
|
-
}
|
|
2104
|
-
function fieldBackground(look) {
|
|
2105
|
-
if (look.background !== void 0) {
|
|
2106
|
-
return look.background;
|
|
2107
|
-
}
|
|
2108
|
-
if (look.input) {
|
|
2109
|
-
return look.hovered ? Theme.Widget.Input.HoverBackgroundColor : Theme.Widget.Input.BackgroundColor;
|
|
2110
|
-
}
|
|
2111
|
-
if (look.pressed) {
|
|
2112
|
-
return Theme.Widget.Button.Click.BackgroundColor;
|
|
2113
|
-
}
|
|
2114
|
-
return look.hovered ? Theme.Widget.Hover.BackgroundColor : Theme.Widget.BackgroundColor;
|
|
2115
|
-
}
|
|
2116
|
-
function drawFieldBox(ctx, box, scale, look) {
|
|
2117
|
-
ctx.fillStyle = fieldBackground(look);
|
|
2118
|
-
ctx.beginPath();
|
|
2119
|
-
ctx.roundRect(box.Position.x, box.Position.y, box.Size.x, box.Size.y, Theme.Widget.Border.Radius * scale);
|
|
2120
|
-
ctx.fill();
|
|
2121
|
-
if (Theme.Widget.Border.Size > 0) {
|
|
2122
|
-
ctx.strokeStyle = look.border ?? Theme.Widget.Border.Color;
|
|
2123
|
-
ctx.lineWidth = Theme.Widget.Border.Size * scale;
|
|
2124
|
-
ctx.stroke();
|
|
2125
|
-
}
|
|
2126
|
-
if (Theme.Widget.Bevel !== null) {
|
|
2127
|
-
drawBevel(ctx, box, scale, Theme.Widget.Bevel, look.input === true || look.pressed === true);
|
|
2128
|
-
}
|
|
2129
|
-
}
|
|
2130
|
-
function drawField(ctx, box, scale, look) {
|
|
2131
|
-
drawFieldBox(ctx, box, scale, look);
|
|
2132
|
-
drawFieldText(ctx, box, scale, look);
|
|
2133
|
-
}
|
|
2134
|
-
function drawFieldText(ctx, box, scale, look) {
|
|
2135
|
-
const padding = Theme.Widget.Padding * scale;
|
|
2136
|
-
const middle = box.Position.y + box.Size.y / 2;
|
|
2137
|
-
const textColor = look.textColor ?? (look.input ? Theme.Widget.Input.FontColor : Theme.Widget.FontColor);
|
|
2138
|
-
ctx.font = widgetFont(scale);
|
|
2139
|
-
ctx.textBaseline = "middle";
|
|
2140
|
-
if (look.label === void 0 || look.label === "") {
|
|
2141
|
-
ctx.textAlign = "center";
|
|
2142
|
-
ctx.fillStyle = textColor;
|
|
2143
|
-
ctx.fillText(
|
|
2144
|
-
fitString(ctx, look.value, box.Size.x - padding * 2),
|
|
2145
|
-
box.Position.x + box.Size.x / 2,
|
|
2146
|
-
middle
|
|
2147
|
-
);
|
|
2148
|
-
return;
|
|
2149
|
-
}
|
|
2150
|
-
const room = box.Size.x - padding * 2;
|
|
2151
|
-
const label = fitString(ctx, look.label, room / 2);
|
|
2152
|
-
const labelWidth = ctx.measureText(label).width;
|
|
2153
|
-
ctx.textAlign = "left";
|
|
2154
|
-
ctx.fillStyle = look.textColor ?? Theme.Widget.LabelColor;
|
|
2155
|
-
ctx.fillText(label, box.Position.x + padding, middle);
|
|
2156
|
-
ctx.textAlign = "right";
|
|
2157
|
-
ctx.fillStyle = textColor;
|
|
2158
|
-
ctx.fillText(
|
|
2159
|
-
fitString(ctx, look.value, room - labelWidth - padding),
|
|
2160
|
-
box.Position.x + box.Size.x - padding,
|
|
2161
|
-
middle
|
|
2162
|
-
);
|
|
2163
|
-
}
|
|
2164
|
-
|
|
2165
1980
|
// src/widgets/inplace.ts
|
|
2166
1981
|
var open = /* @__PURE__ */ new Set();
|
|
2167
1982
|
function placeEditsDuring(canvas, draw) {
|
|
@@ -2382,6 +2197,242 @@ function startingWidgetValue(node, property, configured, fallback) {
|
|
|
2382
2197
|
return fallback;
|
|
2383
2198
|
}
|
|
2384
2199
|
|
|
2200
|
+
// src/widgets/hidden_ports.ts
|
|
2201
|
+
var HiddenPortsToggle = class extends WidgetBase {
|
|
2202
|
+
constructor(owner) {
|
|
2203
|
+
super();
|
|
2204
|
+
this.owner = owner;
|
|
2205
|
+
}
|
|
2206
|
+
Size() {
|
|
2207
|
+
return { x: 150, y: 16 };
|
|
2208
|
+
}
|
|
2209
|
+
render(ctx, box, scale) {
|
|
2210
|
+
const label = this.owner.hiddenPortsShown() ? "\u25B4 less" : `\u25BE ${this.owner.hiddenPortCount()} more`;
|
|
2211
|
+
const midY = box.Position.y + box.Size.y / 2;
|
|
2212
|
+
const centerX = box.Position.x + box.Size.x / 2;
|
|
2213
|
+
ctx.font = `${11 * scale}px ${Theme.FontFamily}`;
|
|
2214
|
+
const half = ctx.measureText(label).width / 2 + 6 * scale;
|
|
2215
|
+
ctx.globalAlpha = this.hovered() ? 1 : 0.5;
|
|
2216
|
+
ctx.strokeStyle = Theme.Widget.FontColor;
|
|
2217
|
+
ctx.fillStyle = Theme.Widget.FontColor;
|
|
2218
|
+
ctx.lineWidth = Math.max(1, scale);
|
|
2219
|
+
ctx.beginPath();
|
|
2220
|
+
ctx.moveTo(box.Position.x, midY);
|
|
2221
|
+
ctx.lineTo(centerX - half, midY);
|
|
2222
|
+
ctx.moveTo(centerX + half, midY);
|
|
2223
|
+
ctx.lineTo(box.Position.x + box.Size.x, midY);
|
|
2224
|
+
ctx.stroke();
|
|
2225
|
+
ctx.textAlign = "center";
|
|
2226
|
+
ctx.textBaseline = "middle";
|
|
2227
|
+
ctx.fillText(label, centerX, midY);
|
|
2228
|
+
}
|
|
2229
|
+
onClick() {
|
|
2230
|
+
this.owner.setHiddenPortsShown(!this.owner.hiddenPortsShown());
|
|
2231
|
+
}
|
|
2232
|
+
};
|
|
2233
|
+
|
|
2234
|
+
// src/styles/stroke.ts
|
|
2235
|
+
function StrokeStyleWithFallback(input, fallback) {
|
|
2236
|
+
return {
|
|
2237
|
+
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
2238
|
+
size: input?.size === void 0 ? fallback?.size : input?.size
|
|
2239
|
+
};
|
|
2240
|
+
}
|
|
2241
|
+
var StrokeStyle = class {
|
|
2242
|
+
#size;
|
|
2243
|
+
#color;
|
|
2244
|
+
constructor(config) {
|
|
2245
|
+
this.#size = config?.size === void 0 ? 0.5 : config.size;
|
|
2246
|
+
this.#color = config?.color === void 0 ? "black" : config.color;
|
|
2247
|
+
}
|
|
2248
|
+
setupStyle(ctx, scale) {
|
|
2249
|
+
ctx.strokeStyle = this.#color;
|
|
2250
|
+
ctx.lineWidth = scale * this.#size;
|
|
2251
|
+
}
|
|
2252
|
+
setColor(newColor) {
|
|
2253
|
+
this.#color = newColor;
|
|
2254
|
+
}
|
|
2255
|
+
setSize(newSize) {
|
|
2256
|
+
this.#size = newSize;
|
|
2257
|
+
}
|
|
2258
|
+
size() {
|
|
2259
|
+
return this.#size;
|
|
2260
|
+
}
|
|
2261
|
+
};
|
|
2262
|
+
|
|
2263
|
+
// src/styles/box.ts
|
|
2264
|
+
function BoxStyleWithFallback(input, fallback) {
|
|
2265
|
+
return {
|
|
2266
|
+
radius: input?.radius === void 0 ? fallback?.radius : input?.radius,
|
|
2267
|
+
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
2268
|
+
border: StrokeStyleWithFallback(input?.border, fallback?.border)
|
|
2269
|
+
};
|
|
2270
|
+
}
|
|
2271
|
+
var BoxStyle = class {
|
|
2272
|
+
#border;
|
|
2273
|
+
#color;
|
|
2274
|
+
#radius;
|
|
2275
|
+
constructor(config) {
|
|
2276
|
+
this.#color = config?.color === void 0 ? "#CCCCCC" : config.color;
|
|
2277
|
+
this.#border = config?.border === void 0 ? null : new StrokeStyle(config.border);
|
|
2278
|
+
this.#radius = config?.radius === void 0 ? 2 : config.radius;
|
|
2279
|
+
}
|
|
2280
|
+
#box(ctx, box, scale, radius) {
|
|
2281
|
+
ctx.fillStyle = this.#color;
|
|
2282
|
+
this.#border?.setupStyle(ctx, scale);
|
|
2283
|
+
ctx.beginPath();
|
|
2284
|
+
ctx.roundRect(
|
|
2285
|
+
box.Position.x,
|
|
2286
|
+
box.Position.y,
|
|
2287
|
+
box.Size.x,
|
|
2288
|
+
box.Size.y,
|
|
2289
|
+
radius
|
|
2290
|
+
);
|
|
2291
|
+
ctx.fill();
|
|
2292
|
+
}
|
|
2293
|
+
#draw(ctx, box, scale, radius) {
|
|
2294
|
+
this.#box(ctx, box, scale, radius);
|
|
2295
|
+
ctx.stroke();
|
|
2296
|
+
}
|
|
2297
|
+
Outline(ctx, box, scale, radius) {
|
|
2298
|
+
this.#border?.setupStyle(ctx, scale);
|
|
2299
|
+
ctx.beginPath();
|
|
2300
|
+
ctx.roundRect(
|
|
2301
|
+
box.Position.x,
|
|
2302
|
+
box.Position.y,
|
|
2303
|
+
box.Size.x,
|
|
2304
|
+
box.Size.y,
|
|
2305
|
+
radius
|
|
2306
|
+
);
|
|
2307
|
+
ctx.stroke();
|
|
2308
|
+
}
|
|
2309
|
+
Draw(ctx, box, scale) {
|
|
2310
|
+
this.#draw(ctx, box, scale, this.#radius * scale);
|
|
2311
|
+
}
|
|
2312
|
+
DrawRoundedTopOnly(ctx, box, scale) {
|
|
2313
|
+
this.#draw(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
2314
|
+
}
|
|
2315
|
+
DrawUnderline(ctx, box, scale) {
|
|
2316
|
+
this.#box(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
2317
|
+
ctx.beginPath();
|
|
2318
|
+
ctx.moveTo(box.Position.x, box.Position.y + box.Size.y);
|
|
2319
|
+
ctx.lineTo(box.Position.x + box.Size.x, box.Position.y + box.Size.y);
|
|
2320
|
+
ctx.stroke();
|
|
2321
|
+
}
|
|
2322
|
+
borderSize() {
|
|
2323
|
+
if (this.#border === null) {
|
|
2324
|
+
return 0;
|
|
2325
|
+
}
|
|
2326
|
+
return this.#border.size();
|
|
2327
|
+
}
|
|
2328
|
+
radius() {
|
|
2329
|
+
return this.#radius;
|
|
2330
|
+
}
|
|
2331
|
+
setColor(color) {
|
|
2332
|
+
this.#color = color;
|
|
2333
|
+
}
|
|
2334
|
+
setBorderColor(color) {
|
|
2335
|
+
if (this.#border === null) {
|
|
2336
|
+
this.#border = new StrokeStyle({
|
|
2337
|
+
color
|
|
2338
|
+
});
|
|
2339
|
+
} else {
|
|
2340
|
+
this.#border.setColor(color);
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2343
|
+
};
|
|
2344
|
+
|
|
2345
|
+
// src/styles/bevel.ts
|
|
2346
|
+
function drawBevel(ctx, box, scale, colors, sunken) {
|
|
2347
|
+
const width2 = Math.max(1, 2 * scale);
|
|
2348
|
+
const half = width2 / 2;
|
|
2349
|
+
const left = box.Position.x + half;
|
|
2350
|
+
const top = box.Position.y + half;
|
|
2351
|
+
const right = box.Position.x + box.Size.x - half;
|
|
2352
|
+
const bottom = box.Position.y + box.Size.y - half;
|
|
2353
|
+
ctx.save();
|
|
2354
|
+
ctx.lineWidth = width2;
|
|
2355
|
+
ctx.lineCap = "square";
|
|
2356
|
+
ctx.strokeStyle = sunken ? colors.Dark : colors.Light;
|
|
2357
|
+
ctx.beginPath();
|
|
2358
|
+
ctx.moveTo(left, bottom);
|
|
2359
|
+
ctx.lineTo(left, top);
|
|
2360
|
+
ctx.lineTo(right, top);
|
|
2361
|
+
ctx.stroke();
|
|
2362
|
+
ctx.strokeStyle = sunken ? colors.Light : colors.Dark;
|
|
2363
|
+
ctx.beginPath();
|
|
2364
|
+
ctx.moveTo(right, top);
|
|
2365
|
+
ctx.lineTo(right, bottom);
|
|
2366
|
+
ctx.lineTo(left, bottom);
|
|
2367
|
+
ctx.stroke();
|
|
2368
|
+
ctx.restore();
|
|
2369
|
+
}
|
|
2370
|
+
|
|
2371
|
+
// src/widgets/field.ts
|
|
2372
|
+
function widgetFont(scale) {
|
|
2373
|
+
return `${Theme.Widget.FontSize * scale}px ${Theme.FontFamily}`;
|
|
2374
|
+
}
|
|
2375
|
+
function fieldBackground(look) {
|
|
2376
|
+
if (look.background !== void 0) {
|
|
2377
|
+
return look.background;
|
|
2378
|
+
}
|
|
2379
|
+
if (look.input) {
|
|
2380
|
+
return look.hovered ? Theme.Widget.Input.HoverBackgroundColor : Theme.Widget.Input.BackgroundColor;
|
|
2381
|
+
}
|
|
2382
|
+
if (look.pressed) {
|
|
2383
|
+
return Theme.Widget.Button.Click.BackgroundColor;
|
|
2384
|
+
}
|
|
2385
|
+
return look.hovered ? Theme.Widget.Hover.BackgroundColor : Theme.Widget.BackgroundColor;
|
|
2386
|
+
}
|
|
2387
|
+
function drawFieldBox(ctx, box, scale, look) {
|
|
2388
|
+
ctx.fillStyle = fieldBackground(look);
|
|
2389
|
+
ctx.beginPath();
|
|
2390
|
+
ctx.roundRect(box.Position.x, box.Position.y, box.Size.x, box.Size.y, Theme.Widget.Border.Radius * scale);
|
|
2391
|
+
ctx.fill();
|
|
2392
|
+
if (Theme.Widget.Border.Size > 0) {
|
|
2393
|
+
ctx.strokeStyle = look.border ?? Theme.Widget.Border.Color;
|
|
2394
|
+
ctx.lineWidth = Theme.Widget.Border.Size * scale;
|
|
2395
|
+
ctx.stroke();
|
|
2396
|
+
}
|
|
2397
|
+
if (Theme.Widget.Bevel !== null) {
|
|
2398
|
+
drawBevel(ctx, box, scale, Theme.Widget.Bevel, look.input === true || look.pressed === true);
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
function drawField(ctx, box, scale, look) {
|
|
2402
|
+
drawFieldBox(ctx, box, scale, look);
|
|
2403
|
+
drawFieldText(ctx, box, scale, look);
|
|
2404
|
+
}
|
|
2405
|
+
function drawFieldText(ctx, box, scale, look) {
|
|
2406
|
+
const padding = Theme.Widget.Padding * scale;
|
|
2407
|
+
const middle = box.Position.y + box.Size.y / 2;
|
|
2408
|
+
const textColor = look.textColor ?? (look.input ? Theme.Widget.Input.FontColor : Theme.Widget.FontColor);
|
|
2409
|
+
ctx.font = widgetFont(scale);
|
|
2410
|
+
ctx.textBaseline = "middle";
|
|
2411
|
+
if (look.label === void 0 || look.label === "") {
|
|
2412
|
+
ctx.textAlign = "center";
|
|
2413
|
+
ctx.fillStyle = textColor;
|
|
2414
|
+
ctx.fillText(
|
|
2415
|
+
fitString(ctx, look.value, box.Size.x - padding * 2),
|
|
2416
|
+
box.Position.x + box.Size.x / 2,
|
|
2417
|
+
middle
|
|
2418
|
+
);
|
|
2419
|
+
return;
|
|
2420
|
+
}
|
|
2421
|
+
const room = box.Size.x - padding * 2;
|
|
2422
|
+
const label = fitString(ctx, look.label, room / 2);
|
|
2423
|
+
const labelWidth = ctx.measureText(label).width;
|
|
2424
|
+
ctx.textAlign = "left";
|
|
2425
|
+
ctx.fillStyle = look.textColor ?? Theme.Widget.LabelColor;
|
|
2426
|
+
ctx.fillText(label, box.Position.x + padding, middle);
|
|
2427
|
+
ctx.textAlign = "right";
|
|
2428
|
+
ctx.fillStyle = textColor;
|
|
2429
|
+
ctx.fillText(
|
|
2430
|
+
fitString(ctx, look.value, room - labelWidth - padding),
|
|
2431
|
+
box.Position.x + box.Size.x - padding,
|
|
2432
|
+
middle
|
|
2433
|
+
);
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2385
2436
|
// src/widgets/value.ts
|
|
2386
2437
|
var ValueWidget = class extends WidgetBase {
|
|
2387
2438
|
#node;
|
|
@@ -5149,6 +5200,7 @@ var FlowNode = class {
|
|
|
5149
5200
|
#inputPortPositions;
|
|
5150
5201
|
#outputPortPositions;
|
|
5151
5202
|
#widgetPositions;
|
|
5203
|
+
#portWidgetPositions = new List();
|
|
5152
5204
|
#data;
|
|
5153
5205
|
#registeredAnyPropertyChangeCallbacks;
|
|
5154
5206
|
#registeredPropertyChangeCallbacks;
|
|
@@ -5636,9 +5688,10 @@ var FlowNode = class {
|
|
|
5636
5688
|
}
|
|
5637
5689
|
this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
|
|
5638
5690
|
size.y += this.#portRowHeight(port, tempMeasurement.y) + this.#elementSpacing;
|
|
5639
|
-
size.x = Math.max(size.x, tempMeasurement.x + doublePadding);
|
|
5691
|
+
size.x = Math.max(size.x, this.#portRowWidth(port, tempMeasurement.x) + doublePadding);
|
|
5640
5692
|
}
|
|
5641
|
-
|
|
5693
|
+
const widgets = this.#hasHiddenPortsToggle() ? [this.#hiddenPortsToggle, ...this.#widgets] : this.#widgets;
|
|
5694
|
+
for (const widget of widgets) {
|
|
5642
5695
|
if (widget.Hidden?.()) {
|
|
5643
5696
|
continue;
|
|
5644
5697
|
}
|
|
@@ -5656,6 +5709,9 @@ var FlowNode = class {
|
|
|
5656
5709
|
}
|
|
5657
5710
|
addInput(config) {
|
|
5658
5711
|
const port = new Port(this, config.array ? "INPUTARRAY" /* InputArray */ : "INPUT" /* Input */, config);
|
|
5712
|
+
if (config.widget !== void 0) {
|
|
5713
|
+
port.setWidget(GlobalWidgetFactory.createFromConfig(this, config.widget));
|
|
5714
|
+
}
|
|
5659
5715
|
this.#input.push(port);
|
|
5660
5716
|
return port;
|
|
5661
5717
|
}
|
|
@@ -5664,6 +5720,31 @@ var FlowNode = class {
|
|
|
5664
5720
|
this.#output.push(port);
|
|
5665
5721
|
return port;
|
|
5666
5722
|
}
|
|
5723
|
+
#hiddenPortsShown = false;
|
|
5724
|
+
#hiddenPortsToggle = new HiddenPortsToggle(this);
|
|
5725
|
+
#hiddenPortsTogglePosition = null;
|
|
5726
|
+
hiddenPortsShown() {
|
|
5727
|
+
return this.#hiddenPortsShown;
|
|
5728
|
+
}
|
|
5729
|
+
setHiddenPortsShown(shown) {
|
|
5730
|
+
if (shown === this.#hiddenPortsShown) {
|
|
5731
|
+
return;
|
|
5732
|
+
}
|
|
5733
|
+
this.#hiddenPortsShown = shown;
|
|
5734
|
+
this.invalidateLayout();
|
|
5735
|
+
}
|
|
5736
|
+
hiddenPortCount() {
|
|
5737
|
+
let count = 0;
|
|
5738
|
+
for (const port of [...this.#input, ...this.#output]) {
|
|
5739
|
+
if (port.tucked()) {
|
|
5740
|
+
count++;
|
|
5741
|
+
}
|
|
5742
|
+
}
|
|
5743
|
+
return count;
|
|
5744
|
+
}
|
|
5745
|
+
#hasHiddenPortsToggle() {
|
|
5746
|
+
return this.hiddenPortCount() > 0;
|
|
5747
|
+
}
|
|
5667
5748
|
addWidget(widget) {
|
|
5668
5749
|
this.#widgets.push(widget);
|
|
5669
5750
|
requestRender();
|
|
@@ -5742,6 +5823,11 @@ var FlowNode = class {
|
|
|
5742
5823
|
intersection.Port = this.#output[i];
|
|
5743
5824
|
}
|
|
5744
5825
|
}
|
|
5826
|
+
if (this.#hiddenPortsTogglePosition !== null && InBox(this.#hiddenPortsTogglePosition, position)) {
|
|
5827
|
+
intersection.Node = this;
|
|
5828
|
+
intersection.Widget = this.#hiddenPortsToggle;
|
|
5829
|
+
intersection.WidgetBox = this.#hiddenPortsTogglePosition;
|
|
5830
|
+
}
|
|
5745
5831
|
for (let i = 0; i < this.#widgetPositions.Count(); i++) {
|
|
5746
5832
|
const widget = this.#widgets[i];
|
|
5747
5833
|
if (widget !== void 0 && !widget.Hidden?.() && InBox(this.#widgetPositions.At(i), position)) {
|
|
@@ -5751,6 +5837,17 @@ var FlowNode = class {
|
|
|
5751
5837
|
intersection.WidgetBox = this.#widgetPositions.At(i);
|
|
5752
5838
|
}
|
|
5753
5839
|
}
|
|
5840
|
+
for (let i = 0; i < this.#portWidgetPositions.Count(); i++) {
|
|
5841
|
+
const port = this.#input[i];
|
|
5842
|
+
if (port !== void 0 && port.widgetShown() && InBox(this.#portWidgetPositions.At(i), position)) {
|
|
5843
|
+
intersection.Node = this;
|
|
5844
|
+
intersection.Widget = port.widget();
|
|
5845
|
+
intersection.WidgetBox = this.#portWidgetPositions.At(i);
|
|
5846
|
+
intersection.Port = void 0;
|
|
5847
|
+
intersection.PortIndex = void 0;
|
|
5848
|
+
intersection.PortIsInput = void 0;
|
|
5849
|
+
}
|
|
5850
|
+
}
|
|
5754
5851
|
return intersection;
|
|
5755
5852
|
}
|
|
5756
5853
|
canEditTitle() {
|
|
@@ -5865,7 +5962,14 @@ var FlowNode = class {
|
|
|
5865
5962
|
}
|
|
5866
5963
|
#portRowHeight(port, textHeight) {
|
|
5867
5964
|
const slots = port.slots();
|
|
5868
|
-
|
|
5965
|
+
const widget = port.widgetShown() ? port.widget().Size().y : 0;
|
|
5966
|
+
return Math.max(slots > 1 ? slots * ARRAY_SLOT_PITCH : 0, textHeight, widget);
|
|
5967
|
+
}
|
|
5968
|
+
#portRowWidth(port, textWidth) {
|
|
5969
|
+
if (!port.widgetShown()) {
|
|
5970
|
+
return textWidth;
|
|
5971
|
+
}
|
|
5972
|
+
return textWidth + this.#elementSpacing + port.widget().Size().x;
|
|
5869
5973
|
}
|
|
5870
5974
|
hasBeenLaidOut() {
|
|
5871
5975
|
return this.#laidOut;
|
|
@@ -5887,6 +5991,7 @@ var FlowNode = class {
|
|
|
5887
5991
|
this.#inputPortPositions.Clear();
|
|
5888
5992
|
this.#outputPortPositions.Clear();
|
|
5889
5993
|
this.#widgetPositions.Clear();
|
|
5994
|
+
this.#portWidgetPositions.Clear();
|
|
5890
5995
|
const scaledPadding = this.#padding * camera.zoom;
|
|
5891
5996
|
const scaledElementSpacing = this.#elementSpacing * camera.zoom;
|
|
5892
5997
|
const nodeBounds = this.calculateBounds(ctx, camera);
|
|
@@ -5981,6 +6086,7 @@ var FlowNode = class {
|
|
|
5981
6086
|
const port = this.#input[i];
|
|
5982
6087
|
if (port.hidden()) {
|
|
5983
6088
|
this.#inputPortPositions.Push({ Position: { x: nodeBounds.Position.x, y: startY }, Size: { x: 0, y: 0 } });
|
|
6089
|
+
this.#portWidgetPositions.Push({ Position: { x: nodeBounds.Position.x, y: startY }, Size: { x: 0, y: 0 } });
|
|
5984
6090
|
continue;
|
|
5985
6091
|
}
|
|
5986
6092
|
this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
|
|
@@ -5990,6 +6096,19 @@ var FlowNode = class {
|
|
|
5990
6096
|
position.y = startY + portHeight / 2;
|
|
5991
6097
|
this.#portTextStyle.setupStyle(ctx, camera.zoom);
|
|
5992
6098
|
ctx.fillText(port.getDisplayName(), leftSide, position.y);
|
|
6099
|
+
if (port.widgetShown()) {
|
|
6100
|
+
const widget = port.widget();
|
|
6101
|
+
const widgetHeight = widget.Size().y * camera.zoom;
|
|
6102
|
+
const widgetLeft = leftSide + tempMeasurement.x * camera.zoom + scaledElementSpacing;
|
|
6103
|
+
const box = {
|
|
6104
|
+
Position: { x: widgetLeft, y: startY + (portHeight - widgetHeight) / 2 },
|
|
6105
|
+
Size: { x: nodeBounds.Position.x + nodeBounds.Size.x - scaledPadding - widgetLeft, y: widgetHeight }
|
|
6106
|
+
};
|
|
6107
|
+
widget.Draw(ctx, box, camera.zoom, mousePosition);
|
|
6108
|
+
this.#portWidgetPositions.Push(box);
|
|
6109
|
+
} else {
|
|
6110
|
+
this.#portWidgetPositions.Push({ Position: { x: nodeBounds.Position.x, y: startY }, Size: { x: 0, y: 0 } });
|
|
6111
|
+
}
|
|
5993
6112
|
this.#inputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));
|
|
5994
6113
|
startY += portHeight + scaledElementSpacing;
|
|
5995
6114
|
}
|
|
@@ -6011,6 +6130,16 @@ var FlowNode = class {
|
|
|
6011
6130
|
this.#outputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));
|
|
6012
6131
|
startY += portHeight + scaledElementSpacing;
|
|
6013
6132
|
}
|
|
6133
|
+
this.#hiddenPortsTogglePosition = null;
|
|
6134
|
+
if (this.#hasHiddenPortsToggle()) {
|
|
6135
|
+
const box = {
|
|
6136
|
+
Position: { x: nodeBounds.Position.x + scaledPadding, y: startY },
|
|
6137
|
+
Size: { x: nodeBounds.Size.x - scaledPadding * 2, y: this.#hiddenPortsToggle.Size().y * camera.zoom }
|
|
6138
|
+
};
|
|
6139
|
+
this.#hiddenPortsToggle.Draw(ctx, box, camera.zoom, mousePosition);
|
|
6140
|
+
this.#hiddenPortsTogglePosition = box;
|
|
6141
|
+
startY += box.Size.y + scaledElementSpacing;
|
|
6142
|
+
}
|
|
6014
6143
|
for (let i = 0; i < this.#widgets.length; i++) {
|
|
6015
6144
|
const widget = this.#widgets[i];
|
|
6016
6145
|
if (widget.Hidden?.()) {
|
|
@@ -6065,6 +6194,8 @@ var FlowNode = class {
|
|
|
6065
6194
|
return false;
|
|
6066
6195
|
}
|
|
6067
6196
|
this.#widgetPositions.Clear();
|
|
6197
|
+
this.#portWidgetPositions.Clear();
|
|
6198
|
+
this.#hiddenPortsTogglePosition = null;
|
|
6068
6199
|
return true;
|
|
6069
6200
|
}
|
|
6070
6201
|
placePorts(bounds, zoom) {
|
|
@@ -7725,8 +7856,8 @@ var NodeFlowGraph = class {
|
|
|
7725
7856
|
this.#clickEnd.bind(this),
|
|
7726
7857
|
this.#openContextMenu.bind(this),
|
|
7727
7858
|
this.#fileDrop.bind(this),
|
|
7728
|
-
(
|
|
7729
|
-
this
|
|
7859
|
+
(factor, anchor) => {
|
|
7860
|
+
this.#zoomBy(factor, anchor);
|
|
7730
7861
|
}
|
|
7731
7862
|
);
|
|
7732
7863
|
document.addEventListener(
|
|
@@ -7854,12 +7985,15 @@ var NodeFlowGraph = class {
|
|
|
7854
7985
|
this.#mainNoteSubsystem.addNoteDragStopListener(callback);
|
|
7855
7986
|
}
|
|
7856
7987
|
zoom(amount, anchor) {
|
|
7988
|
+
this.#zoomBy(1 + amount * 0.05, anchor);
|
|
7989
|
+
}
|
|
7990
|
+
#zoomBy(factor, anchor) {
|
|
7857
7991
|
const anchorPos = anchor ?? this.#mousePosition;
|
|
7858
7992
|
let oldPos = void 0;
|
|
7859
7993
|
if (anchorPos !== void 0) {
|
|
7860
7994
|
oldPos = this.#sceenPositionToGraphPosition(anchorPos);
|
|
7861
7995
|
}
|
|
7862
|
-
this.#camera.zoom
|
|
7996
|
+
this.#camera.zoom *= factor;
|
|
7863
7997
|
if (!oldPos || anchorPos === void 0) {
|
|
7864
7998
|
return;
|
|
7865
7999
|
}
|