@elicdavis/node-flow 0.1.10 → 0.1.12

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/theme.ts", "../../src/styles/text.ts", "../../src/types/pool.ts", "../../src/types/vector2.ts", "../../src/types/box.ts", "../../src/types/list.ts", "../../src/contextMenu.ts", "../../src/input.ts", "../../src/elements/interfaces.ts", "../../src/elements/base.ts", "../../src/elements/container.ts", "../../src/elements/text.ts", "../../src/utils/string.ts", "../../src/types/text.ts", "../../src/utils/math.ts", "../../src/utils/color.ts", "../../src/port.ts", "../../src/styles/stroke.ts", "../../src/styles/box.ts", "../../src/popup.ts", "../../src/styles/textBox.ts", "../../src/widgets/widget.ts", "../../src/widgets/number.ts", "../../src/widgets/button.ts", "../../src/widgets/color.ts", "../../src/widgets/slider.ts", "../../src/popups/string.ts", "../../src/widgets/string.ts", "../../src/widgets/toggle.ts", "../../src/widgets/image.ts", "../../src/widgets/text.ts", "../../src/widgets/factory.ts", "../../src/connection.ts", "../../src/camera.ts", "../../src/organize.ts", "../../src/performance.ts", "../../src/nodes/publisher.ts", "../../src/nodes/factory.ts", "../../src/nodes/subsystem.ts", "../../src/popups/form.ts", "../../src/node.ts", "../../src/markdown/token.ts", "../../src/markdown/lexicalParser.ts", "../../src/markdown/entry.ts", "../../src/markdown/syntaxParser.ts", "../../src/markdown/markdown.ts", "../../src/notes/note.ts", "../../src/notes/subsystem.ts", "../../src/pass/subsystem.ts", "../../src/quickMenu.ts", "../../src/graph.ts"],
4
+ "sourcesContent": ["export const Theme = {\r\n FontFamily: \"Courier New\",\r\n Graph: {\r\n BackgroundColor: \"#07212a\",\r\n },\r\n Node: {\r\n FontColor: \"#afb9bb\",\r\n BackgroundColor: \"#0c2b35\",\r\n Title: {\r\n Color: \"#154050\",\r\n FontColor: \"#afb9bb\",\r\n Padding: 5\r\n },\r\n BorderRadius: 15,\r\n Border: {\r\n Idle: \"#1c1c1c\",\r\n MouseOver: \"#8e8e8e\",\r\n Grabbed: \"white\",\r\n Selected: \"#6e6e6e\"\r\n },\r\n Port: {\r\n FontColor: \"#afb9bb\"\r\n },\r\n Message: {\r\n InfoColor: \"#afb9bb\",\r\n WarnColor: \"#f1f663ff\",\r\n ErrorColor: \"#FF0000\"\r\n }\r\n },\r\n BoxSelect: {\r\n Color: \"white\",\r\n Size: 1,\r\n Radius: 2,\r\n LineDashLength: 5,\r\n },\r\n Widget: {\r\n FontColor: \"#afb9bb\",\r\n BackgroundColor: \"#0f313c\",\r\n Border: {\r\n Color: \"#154050\",\r\n Size: 2,\r\n Radius: 2\r\n },\r\n Hover: {\r\n BackgroundColor: \"#195366\"\r\n },\r\n Slider: {\r\n FillColor: \"#07212A\",\r\n },\r\n Button: {\r\n Click: {\r\n BackgroundColor: \"#1f637a\"\r\n },\r\n }\r\n },\r\n ContextMenu: {\r\n BackgroundColor: \"#07212A\",\r\n HighlightColor: \"#205A6D\",\r\n FontColor: \"#afb9bb\",\r\n },\r\n Note: {\r\n FontColor: \"#afb9bb\",\r\n FontSize: 16,\r\n EntrySpacing: 20,\r\n LineSpacing: 5,\r\n DotSize: 3,\r\n HeaderLineWidth: 2,\r\n H1: {\r\n FontSize: 32,\r\n },\r\n H2: {\r\n FontSize: 16,\r\n },\r\n H3: {\r\n FontSize: 16,\r\n },\r\n CodeBlock: {\r\n BackgroundColor: \"#0c2b35\",\r\n Padding: 16,\r\n BorderRadius: 4,\r\n }\r\n }\r\n}", "import { Theme } from \"../theme\";\r\nimport { Vector2 } from \"../types/vector2\";\r\n\r\nexport enum FontWeight {\r\n Normal = \"\",\r\n Bold = \"bold\"\r\n}\r\n\r\nexport enum FontStyle {\r\n Normal = \"\",\r\n Italic = \"italic\"\r\n}\r\n\r\nexport interface TextStyleConfig {\r\n size?: number;\r\n color?: string;\r\n font?: string;\r\n weight?: FontWeight;\r\n style?: FontStyle;\r\n}\r\n\r\nconst DefaultSize: number = 16;\r\nconst DefaultColor: string = \"black\";\r\n\r\nexport function TextStyleFallback(input?: TextStyleConfig, fallback?: TextStyleConfig): TextStyleConfig {\r\n return {\r\n color: input?.color === undefined ? fallback?.color : input?.color,\r\n size: input?.size === undefined ? fallback?.size : input?.size,\r\n font: input?.font === undefined ? fallback?.font : input?.font,\r\n style: input?.style === undefined ? fallback?.style : input?.style,\r\n weight: input?.weight === undefined ? fallback?.weight : input?.weight,\r\n };\r\n}\r\n\r\nexport class TextStyle {\r\n\r\n #size: number;\r\n\r\n #color: string;\r\n\r\n #font: string;\r\n\r\n #weight: FontWeight;\r\n\r\n #fontStyle: FontStyle;\r\n\r\n constructor(config: TextStyleConfig | undefined) {\r\n this.#size = config?.size === undefined ? DefaultSize : config.size;\r\n this.#color = config?.color === undefined ? DefaultColor : config.color;\r\n this.#font = config?.font === undefined ? Theme.FontFamily : config.font;\r\n this.#weight = config?.weight === undefined ? FontWeight.Normal : config.weight;\r\n this.#fontStyle = config?.style === undefined ? FontStyle.Normal : config.style;\r\n }\r\n\r\n setupStyle(ctx: CanvasRenderingContext2D, scale: number): void {\r\n ctx.fillStyle = this.#color;\r\n ctx.font = this.#fontStyle + \" \" + this.#weight + \" \" + (this.#size * scale) + \"px \" + this.#font;\r\n }\r\n\r\n getSize(): number {\r\n return this.#size;\r\n }\r\n\r\n getFont(): string {\r\n return this.#font;\r\n }\r\n\r\n measure(ctx: CanvasRenderingContext2D, scale: number, text: string, out: Vector2): void {\r\n this.setupStyle(ctx, scale);\r\n const measurements = ctx.measureText(text)\r\n out.x = measurements.width;\r\n out.y = measurements.actualBoundingBoxAscent + measurements.actualBoundingBoxDescent;\r\n }\r\n\r\n setColor(color: string): void {\r\n this.#color = color;\r\n }\r\n\r\n getColor(): string {\r\n return this.#color ;\r\n }\r\n\r\n setSize(size: number): void {\r\n this.#size = size;\r\n }\r\n\r\n setWeight(weight: FontWeight): void {\r\n this.#weight = weight;\r\n }\r\n}", "import { Vector2 } from \"./vector2\";\r\n\r\n\r\n\r\nexport class Pool<Type> {\r\n\r\n #arr: Array<Type>;\r\n\r\n #count: number;\r\n\r\n #builder: () => Type;\r\n\r\n #reset: (v: Type) => void;\r\n\r\n #runningDepth: number;\r\n\r\n constructor(builder: () => Type, reset: (v: Type) => void) {\r\n this.#arr = new Array<Type>();\r\n this.#count = 0;\r\n this.#builder = builder;\r\n this.#reset = reset;\r\n this.#runningDepth = 0;\r\n }\r\n\r\n public runIf(condition: boolean, fn: () => void) {\r\n if (condition) {\r\n this.run(fn);\r\n }\r\n }\r\n\r\n #running(): boolean {\r\n return this.#runningDepth > 0;\r\n }\r\n\r\n public run(fn: () => void) {\r\n const start = this.#count;\r\n this.#runningDepth += 1;\r\n fn();\r\n this.#runningDepth -= 1;\r\n this.#count = start;\r\n // console.log(this.#arr.length);\r\n }\r\n\r\n get(): Type {\r\n if(!this.#running()) {\r\n throw new Error(\"can't use pool outside of running context\");\r\n }\r\n\r\n let value: Type;\r\n if (this.#arr.length === this.#count) {\r\n value = this.#builder();\r\n this.#arr.push(this.#builder());\r\n } else {\r\n value = this.#arr[this.#count];\r\n this.#reset(value);\r\n }\r\n this.#count++;\r\n return value;\r\n }\r\n\r\n}\r\n\r\nexport const VectorPool = new Pool<Vector2>(\r\n () => ({ x: 0, y: 0 }),\r\n (v) => { v.x = 0; v.y = 0; }\r\n)\r\n", "export interface Vector2 {\r\n x: number\r\n y: number\r\n}\r\n\r\nexport function CopyVector2(dst: Vector2, src: Vector2): void {\r\n dst.x = src.x;\r\n dst.y = src.y;\r\n}\r\n\r\nexport function SubVector2(dst: Vector2, a: Vector2, b: Vector2): void {\r\n dst.x = a.x - b.x;\r\n dst.y = a.y - b.y;\r\n}\r\n\r\nexport function AddVector2(dst: Vector2, a: Vector2, b: Vector2): void {\r\n dst.x = a.x + b.x;\r\n dst.y = a.y + b.y;\r\n}\r\n\r\nexport function ScaleVector(dst: Vector2, scale: number): void {\r\n dst.x *= scale;\r\n dst.y *= scale;\r\n}\r\n\r\nexport function Zero(): Vector2 {\r\n return { x: 0, y: 0 };\r\n}\r\n\r\nexport function Distance(a: Vector2, b: Vector2): number { \r\n const xd = b.x - a.x\r\n const yd = b.y - a.y\r\n return Math.sqrt((xd*xd)+(yd*yd))\r\n}\r\n", "import { VectorPool } from \"./pool\";\r\nimport { AddVector2, CopyVector2, SubVector2, Vector2, Zero } from \"./vector2\";\r\n\r\nexport interface Box {\r\n Position: Vector2\r\n Size: Vector2\r\n}\r\n\r\nexport function CopyBox(dst: Box, src: Box): void {\r\n dst.Position.x = src.Position.x;\r\n dst.Position.y = src.Position.y;\r\n dst.Size.x = src.Size.x;\r\n dst.Size.y = src.Size.y;\r\n}\r\n\r\nfunction normalizeMinMax(min: Vector2, max: Vector2) {\r\n if (min.x > max.x) {\r\n let temp = max.x;\r\n max.x = min.x;\r\n min.x = temp;\r\n }\r\n\r\n if (min.y > max.y) {\r\n let temp = max.y;\r\n max.y = min.y;\r\n min.y = temp;\r\n }\r\n}\r\n\r\nexport function BoxIntersection(a: Box, b: Box): boolean {\r\n let intersects = false;\r\n\r\n VectorPool.run(() => {\r\n const aMin = VectorPool.get();\r\n const aMax = VectorPool.get();\r\n CopyVector2(aMin, a.Position);\r\n AddVector2(aMax, aMin, a.Size);\r\n normalizeMinMax(aMin, aMax);\r\n\r\n const bMin = VectorPool.get();\r\n const bMax = VectorPool.get();\r\n CopyVector2(bMin, b.Position);\r\n AddVector2(bMax, bMin, b.Size);\r\n normalizeMinMax(bMin, bMax);\r\n\r\n intersects = (aMin.x <= bMax.x) && (aMax.x >= bMin.x) &&\r\n (aMin.y <= bMax.y) && (aMax.y >= bMin.y);\r\n })\r\n\r\n return intersects;\r\n}\r\n\r\n// TODO: This is probably incorrect. Needs more testing\r\n// export function ExpandBox(boxToExpand: Box, box: Box): void {\r\n// const newPos: Vector2 = Zero();\r\n// const newSize: Vector2 = Zero();\r\n\r\n// CopyVector2(newPos, boxToExpand.Position);\r\n// CopyVector2(newSize, boxToExpand.Size);\r\n\r\n\r\n// const positionOffset: Vector2 = Zero();\r\n\r\n// // Get Position Adjustment\r\n// SubVector2(positionOffset, box.Position, boxToExpand.Position);\r\n\r\n// // We only care about adjustments that make us bigger.\r\n// positionOffset.x = Math.min(positionOffset.x, 0);\r\n// positionOffset.y = Math.min(positionOffset.y, 0);\r\n\r\n// // Adjust our position \r\n// AddVector2(boxToExpand.Position, boxToExpand.Position, positionOffset);\r\n\r\n// // Increase our size to take into account new position\r\n// SubVector2(newSize, newSize, positionOffset);\r\n\r\n// const sizeIncrease: Vector2 = Zero();\r\n\r\n// const curEndPos: Vector2 = {\r\n// x: boxToExpand.Position.x + boxToExpand.Size.x,\r\n// y: boxToExpand.Position.y + boxToExpand.Size.y,\r\n// };\r\n\r\n// const boxEndPos: Vector2 = {\r\n// x: box.Position.x + box.Size.x,\r\n// y: box.Position.y + box.Size.y,\r\n// };\r\n\r\n// SubVector2(sizeIncrease, boxEndPos, curEndPos);\r\n\r\n// // We only care about increases to our size\r\n// sizeIncrease.x = Math.max(sizeIncrease.x, 0);\r\n// sizeIncrease.y = Math.max(sizeIncrease.y, 0);\r\n\r\n// // Increase our size to take into account new position\r\n// SubVector2(newSize, newSize, sizeIncrease)\r\n\r\n// // Finally, Set result\r\n// CopyVector2(boxToExpand.Position, newPos)\r\n// CopyVector2(boxToExpand.Size, newSize)\r\n// }\r\n\r\nexport function BoxCenter(box: Box, out: Vector2): Vector2 {\r\n out.x = box.Position.x + (box.Size.x / 2);\r\n out.y = box.Position.y + (box.Size.y / 2);\r\n return out\r\n}\r\n\r\nexport function InBox(box: Box, position: Vector2): boolean {\r\n const min = box.Position\r\n if (position.x < min.x) {\r\n return false\r\n }\r\n if (position.y < min.y) {\r\n return false\r\n }\r\n\r\n if (position.x > min.x + box.Size.x) {\r\n return false\r\n }\r\n if (position.y > min.y + box.Size.y) {\r\n return false\r\n }\r\n\r\n return true\r\n}", "export class List<Type> {\r\n\r\n #arr: Array<Type>;\r\n\r\n #count: number;\r\n\r\n constructor() {\r\n this.#arr = new Array<Type>();\r\n this.#count = 0;\r\n }\r\n\r\n public Count(): number {\r\n return this.#count;\r\n }\r\n\r\n public Clear(): void {\r\n this.#count = 0;\r\n }\r\n\r\n public At(index: number): Type {\r\n return this.#arr[index];\r\n }\r\n\r\n public Push(value: Type): void {\r\n if (this.#arr.length === this.#count) {\r\n this.#arr.push(value);\r\n } else {\r\n this.#arr[this.#count] = value;\r\n }\r\n this.#count++;\r\n }\r\n\r\n public ToArray(): Array<Type> {\r\n let arr = new Array<Type>(this.Count());\r\n for(let i = 0; i < this.#count; i ++) {\r\n arr[i] = this.#arr[i]\r\n }\r\n return arr;\r\n }\r\n\r\n}", "import { Theme } from './theme';\r\nimport { TextAlign } from './styles/canvasTextAlign';\r\nimport { TextStyle, TextStyleConfig, TextStyleFallback } from './styles/text';\r\nimport { Box, InBox } from './types/box';\r\nimport { List } from './types/list';\r\nimport { CopyVector2, Vector2, Zero } from './types/vector2';\r\n\r\nconst contextEntryHeight = 30;\r\nconst contextEntryWidth = 250;\r\n\r\nexport interface ContextMenuItemConfig {\r\n name?: string;\r\n textStyle?: TextStyleConfig;\r\n group?: string;\r\n\r\n callback?: () => void;\r\n}\r\n\r\nexport interface ContextMenuConfig {\r\n name?: string;\r\n textStyle?: TextStyleConfig;\r\n group?: string;\r\n\r\n subMenus?: Array<ContextMenuConfig>;\r\n items?: Array<ContextMenuItemConfig>;\r\n}\r\n\r\n\r\nexport class ContextMenuItem {\r\n #name: string;\r\n\r\n #callback?: () => void;\r\n\r\n #textStyle: TextStyle;\r\n\r\n public group?: string;\r\n\r\n constructor(config?: ContextMenuItemConfig) {\r\n this.#name = config?.name === undefined ? \"item\" : config.name;\r\n this.#callback = config?.callback;\r\n this.#textStyle = new TextStyle(config?.textStyle);\r\n this.group = config?.group;\r\n }\r\n\r\n getName(): string {\r\n return this.#name;\r\n }\r\n\r\n execute(): void {\r\n if (this.#callback === undefined) {\r\n return;\r\n }\r\n this.#callback();\r\n }\r\n}\r\n\r\nclass ContextGroup {\r\n\r\n #calculatedHeight: number;\r\n\r\n constructor(public entries: Array<ContextEntry>) {\r\n this.#calculatedHeight = entries.length * contextEntryHeight\r\n }\r\n\r\n height() {\r\n return this.#calculatedHeight;\r\n }\r\n\r\n}\r\n\r\nexport class ContextEntry {\r\n constructor(public text: string, public subMenu: ContextMenu | undefined, public item: ContextMenuItem | undefined) {\r\n }\r\n\r\n click(): void {\r\n this.item?.execute();\r\n }\r\n}\r\n\r\nexport function CombineContextMenus(...contextMenus: Array<ContextMenuConfig | undefined>): ContextMenuConfig {\r\n const finalConfig: ContextMenuConfig = {\r\n items: new Array<ContextMenuItemConfig>,\r\n subMenus: new Array<ContextMenuConfig>,\r\n }\r\n\r\n for (let i = 0; i < contextMenus.length; i++) {\r\n const config = contextMenus[i];\r\n if (config === undefined) {\r\n continue;\r\n }\r\n\r\n if (config.items !== undefined) {\r\n finalConfig.items = finalConfig.items?.concat(config.items);\r\n }\r\n\r\n if (config.subMenus !== undefined) {\r\n finalConfig.subMenus = finalConfig.subMenus?.concat(config.subMenus);\r\n }\r\n }\r\n\r\n return finalConfig;\r\n}\r\n\r\nexport class ContextMenu {\r\n\r\n #name: string;\r\n\r\n #items: Array<ContextMenuItem>;\r\n\r\n #subMenus: Array<ContextMenu>;\r\n\r\n #textStyle: TextStyle;\r\n\r\n #groups: List<ContextGroup>;\r\n\r\n #group?: string;\r\n\r\n #submenuPosition: Vector2;\r\n\r\n constructor(config?: ContextMenuConfig) {\r\n this.#submenuPosition = Zero();\r\n this.#groups = new List<ContextGroup>();\r\n this.#name = config?.name === undefined ? \"menu\" : config?.name;\r\n this.#items = new Array<ContextMenuItem>();\r\n this.#subMenus = new Array<ContextMenu>();\r\n this.#textStyle = new TextStyle(TextStyleFallback(config?.textStyle, {\r\n color: Theme.ContextMenu.FontColor\r\n }));\r\n this.#group = config?.group;\r\n\r\n if (config?.subMenus !== undefined) {\r\n for (let i = 0; i < config?.subMenus.length; i++) {\r\n this.#subMenus.push(new ContextMenu(config?.subMenus[i]));\r\n }\r\n }\r\n\r\n if (config?.items !== undefined) {\r\n for (let i = 0; i < config?.items.length; i++) {\r\n this.#items.push(new ContextMenuItem(config?.items[i]));\r\n }\r\n }\r\n\r\n this.#calculateEntries();\r\n }\r\n\r\n #calculateEntries(): void {\r\n\r\n const groupLUT = new Map<string, number>();\r\n const workingGroups = new Array<Array<ContextEntry>>();\r\n\r\n // Initialize first group for undefined entries\r\n workingGroups.push(new Array<ContextEntry>());\r\n\r\n for (let i = 0; i < this.#items.length; i++) {\r\n let group = 0; // index to undefined entries\r\n\r\n // Find collection that this entry belongs too\r\n const sub = this.#items[i]\r\n if (sub.group !== undefined) {\r\n const groupIndex = groupLUT.get(sub.group)\r\n if (groupIndex !== undefined) {\r\n group = groupIndex\r\n } else {\r\n group = workingGroups.length\r\n groupLUT.set(sub.group, group)\r\n workingGroups.push(new Array<ContextEntry>());\r\n }\r\n }\r\n\r\n workingGroups[group].push(new ContextEntry(\r\n this.#items[i].getName(),\r\n undefined,\r\n this.#items[i]\r\n ));\r\n }\r\n\r\n for (let i = 0; i < this.#subMenus.length; i++) {\r\n let group = 0; // index to undefined entries\r\n\r\n // Find collection that this entry belongs too\r\n const sub = this.#subMenus[i]\r\n if (sub.#group !== undefined) {\r\n const groupIndex = groupLUT.get(sub.#group)\r\n if (groupIndex !== undefined) {\r\n group = groupIndex\r\n } else {\r\n group = workingGroups.length\r\n groupLUT.set(sub.#group, group)\r\n workingGroups.push(new Array<ContextEntry>());\r\n }\r\n }\r\n\r\n workingGroups[group].push(new ContextEntry(\r\n this.#subMenus[i].getName(),\r\n this.#subMenus[i],\r\n undefined\r\n ));\r\n }\r\n\r\n this.#groups.Clear();\r\n for (let i = 0; i < workingGroups.length; i++) {\r\n const groupContent = workingGroups[i];\r\n if (groupContent.length === 0) {\r\n continue;\r\n }\r\n this.#groups.Push(new ContextGroup(groupContent));\r\n }\r\n }\r\n\r\n #calculatedWidth: number = 0;\r\n\r\n #getMaxWidthForText(ctx: CanvasRenderingContext2D, scale: number): number {\r\n if (this.#calculatedWidth > 0) {\r\n return this.#calculatedWidth;\r\n }\r\n\r\n const tempVec = Zero();\r\n for (let groupIndex = 0; groupIndex < this.#groups.Count(); groupIndex++) {\r\n const group = this.#groups.At(groupIndex);\r\n for (let entryIndex = 0; entryIndex < group.entries.length; entryIndex++) {\r\n this.#textStyle.measure(ctx, scale, group.entries[entryIndex].text, tempVec);\r\n this.#calculatedWidth = Math.max(tempVec.x, this.#calculatedWidth);\r\n }\r\n }\r\n return this.#calculatedWidth;\r\n }\r\n\r\n getName(): string {\r\n return this.#name;\r\n }\r\n\r\n #tempBox: Box = { Position: Zero(), Size: Zero() };\r\n\r\n #openSubMenu: ContextMenu | undefined;\r\n\r\n\r\n public render(ctx: CanvasRenderingContext2D, pppp: Vector2, graphScale: number, mousePosition: Vector2 | undefined, openRight: boolean): ContextEntry | null {\r\n const menuScale = 1.25;\r\n const scaledEntryHeight = menuScale * contextEntryHeight;\r\n const scaledEntryWidth = (menuScale * 40) + (this.#getMaxWidthForText(ctx, menuScale)); // contextEntryWidth;\r\n\r\n let totalScaledHeight = 0\r\n for (let i = 0; i < this.#groups.Count(); i++) {\r\n totalScaledHeight += this.#groups.At(i).height();\r\n }\r\n totalScaledHeight *= menuScale;\r\n\r\n const position = { x: 0, y: 0 };\r\n CopyVector2(position, pppp)\r\n\r\n if (!openRight) {\r\n position.x -= scaledEntryWidth;\r\n }\r\n\r\n // Clamp the position so it's not spilling off the canvas\r\n if (position.y + totalScaledHeight > ctx.canvas.clientHeight) {\r\n position.y = ctx.canvas.clientHeight - totalScaledHeight;\r\n }\r\n\r\n let submenuOpenRight = openRight;\r\n if (openRight && position.x + scaledEntryWidth > ctx.canvas.clientWidth) {\r\n position.x = ctx.canvas.clientWidth - scaledEntryWidth;\r\n submenuOpenRight = !submenuOpenRight;\r\n }\r\n\r\n this.#tempBox.Size.x = scaledEntryWidth;\r\n this.#tempBox.Size.y = scaledEntryHeight;\r\n CopyVector2(this.#tempBox.Position, position)\r\n\r\n\r\n\r\n ctx.textAlign = TextAlign.Left;\r\n ctx.fillStyle = Theme.ContextMenu.BackgroundColor;\r\n ctx.shadowColor = \"#000000\";\r\n ctx.shadowBlur = 5 * menuScale;\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n position.x,\r\n this.#tempBox.Position.y,\r\n scaledEntryWidth,\r\n totalScaledHeight,\r\n 5 * menuScale\r\n );\r\n ctx.fill();\r\n ctx.shadowBlur = 0;\r\n\r\n let mouseIsOver: ContextEntry | null = null;\r\n let subOpenedThisFrame = false;\r\n\r\n let optionsRendered = 0;\r\n for (let groupIndex = 0; groupIndex < this.#groups.Count(); groupIndex++) {\r\n const group = this.#groups.At(groupIndex);\r\n for (let entryIndex = 0; entryIndex < group.entries.length; entryIndex++) {\r\n const entry = group.entries[entryIndex];\r\n\r\n this.#tempBox.Position.y = position.y + (scaledEntryHeight * optionsRendered);\r\n\r\n let entryMousedOver = false;\r\n if (mousePosition !== undefined && InBox(this.#tempBox, mousePosition)) {\r\n mouseIsOver = entry;\r\n entryMousedOver = true\r\n if (entry.subMenu !== undefined) {\r\n this.#openSubMenu = entry.subMenu;\r\n this.#submenuPosition.x = position.x\r\n this.#submenuPosition.y = this.#tempBox.Position.y;\r\n if (submenuOpenRight) {\r\n this.#submenuPosition.x += scaledEntryWidth\r\n }\r\n subOpenedThisFrame = true;\r\n } else {\r\n this.#openSubMenu = undefined;\r\n }\r\n }\r\n\r\n if (entryMousedOver || (this.#openSubMenu !== undefined && entry.subMenu === this.#openSubMenu)) {\r\n ctx.fillStyle = Theme.ContextMenu.HighlightColor;\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n position.x + (scaledEntryHeight / 10),\r\n this.#tempBox.Position.y + (scaledEntryHeight / 10),\r\n scaledEntryWidth - (scaledEntryHeight / 5),\r\n scaledEntryHeight - (scaledEntryHeight / 5),\r\n 5 * menuScale\r\n );\r\n ctx.fill();\r\n }\r\n\r\n this.#textStyle.setupStyle(ctx, menuScale);\r\n ctx.fillText(entry.text, position.x + (scaledEntryHeight / 5), this.#tempBox.Position.y + (scaledEntryHeight / 2))\r\n\r\n // Render arrows\r\n if (entry.subMenu !== undefined) {\r\n ctx.beginPath()\r\n ctx.strokeStyle = Theme.ContextMenu.FontColor;\r\n ctx.lineWidth = 1 * menuScale;\r\n ctx.lineTo(position.x + scaledEntryWidth - (scaledEntryHeight / 2.5), this.#tempBox.Position.y + (scaledEntryHeight / 3))\r\n ctx.lineTo(position.x + scaledEntryWidth - (scaledEntryHeight / 4), this.#tempBox.Position.y + (scaledEntryHeight / 2))\r\n ctx.lineTo(position.x + scaledEntryWidth - (scaledEntryHeight / 2.5), this.#tempBox.Position.y + scaledEntryHeight - (scaledEntryHeight / 3))\r\n ctx.stroke();\r\n }\r\n\r\n optionsRendered++;\r\n }\r\n\r\n // Draw a line seperating the groups\r\n if (groupIndex !== this.#groups.Count() - 1) {\r\n ctx.strokeStyle = Theme.ContextMenu.FontColor;\r\n ctx.lineWidth = .5 * menuScale;\r\n ctx.beginPath();\r\n const startX = position.x + (scaledEntryHeight / 10);\r\n const y = this.#tempBox.Position.y + scaledEntryHeight\r\n ctx.lineTo(startX, y);\r\n ctx.lineTo(startX + scaledEntryWidth - (scaledEntryHeight / 5), y);\r\n ctx.stroke();\r\n }\r\n }\r\n\r\n if (this.#openSubMenu !== undefined) {\r\n const mouseOverSub = this.#openSubMenu.render(ctx, this.#submenuPosition, menuScale, mousePosition, submenuOpenRight)\r\n if (mouseOverSub !== null) {\r\n mouseIsOver = mouseOverSub;\r\n }\r\n }\r\n\r\n return mouseIsOver;\r\n }\r\n}", "import { CopyVector2, SubVector2, Vector2, Zero } from \"./types/vector2\";\r\n\r\nexport class MouseObserver {\r\n\r\n #clicked: boolean;\r\n\r\n #lastTouch: Vector2;\r\n\r\n #ele: HTMLElement\r\n\r\n #lastMousePosition: Vector2;\r\n\r\n #dragCallback: (delta: Vector2) => void\r\n #moveCallback: (position: Vector2) => void\r\n #clickStart: (position: Vector2, shiftOrCtrl: boolean) => void\r\n #clickStop: () => void\r\n #contextMenu: (position: Vector2) => void\r\n\r\n constructor(\r\n ele: HTMLElement,\r\n dragCallback: (delta: Vector2) => void,\r\n moveCallback: (position: Vector2) => void,\r\n clickStart: (position: Vector2, shiftOrCtrl: boolean) => void,\r\n clickStop: () => void,\r\n contextMenu: (position: Vector2) => void,\r\n fileDrop: (file: File) => void\r\n ) {\r\n this.#ele = ele;\r\n this.#dragCallback = dragCallback;\r\n this.#moveCallback = moveCallback;\r\n this.#clickStart = clickStart;\r\n this.#clickStop = clickStop;\r\n this.#contextMenu = contextMenu;\r\n\r\n this.#clicked = false;\r\n this.#lastTouch = Zero();\r\n this.#lastMousePosition = Zero();\r\n\r\n // Down\r\n ele.addEventListener('mousedown', this.#down.bind(this), false);\r\n ele.addEventListener('touchstart', this.#touchDown.bind(this), false);\r\n\r\n // Up\r\n document.addEventListener('mouseup', this.#up.bind(this), false);\r\n document.addEventListener('touchend', this.#up.bind(this), false);\r\n\r\n // Move\r\n ele.addEventListener('mousemove', this.#move.bind(this), false);\r\n ele.addEventListener('touchmove', this.#moveTouch.bind(this), false);\r\n\r\n ele.addEventListener('drop', (ev) => {\r\n ev.preventDefault();\r\n console.log(ev)\r\n\r\n if (ev.dataTransfer?.items) {\r\n // Use DataTransferItemList interface to access the file(s)\r\n [...ev.dataTransfer.items].forEach((item, i) => {\r\n // If dropped items aren't files, reject them\r\n if (item.kind === \"file\") {\r\n const file = item.getAsFile();\r\n if (file) {\r\n fileDrop(file);\r\n console.log(file)\r\n console.log(`\u2026 file[${i}].name = ${file.name}`);\r\n }\r\n }\r\n });\r\n } else if (ev.dataTransfer) {\r\n // Use DataTransfer interface to access the file(s)\r\n [...ev.dataTransfer.files].forEach((file, i) => {\r\n console.log(`\u2026 file[${i}].name = ${file.name}`);\r\n });\r\n }\r\n });\r\n\r\n ele.addEventListener('dragover', (ev) => {\r\n ev.preventDefault();\r\n this.#moveCallback(this.#mousePosition(ev));\r\n // console.log(ev)\r\n });\r\n\r\n // Context\r\n ele.addEventListener('contextmenu', (evt) => {\r\n contextMenu(this.#mousePosition(evt));\r\n evt.preventDefault()\r\n }, false);\r\n }\r\n\r\n #mousePosition(event: MouseEvent | DragEvent): Vector2 {\r\n var rect = this.#ele.getBoundingClientRect();\r\n return {\r\n x: event.clientX - rect.left,\r\n y: event.clientY - rect.top\r\n }\r\n }\r\n\r\n #move(event: MouseEvent): void {\r\n const pos = this.#mousePosition(event);\r\n\r\n if (this.#clicked) {\r\n const delta = Zero();\r\n SubVector2(delta, pos, this.#lastMousePosition);\r\n this.#dragCallback(delta)\r\n }\r\n\r\n this.#moveCallback(pos);\r\n CopyVector2(this.#lastMousePosition, pos);\r\n }\r\n\r\n #moveTouch(event: TouchEvent): void {\r\n const rect = this.#ele.getBoundingClientRect();\r\n const pos = {\r\n x: event.touches[0].clientX - rect.left,\r\n y: event.touches[0].clientY - rect.top\r\n }\r\n this.#moveCallback(pos);\r\n\r\n if (this.#clicked) {\r\n this.#dragCallback({\r\n x: pos.x - this.#lastTouch.x,\r\n y: pos.y - this.#lastTouch.y,\r\n });\r\n }\r\n\r\n CopyVector2(this.#lastTouch, pos);\r\n }\r\n\r\n #down(event: MouseEvent): void {\r\n // Only register left clicks\r\n if (event.button !== 0) {\r\n return;\r\n }\r\n this.#clicked = true;\r\n this.#clickStart(this.#mousePosition(event), event.ctrlKey || event.shiftKey);\r\n }\r\n\r\n #touchDown(event: TouchEvent) {\r\n this.#clicked = true;\r\n const rect = this.#ele.getBoundingClientRect();\r\n this.#lastTouch.x = event.touches[0].clientX - rect.left;\r\n this.#lastTouch.y = event.touches[0].clientY - rect.top;\r\n this.#clickStart(this.#lastTouch, false);\r\n }\r\n\r\n #up(event: MouseEvent): void {\r\n // Only register left clicks\r\n if (event.button !== 0) {\r\n return;\r\n }\r\n this.#clicked = false\r\n this.#clickStop();\r\n }\r\n}", "import { Vector2 } from \"../types/vector2\"\r\n\r\n\r\nexport interface RenderElementSidesStyling {\r\n Left?: number\r\n Right?: number\r\n Top?: number\r\n Bottom?: number\r\n}\r\n\r\nexport interface RenderElementSides {\r\n Left: number\r\n Right: number\r\n Top: number\r\n Bottom: number\r\n}\r\n\r\nexport function InstantiateRenderElementSidesStyling(config?: RenderElementSidesStyling | number): RenderElementSides {\r\n if (typeof config === 'number') {\r\n return {\r\n Bottom: config,\r\n Right: config,\r\n Top: config,\r\n Left: config,\r\n }\r\n }\r\n return {\r\n Bottom: config?.Bottom === undefined ? 0 : config?.Bottom,\r\n Right: config?.Right === undefined ? 0 : config?.Right,\r\n Left: config?.Left === undefined ? 0 : config?.Left,\r\n Top: config?.Top === undefined ? 0 : config?.Top,\r\n }\r\n}\r\n\r\nexport interface IRenderElement {\r\n size(ctx: CanvasRenderingContext2D, out: Vector2): void;\r\n render(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void;\r\n}\r\n\r\nexport interface Border {\r\n Color: string;\r\n Thickness: number;\r\n Radius: number;\r\n}\r\n\r\nexport interface BorderStyling {\r\n Color?: string;\r\n Thickness?: number;\r\n Radius?: number;\r\n}\r\n", "import { Vector2 } from \"../types/vector2\";\r\nimport { Border, BorderStyling, InstantiateRenderElementSidesStyling, IRenderElement, RenderElementSides, RenderElementSidesStyling } from \"./interfaces\";\r\n\r\nexport enum Display {\r\n Flex = \"flex\",\r\n None = \"none\"\r\n}\r\n\r\nexport interface RenderElementBaseStyling {\r\n Margin?: RenderElementSidesStyling | number;\r\n Padding?: RenderElementSidesStyling | number;\r\n Border?: BorderStyling;\r\n BackgroundColor?: string;\r\n MinWidth?: number;\r\n MaxWidth?: number;\r\n MaxHeight?: number;\r\n MinHeight?: number;\r\n Grow?: number;\r\n Display?: Display;\r\n}\r\n\r\nexport abstract class RenderElementBase implements IRenderElement {\r\n\r\n #margin: RenderElementSides;\r\n\r\n #padding: RenderElementSides;\r\n\r\n #border: Border;\r\n\r\n #backgroundColor?: string;\r\n\r\n #minWidth?: number;\r\n\r\n #maxWidth?: number;\r\n\r\n #minHeight?: number;\r\n\r\n #maxHeight?: number;\r\n\r\n #grow?: number;\r\n\r\n #display: Display;\r\n\r\n constructor(config?: RenderElementBaseStyling) {\r\n this.#margin = InstantiateRenderElementSidesStyling(config?.Margin);\r\n this.#padding = InstantiateRenderElementSidesStyling(config?.Padding);\r\n this.#backgroundColor = config?.BackgroundColor;\r\n this.#border = {\r\n Color: config?.Border?.Color ?? \"black\",\r\n Thickness: config?.Border?.Thickness ?? 0,\r\n Radius: config?.Border?.Radius ?? 0,\r\n }\r\n this.#minWidth = config?.MinWidth;\r\n this.#maxWidth = config?.MaxWidth;\r\n this.#minHeight = config?.MinHeight;\r\n this.#maxHeight = config?.MaxHeight;\r\n this.#grow = config?.Grow;\r\n this.#display = config?.Display ?? Display.Flex;\r\n }\r\n\r\n setBackgroundColor(newColor: string): void {\r\n this.#backgroundColor = newColor;\r\n }\r\n\r\n abstract doRender(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void;\r\n\r\n render(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void {\r\n if (this.#display === Display.None) {\r\n return;\r\n }\r\n\r\n const scaledSize = { x: 0, y: 0 };\r\n this.size(ctx, scaledSize);\r\n\r\n scaledSize.x = scaledSize.x * graphScale;\r\n scaledSize.y = scaledSize.y * graphScale;\r\n scaledSize.x = Math.max(scaledSize.x, scaledFillableSpace.x);\r\n scaledSize.y = Math.max(scaledSize.y, scaledFillableSpace.y);\r\n\r\n if (this.#backgroundColor) {\r\n ctx.fillStyle = this.#backgroundColor;\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n position.x + (this.#margin.Left * graphScale),\r\n position.y + (this.#margin.Right * graphScale),\r\n scaledSize.x - ((this.#margin.Left + this.#margin.Right) * graphScale),\r\n scaledSize.y - ((this.#margin.Top + this.#margin.Bottom) * graphScale),\r\n this.#border.Radius * graphScale\r\n );\r\n ctx.fill();\r\n }\r\n\r\n if (this.#border.Thickness > 0) {\r\n ctx.lineWidth = this.#border.Thickness * graphScale;\r\n ctx.strokeStyle = this.#border.Color;\r\n ctx.stroke();\r\n }\r\n\r\n const offsetPosition = {\r\n x: position.x + (this.#totalLeftOffset() * graphScale),\r\n y: position.y + (this.#totalTopOffset() * graphScale),\r\n };\r\n const elementSize = {\r\n x: scaledSize.x - (this.#horizontalOffset() * graphScale),\r\n y: scaledSize.y - (this.#verticalOffset() * graphScale)\r\n }\r\n this.doRender(ctx, offsetPosition, graphScale, elementSize);\r\n }\r\n\r\n // todo: Remove limitations argument?\r\n abstract calcSize(ctx: CanvasRenderingContext2D, out: Vector2, limitations: Vector2): void;\r\n\r\n protected maxLimitations(out: Vector2): void {\r\n out.x = -1;\r\n out.y = -1;\r\n\r\n if (this.#maxWidth) {\r\n out.x = this.#maxWidth;\r\n }\r\n\r\n if (this.#maxHeight) {\r\n out.y = this.#maxHeight;\r\n }\r\n }\r\n\r\n setDisplay(display: Display): void {\r\n this.#display = display;\r\n }\r\n\r\n getDisplay(): Display {\r\n return this.#display;\r\n }\r\n\r\n size(ctx: CanvasRenderingContext2D, out: Vector2): void {\r\n out.x = 0;\r\n out.y = 0;\r\n if (this.#display === Display.None) {\r\n return;\r\n }\r\n\r\n const maxLimits = { x: -1, y: -1 }\r\n this.maxLimitations(maxLimits);\r\n\r\n this.calcSize(ctx, out, maxLimits);\r\n\r\n out.x += this.#horizontalOffset();\r\n out.y += this.#verticalOffset();\r\n\r\n if (this.#minWidth) {\r\n out.x = Math.max(out.x, this.#minWidth)\r\n }\r\n\r\n if (this.#maxWidth) {\r\n out.x = Math.min(this.#maxWidth, out.x);\r\n }\r\n\r\n if (this.#maxHeight) {\r\n out.y = Math.min(this.#maxHeight, out.y);\r\n }\r\n\r\n if (this.#minHeight) {\r\n out.y = Math.max(this.#minHeight, out.y);\r\n }\r\n }\r\n\r\n #horizontalOffset(): number {\r\n return (this.#border.Thickness) +\r\n this.#margin.Left +\r\n this.#margin.Right +\r\n this.#padding.Left +\r\n this.#padding.Right;\r\n }\r\n\r\n #verticalOffset(): number {\r\n return (this.#border.Thickness) +\r\n this.#margin.Top +\r\n this.#margin.Bottom +\r\n this.#padding.Top +\r\n this.#padding.Bottom;\r\n }\r\n\r\n #totalTopOffset(): number {\r\n return (this.#border.Thickness / 2) +\r\n this.#margin.Top +\r\n this.#padding.Top;\r\n }\r\n\r\n #totalLeftOffset(): number {\r\n return (this.#border.Thickness / 2) +\r\n this.#margin.Left +\r\n this.#padding.Left;\r\n }\r\n}\r\n", "import { ScaleVector, Vector2 } from '../types/vector2';\r\nimport { RenderElementBase, RenderElementBaseStyling } from \"./base\";\r\nimport { IRenderElement } from \"./interfaces\";\r\n\r\n\r\ninterface ContainerRenderElementConfig extends RenderElementBaseStyling {\r\n\r\n}\r\n\r\nexport enum LayoutDirection {\r\n Column = \"column\",\r\n Row = \"row\"\r\n}\r\n\r\nexport enum AlignItems {\r\n Stretch = \"stretch\",\r\n Start = \"start\",\r\n Center = \"center\",\r\n End = \"end\"\r\n}\r\n\r\nexport class ContainerRenderElement extends RenderElementBase {\r\n\r\n #elements: Array<IRenderElement>;\r\n\r\n #layout: LayoutDirection;\r\n\r\n #alignment: AlignItems;\r\n\r\n constructor(elements: Array<IRenderElement>, config?: ContainerRenderElementConfig) {\r\n super(config);\r\n this.#elements = elements;\r\n this.#layout = LayoutDirection.Column;\r\n this.#alignment = AlignItems.Stretch;\r\n }\r\n\r\n calcSize(ctx: CanvasRenderingContext2D, out: Vector2, limitations: Vector2): void {\r\n out.x = 0;\r\n out.y = 0;\r\n\r\n const eleSize = { x: 0, y: 0 };\r\n\r\n switch (this.#layout) {\r\n case LayoutDirection.Column:\r\n for (let i = 0; i < this.#elements.length; i++) {\r\n this.#elements[i].size(ctx, eleSize);\r\n out.x = Math.max(out.x, eleSize.x);\r\n out.y += eleSize.y;\r\n }\r\n break;\r\n\r\n case LayoutDirection.Row:\r\n for (let i = 0; i < this.#elements.length; i++) {\r\n this.#elements[i].size(ctx, eleSize);\r\n out.y = Math.max(out.y, eleSize.y);\r\n out.x += eleSize.x;\r\n }\r\n break;\r\n\r\n default:\r\n throw new Error(\"unknown layout: \" + this.#layout);\r\n }\r\n\r\n }\r\n\r\n doRender(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void {\r\n // const size = { x: 0, y: 0 };\r\n // const limitations = { x: 0, y: 0 };\r\n // this.limitations(limitations)\r\n // this.calcSize(ctx, size, limitations);\r\n switch (this.#layout) {\r\n case LayoutDirection.Column:\r\n this.#renderColumn(ctx, position, graphScale, scaledFillableSpace);\r\n break;\r\n\r\n default:\r\n throw new Error(\"unimplemented layout direction: \" + this.#layout);\r\n }\r\n }\r\n\r\n #renderColumn(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void {\r\n const currnetPos = { x: position.x, y: position.y };\r\n const scaledEleSize = { x: 0, y: 0 };\r\n for (let i = 0; i < this.#elements.length; i++) {\r\n const ele = this.#elements[i];\r\n\r\n ele.size(ctx, scaledEleSize);\r\n ScaleVector(scaledEleSize, graphScale);\r\n\r\n switch (this.#alignment) {\r\n\r\n case AlignItems.Stretch:\r\n currnetPos.x = position.x;\r\n scaledEleSize.x = scaledFillableSpace.x;\r\n break;\r\n\r\n // I'm not sure if this is even needed, I feel like this should\r\n // already be the case.\r\n case AlignItems.Start: //garney flarney <---- silly goose steenky feet\r\n currnetPos.x = position.x;\r\n break\r\n\r\n case AlignItems.End:\r\n currnetPos.x = scaledFillableSpace.x - scaledEleSize.x\r\n break;\r\n\r\n case AlignItems.Center:\r\n currnetPos.x = scaledFillableSpace.x - (scaledEleSize.x / 2)\r\n break;\r\n\r\n default:\r\n throw new Error(\"unimplmeneted alignment: \" + this.#alignment)\r\n }\r\n\r\n ele.render(ctx, currnetPos, graphScale, scaledEleSize);\r\n currnetPos.y += scaledEleSize.y;\r\n }\r\n }\r\n}", "import { Text } from \"../types/text\";\r\nimport { CopyVector2, ScaleVector, Vector2, Zero } from \"../types/vector2\";\r\nimport { RenderElementBase, RenderElementBaseStyling } from \"./base\";\r\n\r\nexport enum TextAlign {\r\n Left = \"left\",\r\n Right = \"right\",\r\n Center = \"center\",\r\n}\r\n\r\nexport enum VerticalAlign {\r\n Top = \"top\",\r\n Center = \"center\",\r\n Bottom = \"bottom\"\r\n}\r\n\r\nexport interface TextElementStyling extends RenderElementBaseStyling {\r\n Align?: TextAlign\r\n VerticalAlign?: VerticalAlign\r\n LineHeight?: number\r\n}\r\n\r\nexport class TextElement extends RenderElementBase {\r\n #text: Text;\r\n\r\n #align: TextAlign;\r\n\r\n #verticalAlign: VerticalAlign;\r\n\r\n #lineHeight: number;\r\n\r\n constructor(text: Text, styling?: TextElementStyling) {\r\n super(styling);\r\n this.#text = text;\r\n this.#align = styling?.Align ?? TextAlign.Left;\r\n this.#verticalAlign = styling?.VerticalAlign ?? VerticalAlign.Top;\r\n this.#lineHeight = styling?.LineHeight ?? 1;\r\n }\r\n\r\n doRender(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void {\r\n const scale = Zero();\r\n this.calcSize(ctx, scale, scaledFillableSpace);\r\n ScaleVector(scale, graphScale);\r\n\r\n const justifiedPosition = Zero();\r\n CopyVector2(justifiedPosition, position)\r\n\r\n ctx.textAlign = \"left\";\r\n ctx.textBaseline = \"top\"\r\n\r\n switch (this.#align) {\r\n case TextAlign.Left:\r\n // Do nothing. This is default\r\n break;\r\n\r\n case TextAlign.Right:\r\n justifiedPosition.x += scaledFillableSpace.x - scale.x;\r\n break;\r\n\r\n case TextAlign.Center:\r\n justifiedPosition.x += (scaledFillableSpace.x - scale.x) / 2;\r\n break;\r\n\r\n default:\r\n throw new Error(\"unimplemented justification: \" + this.#align);\r\n }\r\n\r\n switch (this.#verticalAlign) {\r\n case VerticalAlign.Top:\r\n // Do nothing. This is default\r\n break;\r\n\r\n case VerticalAlign.Bottom:\r\n justifiedPosition.y += scaledFillableSpace.y - scale.y;\r\n break;\r\n\r\n case VerticalAlign.Center:\r\n justifiedPosition.y += (scaledFillableSpace.y - scale.y) / 2;\r\n break;\r\n\r\n default:\r\n throw new Error(\"unimplemented justification: \" + this.#align);\r\n }\r\n\r\n if (scaledFillableSpace.x <= 0) {\r\n this.#text.render(ctx, graphScale, justifiedPosition);\r\n } else {\r\n const eles = this.#text.breakIntoLines(ctx, scaledFillableSpace.x);\r\n\r\n const tempSize = { x: 0, y: 0 };\r\n for (let i = 0; i < eles.length; i++) {\r\n eles[i].render(ctx, graphScale, justifiedPosition);\r\n eles[i].size(ctx, 1, tempSize)\r\n justifiedPosition.y += this.#text.style().getSize() * this.#lineHeight\r\n }\r\n }\r\n }\r\n\r\n calcSize(ctx: CanvasRenderingContext2D, out: Vector2, limitations: Vector2): void {\r\n if (limitations.x <= 0) {\r\n this.#text.size(ctx, 1, out);\r\n return;\r\n }\r\n\r\n const eles = this.#text.breakIntoLines(ctx, limitations.x);\r\n const tempSize = { x: 0, y: 0 };\r\n out.x = 0;\r\n out.y = this.#text.style().getSize() * eles.length * this.#lineHeight;\r\n for (let i = 0; i < eles.length; i++) {\r\n eles[i].size(ctx, 1, tempSize)\r\n out.x = Math.max(tempSize.x, out.x);\r\n }\r\n }\r\n}\r\n", "const binarySearch = ({ max, getValue, match }) => {\r\n let min = 0;\r\n\r\n while (min <= max) {\r\n let guess = Math.floor((min + max) / 2);\r\n const compareVal = getValue(guess);\r\n\r\n if (compareVal === match) return guess;\r\n if (compareVal < match) min = guess + 1;\r\n else max = guess - 1;\r\n }\r\n\r\n return max;\r\n};\r\n\r\nexport function fitString(ctx: CanvasRenderingContext2D, str: string, maxWidth: number): string {\r\n let width = ctx.measureText(str).width;\r\n const ellipsis = '\u2026';\r\n const ellipsisWidth = ctx.measureText(ellipsis).width;\r\n if (width <= maxWidth || width <= ellipsisWidth) {\r\n return str;\r\n }\r\n\r\n const index = binarySearch({\r\n max: str.length,\r\n getValue: (guess: number) => ctx.measureText(str.substring(0, guess)).width,\r\n match: maxWidth - ellipsisWidth,\r\n });\r\n\r\n return str.substring(0, index) + ellipsis;\r\n};\r\n\r\nexport function splitString(ctx: CanvasRenderingContext2D, str: string, maxWidth: number): Array<string> {\r\n let width = ctx.measureText(str).width;\r\n if (width <= maxWidth) {\r\n return [str];\r\n }\r\n\r\n let index = binarySearch({\r\n max: str.length,\r\n getValue: (guess: number) => ctx.measureText(str.substring(0, guess)).width,\r\n match: maxWidth,\r\n });\r\n\r\n for (let backward = index - 1; backward >= 1; backward--) {\r\n if (str.charAt(backward) === \" \") {\r\n index = backward + 1;\r\n break;\r\n }\r\n }\r\n\r\n return [str.substring(0, index), str.substring(index)];\r\n};\r\n\r\n\r\nexport function splitStringIntoLines(ctx: CanvasRenderingContext2D, str: string, maxWidth: number): Array<string> {\r\n let width = ctx.measureText(str).width;\r\n if (width <= maxWidth) {\r\n return [str];\r\n }\r\n\r\n const strings = new Array<string>;\r\n let remaining = str;\r\n while (remaining !== \"\") {\r\n let index = binarySearch({\r\n max: remaining.length,\r\n getValue: (guess: number) => ctx.measureText(remaining.substring(0, guess)).width,\r\n match: maxWidth,\r\n });\r\n\r\n if (index === remaining.length) {\r\n strings.push(remaining.substring(0, index))\r\n break;\r\n }\r\n\r\n for (let backward = index - 1; backward >= 1; backward--) {\r\n if (remaining.charAt(backward) === \" \") {\r\n index = backward + 1;\r\n break;\r\n }\r\n }\r\n\r\n strings.push(remaining.substring(0, index))\r\n remaining = remaining.substring(index)\r\n }\r\n\r\n return strings;\r\n};\r\n\r\n// https://stackoverflow.com/a/18234317/4974261\r\nexport function Format(str: string, ...args: Array<string>): string {\r\n if (arguments.length) {\r\n for (let key in args) {\r\n str = str.replace(new RegExp(\"\\\\{\" + key + \"\\\\}\", \"gi\"), args[key]);\r\n }\r\n }\r\n return str;\r\n};", "import { FontWeight, TextStyle, TextStyleConfig } from \"../styles/text\";\r\nimport { splitString, splitStringIntoLines } from \"../utils/string\";\r\nimport { CopyVector2, ScaleVector, Vector2, Zero } from \"./vector2\";\r\n\r\nexport interface MultilineTextConfig {\r\n MaxWidth?: number;\r\n LineSpacing?: number;\r\n}\r\n\r\nexport class Text {\r\n\r\n #measured: boolean\r\n\r\n #size: Vector2;\r\n\r\n #style: TextStyle;\r\n\r\n #value: string\r\n\r\n #maxWidth: number;\r\n\r\n #lineSpacing: number;\r\n\r\n #textToRender: Array<string>;\r\n\r\n constructor(value: string, style?: TextStyleConfig, config?: MultilineTextConfig) {\r\n this.#value = value;\r\n this.#measured = false;\r\n this.#size = Zero();\r\n this.#style = new TextStyle(style);\r\n this.#maxWidth = config?.MaxWidth ? config?.MaxWidth : -1;\r\n this.#lineSpacing = config?.LineSpacing ? config?.LineSpacing : 5;\r\n this.#textToRender = [value];\r\n\r\n if (!document.fonts.check(`16px \"${this.#style.getFont()}\"`)) {\r\n document.fonts.addEventListener(\"loadingdone\", (event) => {\r\n this.#measured = false;\r\n });\r\n }\r\n }\r\n\r\n set(newValue: string): void {\r\n this.#value = newValue;\r\n this.#measured = false;\r\n }\r\n\r\n get(): string {\r\n return this.#value;\r\n }\r\n\r\n breakIntoLines(ctx: CanvasRenderingContext2D, maxWidth: number): Array<Text> {\r\n const results = new Array<Text>();\r\n\r\n this.#style.setupStyle(ctx, 1);\r\n const entries = splitStringIntoLines(ctx, this.#value, maxWidth);\r\n if (entries.length === 1) {\r\n return [this];\r\n }\r\n for (let i = 0; i < entries.length; i++) {\r\n const text = new Text(entries[i])\r\n text.#style = this.#style;\r\n results.push(text)\r\n }\r\n\r\n return results;\r\n }\r\n\r\n split(char: string): Array<Text> {\r\n const entries = this.#value.split(char)\r\n const results = new Array<Text>();\r\n for (let i = 0; i < entries.length; i++) {\r\n const text = new Text(entries[i])\r\n text.#style = this.#style;\r\n results.push(text)\r\n }\r\n return results;\r\n }\r\n\r\n splitAtIndex(index: number): Array<Text> {\r\n const results = [\r\n new Text(this.#value.substring(0, index)),\r\n new Text(this.#value.substring(index, 0)),\r\n ];\r\n\r\n\r\n for (let i = 0; i < results.length; i++) {\r\n results[i].#style = this.#style;\r\n }\r\n return results;\r\n }\r\n\r\n splitAtWidth(ctx: CanvasRenderingContext2D, maxWidth: number): Array<Text> {\r\n this.#style.setupStyle(ctx, 1);\r\n const entries = splitString(ctx, this.#value, maxWidth);\r\n if (entries.length === 1) {\r\n return [this];\r\n }\r\n\r\n const results = new Array<Text>();\r\n for (let i = 0; i < entries.length; i++) {\r\n const text = new Text(entries[i])\r\n text.#style = this.#style;\r\n results.push(text)\r\n }\r\n return results;\r\n }\r\n\r\n #measure(ctx: CanvasRenderingContext2D): void {\r\n if (this.#measured) {\r\n return;\r\n }\r\n\r\n\r\n this.#style.setupStyle(ctx, 1);\r\n\r\n if (this.#maxWidth == -1) {\r\n const measurements = ctx.measureText(this.#value);\r\n this.#size.x = measurements.width;\r\n this.#size.y = measurements.actualBoundingBoxAscent + measurements.actualBoundingBoxDescent;\r\n this.#textToRender = [this.#value];\r\n this.#measured = true;\r\n return;\r\n }\r\n\r\n this.#textToRender = splitStringIntoLines(ctx, this.#value, this.#maxWidth);\r\n\r\n this.#size.x = 0;\r\n this.#size.y = 0;\r\n for (let i = 0; i < this.#textToRender.length; i++) {\r\n const measurements = ctx.measureText(this.#textToRender[i]);\r\n this.#size.x = Math.max(this.#size.x, measurements.width);\r\n }\r\n\r\n this.#size.y += ((this.#textToRender.length - 1) * this.#lineSpacing) + (this.#style.getSize() * this.#textToRender.length);\r\n this.#measured = true;\r\n }\r\n\r\n size(ctx: CanvasRenderingContext2D, scale: number, out: Vector2): void {\r\n this.#measure(ctx);\r\n CopyVector2(out, this.#size);\r\n ScaleVector(out, scale);\r\n }\r\n\r\n height(ctx: CanvasRenderingContext2D): number {\r\n this.#measure(ctx);\r\n return this.#size.y;\r\n }\r\n\r\n setColor(color: string): void {\r\n this.#style.setColor(color);\r\n }\r\n\r\n getColor(): string {\r\n return this.#style.getColor();\r\n }\r\n\r\n setSize(size: number): void {\r\n this.#style.setSize(size);\r\n }\r\n\r\n setWeight(weight: FontWeight): void {\r\n this.#style.setWeight(weight);\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, scale: number, position: Vector2): void {\r\n this.#measure(ctx);\r\n this.#style.setupStyle(ctx, scale);\r\n let yOffset = 0;\r\n for (let i = 0; i < this.#textToRender.length; i++) {\r\n ctx.fillText(\r\n this.#textToRender[i],\r\n position.x,\r\n position.y + yOffset\r\n );\r\n yOffset += (this.#style.getSize() + this.#lineSpacing) * scale\r\n }\r\n }\r\n\r\n style(): TextStyle {\r\n return this.#style;\r\n }\r\n}", "export function Clamp(v: number, min: number, max: number): number {\r\n return Math.min(Math.max(v, min), max)\r\n}\r\n\r\nexport function Clamp01(v: number): number {\r\n return Clamp(v, 0, 1);\r\n}\r\n\r\n", "import { Clamp01 } from './math';\r\n\r\nexport interface Color {\r\n r: number, // 0 - 1\r\n g: number, // 0 - 1\r\n b: number, // 0 - 1\r\n}\r\n\r\nexport interface HSV {\r\n h: number, // angle in degrees\r\n s: number, // 0 - 1\r\n v: number, // 0 - 1\r\n}\r\n\r\nfunction componentToHex(c: number) {\r\n var hex = c.toString(16);\r\n return hex.length == 1 ? \"0\" + hex : hex;\r\n}\r\n\r\nexport function RgbToHex(c: Color): string {\r\n return \"#\" + componentToHex(Math.round(c.r * 255)) + componentToHex(Math.round(c.g * 255)) + componentToHex(Math.round(c.b * 255));\r\n}\r\n\r\nexport function HexToColor(hex: string): Color | null {\r\n var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n return result ? {\r\n r: parseInt(result[1], 16) / 255,\r\n g: parseInt(result[2], 16) / 255,\r\n b: parseInt(result[3], 16) / 255\r\n } : null;\r\n}\r\n\r\n\r\nexport function HSV2RGB(hsv: HSV, out: Color): void {\r\n if (hsv.s <= 0.0) { // < is bogus, just shuts up warnings\r\n out.r = hsv.v;\r\n out.g = hsv.v;\r\n out.b = hsv.v;\r\n return;\r\n }\r\n let hh = hsv.h;\r\n if (hh >= 360.0) {\r\n hh = 0.0;\r\n }\r\n hh /= 60.0;\r\n\r\n const i = Math.round(hh);\r\n const ff = hh - i;\r\n const p = hsv.v * (1.0 - hsv.s);\r\n const q = hsv.v * (1.0 - (hsv.s * ff));\r\n const t = hsv.v * (1.0 - (hsv.s * (1.0 - ff)));\r\n\r\n switch (i) {\r\n case 0:\r\n out.r = hsv.v;\r\n out.g = t;\r\n out.b = p;\r\n break;\r\n case 1:\r\n out.r = q;\r\n out.g = hsv.v;\r\n out.b = p;\r\n break;\r\n case 2:\r\n out.r = p;\r\n out.g = hsv.v;\r\n out.b = t;\r\n break;\r\n\r\n case 3:\r\n out.r = p;\r\n out.g = q;\r\n out.b = hsv.v;\r\n break;\r\n case 4:\r\n out.r = t;\r\n out.g = p;\r\n out.b = hsv.v;\r\n break;\r\n // case 5:\r\n default:\r\n out.r = hsv.v;\r\n out.g = p;\r\n out.b = q;\r\n break;\r\n }\r\n\r\n out.r = Clamp01(out.r)\r\n out.g = Clamp01(out.g)\r\n out.b = Clamp01(out.b)\r\n}\r\n\r\nexport function RGB2HSV(rgb: Color, out: HSV): void {\r\n out.h = 0;\r\n out.s = 0;\r\n out.v = 0;\r\n let min: number = 0;\r\n let max: number = 0;\r\n let delta: number = 0;\r\n\r\n min = rgb.r < rgb.g ? rgb.r : rgb.g;\r\n min = min < rgb.b ? min : rgb.b;\r\n\r\n max = rgb.r > rgb.g ? rgb.r : rgb.g;\r\n max = max > rgb.b ? max : rgb.b;\r\n\r\n out.v = max; // v\r\n delta = max - min;\r\n if (delta < 0.00001) {\r\n out.s = 0;\r\n out.h = 0; // undefined, maybe nan?\r\n return;\r\n }\r\n if (max > 0.0) { // NOTE: if Max is == 0, this divide would cause a crash\r\n out.s = (delta / max); // s\r\n } else {\r\n // if max is 0, then r = g = b = 0 \r\n // s = 0, h is undefined\r\n out.s = 0.0;\r\n out.h = NaN; // its now undefined\r\n return;\r\n }\r\n if (rgb.r >= max) // > is bogus, just keeps compilor happy\r\n out.h = (rgb.g - rgb.b) / delta; // between yellow & magenta\r\n else\r\n if (rgb.g >= max)\r\n out.h = 2.0 + (rgb.b - rgb.r) / delta; // between cyan & yellow\r\n else\r\n out.h = 4.0 + (rgb.r - rgb.g) / delta; // between magenta & cyan\r\n\r\n out.h *= 60.0; // degrees\r\n\r\n if (out.h < 0.0)\r\n out.h += 360.0;\r\n\r\n}\r\n", "import { Camera } from \"./camera\";\r\nimport { Connection } from './connection';\r\nimport { RenderElementBase } from \"./elements/base\";\r\nimport { ContainerRenderElement, AlignItems } from './elements/container';\r\nimport { TextAlign, TextElement } from \"./elements/text\";\r\nimport { FlowNode } from \"./node\";\r\nimport { PassSubsystem } from \"./pass/subsystem\";\r\nimport { FontStyle } from \"./styles/text\";\r\nimport { Box, InBox } from \"./types/box\";\r\nimport { Text } from \"./types/text\";\r\nimport { Vector2 } from \"./types/vector2\";\r\nimport { Color, HSV, HSV2RGB, RgbToHex } from './utils/color';\r\n\r\nexport enum PortType {\r\n Input = \"INPUT\",\r\n Output = \"OUTPUT\",\r\n InputArray = \"INPUTARRAY\",\r\n}\r\n\r\nexport interface PortStyle {\r\n size?: number;\r\n fillColor?: string;\r\n borderColor?: string;\r\n borderSize?: number;\r\n}\r\n\r\ntype ConnectionChangeCallback = (connection: Connection, connectionIndex: number, port: Port, portType: PortType, node: FlowNode) => void\r\n\r\nexport interface PortConfig {\r\n name?: string;\r\n type?: string;\r\n description?: string;\r\n array?: boolean;\r\n emptyStyle?: PortStyle;\r\n filledStyle?: PortStyle;\r\n onConnectionAdded?: ConnectionChangeCallback;\r\n onConnectionRemoved?: ConnectionChangeCallback;\r\n};\r\n\r\n// Calculate a color hash for an arbirary type\r\nfunction fallbackColor(type: string, s: number): string {\r\n let value = 0;\r\n for (var i = 0; i < type.length; i++) {\r\n value += type.charCodeAt(i) * (i + 1);\r\n }\r\n\r\n const mod = 24;\r\n value = Math.round(value) % mod;\r\n\r\n const hsv: HSV = { h: (value / (mod - 1)) * 360, s: s, v: 1 };\r\n const color: Color = { r: 0, g: 0, b: 0 };\r\n HSV2RGB(hsv, color);\r\n return RgbToHex(color);\r\n}\r\n\r\nexport class Port {\r\n\r\n #node: FlowNode;\r\n\r\n #displayName: string;\r\n\r\n #emptyStyle: PortStyle;\r\n\r\n #filledStyle: PortStyle;\r\n\r\n #connections: Array<Connection>;\r\n\r\n #portType: PortType\r\n\r\n #dataType: string;\r\n\r\n #dataTypePopupElement: RenderElementBase;\r\n\r\n #onConnectionAdded: Array<ConnectionChangeCallback>;\r\n\r\n #onConnectionRemoved: Array<ConnectionChangeCallback>;\r\n\r\n constructor(node: FlowNode, portType: PortType, config?: PortConfig) {\r\n this.#node = node;\r\n this.#connections = new Array<Connection>();\r\n this.#portType = portType;\r\n this.#displayName = config?.name === undefined ? \"Port\" : config?.name;\r\n this.#dataType = config?.type === undefined ? \"\" : config?.type;\r\n\r\n this.#emptyStyle = {\r\n borderColor: config?.emptyStyle?.borderColor === undefined ? \"#1c1c1c\" : config.emptyStyle?.borderColor,\r\n fillColor: config?.emptyStyle?.fillColor === undefined ? fallbackColor(this.#dataType, 0.3) : config.emptyStyle?.fillColor,\r\n borderSize: config?.emptyStyle?.borderSize === undefined ? 1 : config.emptyStyle?.borderSize,\r\n size: config?.emptyStyle?.size === undefined ? 4 : config.emptyStyle?.size\r\n }\r\n\r\n this.#filledStyle = {\r\n borderColor: config?.filledStyle?.borderColor === undefined ? \"#1c1c1c\" : config.filledStyle?.borderColor,\r\n fillColor: config?.filledStyle?.fillColor === undefined ? fallbackColor(this.#dataType, 1) : config.filledStyle?.fillColor,\r\n borderSize: config?.filledStyle?.borderSize === undefined ? 1 : config.filledStyle?.borderSize,\r\n size: config?.filledStyle?.size === undefined ? 5 : config.filledStyle?.size\r\n }\r\n\r\n this.#onConnectionAdded = new Array<ConnectionChangeCallback>();\r\n if (config?.onConnectionAdded) {\r\n this.#onConnectionAdded.push(config?.onConnectionAdded);\r\n }\r\n\r\n this.#onConnectionRemoved = new Array<ConnectionChangeCallback>();\r\n if (config?.onConnectionRemoved) {\r\n this.#onConnectionRemoved.push(config?.onConnectionRemoved);\r\n }\r\n\r\n const containerElements = new Array<RenderElementBase>();\r\n let dataTypeDisplay = this.#dataType;\r\n if (config?.array === true) {\r\n dataTypeDisplay = \"Array<\" + dataTypeDisplay + \">\"\r\n }\r\n containerElements.push(new TextElement(\r\n new Text(dataTypeDisplay, {\r\n color: \"white\",\r\n }),\r\n {\r\n Align: TextAlign.Center,\r\n }\r\n ));\r\n\r\n const description = config?.description;\r\n if (description && description !== \"\") {\r\n containerElements.push(new TextElement(\r\n new Text(description, { color: \"white\", style: FontStyle.Italic }),\r\n {\r\n Align: TextAlign.Center,\r\n Padding: { Top: 16 },\r\n MaxWidth: 400,\r\n LineHeight: 1.5\r\n }\r\n ));\r\n }\r\n\r\n this.#dataTypePopupElement = new ContainerRenderElement(\r\n containerElements,\r\n {\r\n BackgroundColor: \"rgba(0, 0, 0, 0.85)\",\r\n Border: {\r\n Radius: 6,\r\n },\r\n Padding: 13,\r\n }\r\n );\r\n }\r\n\r\n addConnection(connection: Connection): void {\r\n const c = this.#connections.length;\r\n this.#connections.push(connection);\r\n for (let i = 0; i < this.#onConnectionAdded.length; i++) {\r\n this.#onConnectionAdded[i](connection, c, this, this.#portType, this.#node);\r\n }\r\n }\r\n\r\n replaceConnection(connection: Connection, index: number): void {\r\n const c = this.#connections.length;\r\n this.#connections[index] = connection;\r\n for (let i = 0; i < this.#onConnectionAdded.length; i++) {\r\n this.#onConnectionAdded[i](connection, c, this, this.#portType, this.#node);\r\n }\r\n }\r\n\r\n addConnectionAddedListener(callback: ConnectionChangeCallback) {\r\n if (callback === undefined) {\r\n return;\r\n }\r\n this.#onConnectionAdded.push(callback);\r\n }\r\n\r\n connections(): Array<Connection> {\r\n return this.#connections;\r\n }\r\n\r\n addConnectionRemovedListener(callback: ConnectionChangeCallback) {\r\n if (callback === undefined) {\r\n return;\r\n }\r\n this.#onConnectionRemoved.push(callback);\r\n }\r\n\r\n clearConnection(connection: Connection): void {\r\n const index = this.#connections.indexOf(connection);\r\n if (index > -1) {\r\n this.#connections.splice(index, 1);\r\n for (let i = 0; i < this.#onConnectionRemoved.length; i++) {\r\n this.#onConnectionRemoved[i](connection, index, this, this.#portType, this.#node);\r\n }\r\n } else {\r\n console.error(\"no connection found to remove\");\r\n }\r\n }\r\n\r\n getDataType(): string {\r\n return this.#dataType;\r\n }\r\n\r\n getPortType(): PortType {\r\n return this.#portType;\r\n }\r\n\r\n getDisplayName(): string {\r\n return this.#displayName;\r\n }\r\n\r\n filledStyleColor(): string {\r\n if (this.#filledStyle.fillColor === undefined) {\r\n console.error(\"There's no fill color!!!!!!!!!\")\r\n return \"black\";\r\n }\r\n return this.#filledStyle.fillColor;\r\n }\r\n\r\n #box: Box = { Position: { x: 0, y: 0 }, Size: { x: 0, y: 0 } };\r\n\r\n render(ctx: CanvasRenderingContext2D, position: Vector2, camera: Camera, mousePosition: Vector2 | undefined, postProcess: PassSubsystem): Box {\r\n let style = this.#emptyStyle;\r\n if (this.#connections.length > 0) {\r\n style = this.#filledStyle;\r\n }\r\n\r\n let scaledRadius = style.size as number * camera.zoom\r\n\r\n if (mousePosition && InBox(this.#box, mousePosition)) {\r\n scaledRadius *= 1.25;\r\n\r\n // Redeclare so lambda is ensured to use these values\r\n const xPos = position.x;\r\n const yPos = position.y;\r\n\r\n // TODO: Make it so we're not creating a new lambda each frame\r\n postProcess.queue(() => {\r\n const size = { x: 0, y: 0 }\r\n this.#dataTypePopupElement.calcSize(ctx, size, { x: -1, y: -1 });\r\n // size.x = Math.min(150, size.x)\r\n this.#dataTypePopupElement.render(ctx, { x: xPos - (size.x / 2), y: yPos }, 1, size)\r\n })\r\n }\r\n\r\n this.#box.Position.x = position.x - scaledRadius;\r\n this.#box.Position.y = position.y - scaledRadius;\r\n this.#box.Size.x = scaledRadius * 2;\r\n this.#box.Size.y = scaledRadius * 2;\r\n\r\n ctx.strokeStyle = style.borderColor as string;\r\n ctx.fillStyle = style.fillColor as string;\r\n\r\n ctx.beginPath();\r\n if (this.#portType === PortType.InputArray) {\r\n ctx.rect(position.x - scaledRadius, position.y - scaledRadius, scaledRadius * 2, scaledRadius * 2)\r\n } else {\r\n ctx.arc(position.x, position.y, scaledRadius, 0, 2 * Math.PI);\r\n }\r\n ctx.fill();\r\n ctx.stroke();\r\n\r\n\r\n return this.#box;\r\n }\r\n}", "export interface StrokeStyleConfig {\r\n size?: number;\r\n color?: string;\r\n}\r\n\r\nexport function StrokeStyleWithFallback(input?: StrokeStyleConfig, fallback?: StrokeStyleConfig): StrokeStyleConfig {\r\n return {\r\n color: input?.color === undefined ? fallback?.color : input?.color,\r\n size: input?.size === undefined ? fallback?.size : input?.size,\r\n };\r\n}\r\n\r\nexport class StrokeStyle {\r\n #size: number;\r\n\r\n #color: string;\r\n\r\n constructor(config?: StrokeStyleConfig) {\r\n this.#size = config?.size === undefined ? 0.5 : config.size;\r\n this.#color = config?.color === undefined ? \"black\" : config.color;\r\n }\r\n\r\n setupStyle(ctx: CanvasRenderingContext2D, scale: number): void {\r\n ctx.strokeStyle = this.#color;\r\n ctx.lineWidth = scale * this.#size;\r\n }\r\n\r\n setColor(newColor: string): void {\r\n this.#color = newColor;\r\n }\r\n\r\n setSize(newSize: number): void {\r\n this.#size = newSize;\r\n }\r\n\r\n size(): number {\r\n return this.#size;\r\n }\r\n}", "import { Box } from \"../types/box\";\r\nimport { StrokeStyle, StrokeStyleConfig, StrokeStyleWithFallback } from \"./stroke\";\r\n\r\nexport interface BoxStyleConfig {\r\n border?: StrokeStyleConfig;\r\n color?: string;\r\n radius?: number;\r\n}\r\n\r\nexport function BoxStyleWithFallback(input?: BoxStyleConfig, fallback?: BoxStyleConfig): BoxStyleConfig {\r\n return {\r\n radius: input?.radius === undefined ? fallback?.radius : input?.radius,\r\n color: input?.color === undefined ? fallback?.color : input?.color,\r\n border: StrokeStyleWithFallback(input?.border, fallback?.border)\r\n };\r\n}\r\n\r\nexport class BoxStyle {\r\n #border: StrokeStyle | null;\r\n\r\n #color: string;\r\n\r\n #radius: number;\r\n\r\n constructor(config?: BoxStyleConfig) {\r\n this.#color = config?.color === undefined ? \"#CCCCCC\" : config.color;\r\n this.#border = config?.border === undefined ? null : new StrokeStyle(config.border);\r\n this.#radius = config?.radius === undefined ? 2 : config.radius;\r\n }\r\n\r\n #box(ctx: CanvasRenderingContext2D, box: Box, scale: number, radius: any): void {\r\n ctx.fillStyle = this.#color\r\n this.#border?.setupStyle(ctx, scale);\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n box.Position.x,\r\n box.Position.y,\r\n box.Size.x,\r\n box.Size.y,\r\n radius\r\n );\r\n ctx.fill();\r\n }\r\n\r\n #draw(ctx: CanvasRenderingContext2D, box: Box, scale: number, radius: any): void {\r\n this.#box(ctx, box, scale, radius);\r\n ctx.stroke();\r\n }\r\n\r\n Outline(ctx: CanvasRenderingContext2D, box: Box, scale: number, radius: any): void {\r\n this.#border?.setupStyle(ctx, scale);\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n box.Position.x,\r\n box.Position.y,\r\n box.Size.x,\r\n box.Size.y,\r\n radius\r\n );\r\n ctx.stroke();\r\n }\r\n\r\n Draw(ctx: CanvasRenderingContext2D, box: Box, scale: number): void {\r\n this.#draw(ctx, box, scale, this.#radius * scale)\r\n }\r\n\r\n DrawRoundedTopOnly(ctx: CanvasRenderingContext2D, box: Box, scale: number): void {\r\n this.#draw(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0])\r\n }\r\n\r\n DrawUnderline(ctx: CanvasRenderingContext2D, box: Box, scale: number): void {\r\n this.#box(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);\r\n ctx.beginPath();\r\n ctx.moveTo(box.Position.x, box.Position.y + box.Size.y)\r\n ctx.lineTo(box.Position.x + box.Size.x, box.Position.y + box.Size.y);\r\n ctx.stroke();\r\n }\r\n\r\n borderSize(): number {\r\n if (this.#border === null) {\r\n return 0;\r\n }\r\n return this.#border.size();\r\n }\r\n\r\n radius(): number {\r\n return this.#radius;\r\n }\r\n\r\n setColor(color: string): void {\r\n this.#color = color;\r\n }\r\n\r\n setBorderColor(color: string): void {\r\n if (this.#border === null) {\r\n this.#border = new StrokeStyle({\r\n color: color\r\n })\r\n } else {\r\n this.#border.setColor(color);\r\n }\r\n }\r\n\r\n}", "export interface PopupConfig {\r\n title: string;\r\n options: Array<string>;\r\n\r\n onClose?: (button: string | null) => void;\r\n content?: () => Element;\r\n buttonCSS?: string;\r\n}\r\n\r\nexport class Popup {\r\n\r\n #title: string;\r\n\r\n #options: Array<string>;\r\n\r\n #content?: () => Element;\r\n\r\n #onClose?: (button: string | null) => void;\r\n\r\n // Styling ================================================================\r\n\r\n #buttonCSS: string;\r\n\r\n // Runtime ================================================================\r\n\r\n #popup: HTMLDivElement | null;\r\n\r\n constructor(config: PopupConfig) {\r\n this.#title = config.title;\r\n this.#options = config.options;\r\n this.#content = config.content;\r\n this.#onClose = config.onClose;\r\n this.#buttonCSS = config.buttonCSS === undefined ? \"flex-grow: 1; margin-right: 8px;\" : config.buttonCSS;\r\n this.#popup = null;\r\n }\r\n\r\n Hide(): void {\r\n if (this.#popup === null) {\r\n return;\r\n }\r\n document.body.removeChild(this.#popup);\r\n this.#popup = null;\r\n }\r\n\r\n Show(): void {\r\n this.#popup = document.createElement('div');\r\n this.#popup.style.cssText = 'position:absolute;top:0;width:100%;display:flex;height:100%;justify-content:center;align-items:center;background-color:#00000070;';\r\n document.body.appendChild(this.#popup);\r\n\r\n const container = document.createElement('div');\r\n container.style.cssText = 'background-color:#000;color:white;font-family:Verdana;border-radius:8px;padding:16px;';\r\n this.#popup.appendChild(container);\r\n\r\n const title = document.createElement(\"h2\");\r\n title.textContent = this.#title;\r\n title.style.cssText = \"margin-top:0;margin-bottom:16px;\";\r\n container.appendChild(title)\r\n\r\n if (this.#content !== undefined) {\r\n container.appendChild(this.#content());\r\n }\r\n\r\n const buttonContainer = document.createElement(\"div\");\r\n buttonContainer.style.cssText = 'margin-top:16px;justify-content:space-around;align-items:center;flex-direction:row;display:flex;';\r\n container.appendChild(buttonContainer);\r\n\r\n for (let i = 0; i < this.#options.length; i++) {\r\n const button = document.createElement(\"button\");\r\n button.style.cssText = this.#buttonCSS;\r\n button.textContent = this.#options[i];\r\n button.onclick = () => {\r\n this.Hide();\r\n if (this.#onClose !== undefined) {\r\n this.#onClose(this.#options[i]);\r\n }\r\n };\r\n buttonContainer.appendChild(button);\r\n }\r\n }\r\n\r\n} ", "import { Box } from \"../types/box\";\r\nimport { BoxStyle, BoxStyleConfig, BoxStyleWithFallback } from \"./box\";\r\nimport { TextAlign } from \"./canvasTextAlign\";\r\nimport { TextBaseline } from \"./canvasTextBaseline\";\r\nimport { TextStyle, TextStyleConfig, TextStyleFallback } from './text';\r\n\r\n\r\nexport interface TextBoxStyleConfig {\r\n box?: BoxStyleConfig;\r\n text?: TextStyleConfig;\r\n\r\n textAlign?: CanvasTextAlign;\r\n textBaseline?: CanvasTextBaseline;\r\n}\r\n\r\nexport function TextBoxStyleWithFallback(input?: TextBoxStyleConfig, fallback?: TextBoxStyleConfig): TextBoxStyleConfig {\r\n return {\r\n box: BoxStyleWithFallback(input?.box, fallback?.box),\r\n text: TextStyleFallback(input?.text, fallback?.text),\r\n \r\n textAlign: input?.textAlign === undefined ? fallback?.textAlign : input?.textAlign,\r\n textBaseline: input?.textBaseline === undefined ? fallback?.textBaseline : input?.textBaseline,\r\n };\r\n}\r\n\r\nexport class TextBoxStyle {\r\n #box: BoxStyle;\r\n\r\n #text: TextStyle;\r\n\r\n #textAlign: CanvasTextAlign;\r\n\r\n #textBaseline: CanvasTextBaseline;\r\n\r\n constructor(config?: TextBoxStyleConfig) {\r\n this.#box = new BoxStyle(config?.box);\r\n this.#text = new TextStyle(config?.text);\r\n\r\n this.#textAlign = config?.textAlign === undefined ? TextAlign.Center : config.textAlign;\r\n this.#textBaseline = config?.textBaseline === undefined ? TextBaseline.Middle : config.textBaseline;\r\n }\r\n\r\n Draw(ctx: CanvasRenderingContext2D, box: Box, scale: number, text: string) {\r\n this.#box.Draw(ctx, box, scale);\r\n\r\n ctx.textAlign = this.#textAlign;\r\n ctx.textBaseline = this.#textBaseline;\r\n this.#text.setupStyle(ctx, scale);\r\n\r\n ctx.fillText(\r\n text,\r\n box.Position.x + (box.Size.x / 2),\r\n box.Position.y + (box.Size.y / 2),\r\n );\r\n }\r\n\r\n DrawUnderline(ctx: CanvasRenderingContext2D, box: Box, scale: number, text: string) {\r\n this.#box.DrawUnderline(ctx, box, scale);\r\n\r\n ctx.textAlign = this.#textAlign;\r\n ctx.textBaseline = this.#textBaseline;\r\n this.#text.setupStyle(ctx, scale);\r\n\r\n ctx.fillText(\r\n text,\r\n box.Position.x + (box.Size.x / 2),\r\n box.Position.y + (box.Size.y / 2),\r\n );\r\n }\r\n\r\n setTextColor(color: string): void {\r\n this.#text.setColor(color);\r\n }\r\n\r\n setBoxColor(color: string): void {\r\n this.#box.setColor(color);\r\n }\r\n\r\n setBorderColor(color: string): void {\r\n this.#box.setBorderColor(color);\r\n }\r\n}", "import { Box } from '../types/box';\r\nimport { Vector2 } from '../types/vector2';\r\n\r\nexport const width = 150;\r\nexport const height = 25;\r\n\r\nexport interface Widget {\r\n Size(): Vector2\r\n Draw(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, mousePosition: Vector2 | undefined): Box\r\n ClickStart(): void\r\n ClickEnd(): void\r\n}", "import { Theme } from \"../theme\";\r\nimport { Popup } from \"../popup\";\r\nimport { TextBoxStyle, TextBoxStyleConfig, TextBoxStyleWithFallback } from \"../styles/textBox\";\r\nimport { Box, InBox } from '../types/box';\r\nimport { CopyVector2, Vector2 } from \"../types/vector2\";\r\nimport { height, width } from \"./widget\";\r\nimport { FlowNode } from \"../node\";\r\n\r\nexport interface NumberWidgetConfig {\r\n value?: number;\r\n\r\n property?: string;\r\n\r\n idleBoxStyle?: TextBoxStyleConfig;\r\n\r\n highlightBoxStyle?: TextBoxStyleConfig;\r\n\r\n callback?: (newNumber: number) => void;\r\n}\r\n\r\nexport class NumberWidget {\r\n\r\n #node: FlowNode;\r\n\r\n #nodeProperty: string | undefined;\r\n\r\n #value: number;\r\n\r\n #idleBoxStyle: TextBoxStyle;\r\n\r\n #highlightBoxStyle: TextBoxStyle;\r\n\r\n #text: string;\r\n\r\n #callback?: (newNumber: number) => void;\r\n\r\n constructor(node: FlowNode, config?: NumberWidgetConfig) {\r\n this.#value = 0;\r\n this.#text = \"0\";\r\n\r\n this.#node = node;\r\n this.#nodeProperty = config?.property;\r\n this.#idleBoxStyle = new TextBoxStyle(TextBoxStyleWithFallback(config?.idleBoxStyle, {\r\n box: {\r\n color: Theme.Widget.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n },\r\n radius: Theme.Widget.Border.Radius\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }));\r\n this.#highlightBoxStyle = new TextBoxStyle(TextBoxStyleWithFallback(config?.highlightBoxStyle, {\r\n box: {\r\n color: Theme.Widget.Hover.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n },\r\n radius: Theme.Widget.Border.Radius\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }));\r\n this.Set(config?.value === undefined ? 0 : config?.value);\r\n this.#callback = config?.callback;\r\n\r\n if (this.#nodeProperty !== undefined) {\r\n this.#node.addPropertyChangeListener(this.#nodeProperty, (oldVal, newVal) => {\r\n this.Set(newVal);\r\n });\r\n }\r\n\r\n }\r\n\r\n Size(): Vector2 {\r\n return { \"x\": width, \"y\": height }\r\n }\r\n\r\n Set(newNumber: number): void {\r\n if (this.#value === newNumber) {\r\n return;\r\n }\r\n\r\n this.#value = newNumber;\r\n\r\n if (this.#nodeProperty !== undefined) {\r\n this.#node.setProperty(this.#nodeProperty, this.#value);\r\n }\r\n\r\n if (this.#callback !== undefined) {\r\n this.#callback(this.#value);\r\n }\r\n\r\n // https://stackoverflow.com/questions/5765398/whats-the-best-way-to-convert-a-number-to-a-string-in-javascript\r\n this.#text = '' + parseFloat(this.#value.toPrecision(6));\r\n }\r\n\r\n ClickStart(): void {\r\n }\r\n\r\n ClickEnd(): void {\r\n let input: HTMLInputElement | null = null;\r\n\r\n const setOption = \"Set\";\r\n const cancelOption = \"Cancel\";\r\n const popup = new Popup({\r\n title: \"Set Number\",\r\n options: [setOption, cancelOption],\r\n content: () => {\r\n const container = document.createElement('div');\r\n input = document.createElement('input')\r\n input.type = \"number\";\r\n input.valueAsNumber = this.#value;\r\n container.append(input);\r\n return container;\r\n },\r\n onClose: (button: string | null): void => {\r\n if (button !== setOption || input === null) {\r\n return;\r\n }\r\n\r\n this.Set(input.valueAsNumber);\r\n },\r\n });\r\n\r\n popup.Show();\r\n }\r\n\r\n\r\n Draw(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, mousePosition: Vector2 | undefined): Box {\r\n const box = {\r\n Position: { x: 0, y: 0 },\r\n Size: {\r\n x: width * scale,\r\n y: height * scale\r\n }\r\n };\r\n CopyVector2(box.Position, position);\r\n\r\n let style: TextBoxStyle = this.#idleBoxStyle;\r\n\r\n if (mousePosition !== undefined) {\r\n if (InBox(box, mousePosition)) {\r\n style = this.#highlightBoxStyle;\r\n }\r\n }\r\n\r\n style.DrawUnderline(ctx, box, scale, this.#text)\r\n\r\n return box;\r\n }\r\n}", "import { Theme } from \"../theme\";\r\nimport { TextBoxStyle, TextBoxStyleConfig, TextBoxStyleWithFallback } from \"../styles/textBox\";\r\nimport { Box, InBox } from \"../types/box\";\r\nimport { CopyVector2, Vector2 } from \"../types/vector2\";\r\nimport { height, width } from \"./widget\";\r\n\r\n\r\nexport interface ButtonWidgetConfig {\r\n text?: string;\r\n callback?: () => void;\r\n idleStyle?: TextBoxStyleConfig;\r\n hoverStyle?: TextBoxStyleConfig;\r\n clickStyle?: TextBoxStyleConfig;\r\n}\r\n\r\nexport class ButtonWidget {\r\n\r\n #text: string;\r\n\r\n #idleStyle: TextBoxStyle;\r\n\r\n #hoverStyle: TextBoxStyle;\r\n\r\n #clickStyle: TextBoxStyle;\r\n\r\n #callback?: () => void;\r\n\r\n #gettingClicked: boolean;\r\n\r\n constructor(config?: ButtonWidgetConfig) {\r\n this.#text = config?.text === undefined ? \"Button\" : config?.text;\r\n this.#callback = config?.callback\r\n this.#gettingClicked = false;\r\n\r\n this.#idleStyle = new TextBoxStyle(TextBoxStyleWithFallback(config?.idleStyle, {\r\n box: {\r\n color: Theme.Widget.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n }\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }));\r\n this.#hoverStyle = new TextBoxStyle(TextBoxStyleWithFallback(config?.hoverStyle, {\r\n box: {\r\n color: Theme.Widget.Hover.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n }\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }));\r\n this.#clickStyle = new TextBoxStyle(TextBoxStyleWithFallback(config?.clickStyle, {\r\n box: { \r\n color: Theme.Widget.Button.Click.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n }\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }))\r\n }\r\n\r\n Size(): Vector2 {\r\n return { \"x\": width, \"y\": height }\r\n }\r\n\r\n Draw(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, mousePosition: Vector2 | undefined): Box {\r\n const box = {\r\n Position: { x: 0, y: 0 },\r\n Size: {\r\n x: width * scale,\r\n y: height * scale\r\n }\r\n };\r\n CopyVector2(box.Position, position);\r\n\r\n let style: TextBoxStyle = this.#idleStyle;\r\n\r\n if (mousePosition !== undefined && !this.#gettingClicked) {\r\n if (InBox(box, mousePosition)) {\r\n style = this.#hoverStyle;\r\n }\r\n }\r\n\r\n if (this.#gettingClicked) {\r\n style = this.#clickStyle;\r\n }\r\n style.Draw(ctx, box, scale, this.#text);\r\n\r\n return box\r\n }\r\n\r\n ClickStart(): void {\r\n this.#gettingClicked = true;\r\n }\r\n\r\n ClickEnd(): void {\r\n this.#gettingClicked = false;\r\n if (this.#callback !== undefined) {\r\n this.#callback();\r\n }\r\n }\r\n}", "import { HexToColor } from \"../utils/color\";\r\nimport { TextStyleConfig } from \"../styles/text\";\r\nimport { Box } from \"../types/box\";\r\nimport { CopyVector2, Vector2 } from \"../types/vector2\";\r\nimport { height, width } from \"./widget\";\r\nimport { Popup } from \"../popup\";\r\nimport { TextBoxStyle } from '../styles/textBox';\r\nimport { Theme } from \"../theme\";\r\nimport { FlowNode } from \"../node\";\r\n\r\nexport interface ColorWidgetConfig {\r\n value?: string;\r\n\r\n property?: string;\r\n\r\n textStyle?: TextStyleConfig;\r\n\r\n callback?: (newColor: string) => void;\r\n}\r\n\r\nfunction contrastColor(color: string): string {\r\n const c = HexToColor(color);\r\n if (c === null) {\r\n return \"black\";\r\n }\r\n\r\n if ((c.r + c.g + c.b) / 3 > 0.5) {\r\n return \"black\"\r\n }\r\n\r\n return \"white\";\r\n}\r\n\r\nexport class ColorWidget {\r\n\r\n #node: FlowNode;\r\n\r\n #nodeProperty: string | undefined;\r\n\r\n #value: string;\r\n\r\n #contrast: string;\r\n\r\n #textBoxStyle: TextBoxStyle;\r\n\r\n #callback?: (newColor: string) => void;\r\n\r\n constructor(node: FlowNode, config?: ColorWidgetConfig) {\r\n this.#value = \"#000000\"\r\n this.#contrast = contrastColor(this.#value);\r\n this.Set(config?.value === undefined ? \"#000000\" : config?.value);\r\n \r\n this.#node = node;\r\n this.#nodeProperty = config?.property;\r\n this.#textBoxStyle = new TextBoxStyle({\r\n box: {\r\n color: this.#value,\r\n border: {\r\n color: this.#contrast,\r\n size: Theme.Widget.Border.Size\r\n }\r\n },\r\n text: config?.textStyle\r\n });\r\n this.#callback = config?.callback;\r\n\r\n if (this.#nodeProperty !== undefined) {\r\n this.#node.addPropertyChangeListener(this.#nodeProperty, (oldVal, newVal) => {\r\n this.Set(newVal);\r\n });\r\n }\r\n }\r\n\r\n Size(): Vector2 {\r\n return { \"x\": width, \"y\": height }\r\n }\r\n\r\n Set(value: string): void {\r\n if (this.#value === value) {\r\n return;\r\n }\r\n\r\n this.#value = value;\r\n\r\n if (this.#callback !== undefined) {\r\n this.#callback(this.#value);\r\n }\r\n\r\n if (this.#nodeProperty !== undefined) {\r\n this.#node.setProperty(this.#nodeProperty, this.#value);\r\n }\r\n\r\n // Update Styling\r\n this.#contrast = contrastColor(this.#value);\r\n this.#textBoxStyle.setBoxColor(this.#value);\r\n this.#textBoxStyle.setBorderColor(this.#contrast);\r\n this.#textBoxStyle.setTextColor(this.#contrast);\r\n }\r\n\r\n ClickStart(): void {\r\n }\r\n\r\n ClickEnd(): void {\r\n let input: HTMLInputElement | null = null;\r\n\r\n const popup = new Popup({\r\n title: \"Set Color\",\r\n options: [\"Set\", \"Cancel\"],\r\n content: () => {\r\n const container = document.createElement('div');\r\n\r\n input = document.createElement('input')\r\n input.type = \"color\";\r\n input.value = this.#value;\r\n input.name = \"color\"\r\n container.append(input);\r\n\r\n const label = document.createElement(\"label\");\r\n label.htmlFor = \"color\";\r\n label.textContent = \"Color\";\r\n container.append(label);\r\n\r\n return container;\r\n },\r\n onClose: (button: string | null): void => {\r\n if (button !== \"Set\" || input === null) {\r\n return;\r\n }\r\n\r\n this.Set(input.value);\r\n },\r\n });\r\n\r\n popup.Show();\r\n }\r\n\r\n Draw(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, mousePosition: Vector2 | undefined): Box {\r\n const box = {\r\n Position: { x: 0, y: 0 },\r\n Size: {\r\n x: width * scale,\r\n y: height * scale\r\n }\r\n };\r\n CopyVector2(box.Position, position);\r\n\r\n this.#textBoxStyle.Draw(ctx, box, scale, this.#value)\r\n\r\n return box;\r\n }\r\n}", "import { Theme } from \"../theme\";\r\nimport { TextAlign } from \"../styles/canvasTextAlign\";\r\nimport { TextStyle, TextStyleConfig, TextStyleFallback } from \"../styles/text\";\r\nimport { Box } from '../types/box';\r\nimport { CopyVector2, Vector2, Zero } from \"../types/vector2\";\r\nimport { Clamp, Clamp01 } from \"../utils/math\";\r\nimport { height, width } from \"./widget\";\r\nimport { TextBaseline } from \"../styles/canvasTextBaseline\";\r\nimport { FlowNode } from \"../node\";\r\n\r\nexport interface SliderWidgetConfig {\r\n\r\n property?: string;\r\n\r\n min?: number;\r\n\r\n max?: number;\r\n\r\n value?: number;\r\n\r\n backgroundColor?: string;\r\n\r\n borderColor?: string;\r\n\r\n fillColor?: string;\r\n\r\n textStyle?: TextStyleConfig;\r\n\r\n change?: (newValue: number) => void;\r\n\r\n release?: (newValue: number) => void;\r\n\r\n snapIncrement?: number;\r\n\r\n}\r\n\r\nexport class SliderWidget {\r\n\r\n // Data Variables =========================================================\r\n\r\n #min: number;\r\n\r\n #max: number;\r\n\r\n #value: number;\r\n\r\n #text: string;\r\n\r\n #snapIncrement?: number;\r\n\r\n #node: FlowNode;\r\n\r\n #nodeProperty: string | undefined;\r\n\r\n // Callbacks ==============================================================\r\n\r\n #change?: (newValue: number) => void;\r\n\r\n #release?: (newValue: number) => void;\r\n\r\n // Styling Variables ======================================================\r\n\r\n #textStyle: TextStyle\r\n\r\n #backgroundColor: string;\r\n\r\n #borderColor: string;\r\n\r\n #fillColor: string;\r\n\r\n // Runtime Variables ======================================================\r\n\r\n #lastMousePosition: Vector2;\r\n\r\n #clickStartMousePosition: Vector2;\r\n\r\n #clicking: boolean;\r\n\r\n constructor(node: FlowNode, config?: SliderWidgetConfig) {\r\n this.#node = node;\r\n this.#value = 0;\r\n this.#min = config?.min === undefined ? 0 : config?.min;\r\n this.#max = config?.max === undefined ? 1 : config?.max;\r\n this.#snapIncrement = config?.snapIncrement;\r\n this.#nodeProperty = config?.property;\r\n this.#text = \"\";\r\n \r\n this.#release = config?.release;\r\n\r\n this.#backgroundColor = config?.backgroundColor === undefined ? Theme.Widget.BackgroundColor : config?.backgroundColor;\r\n this.#fillColor = config?.fillColor === undefined ? Theme.Widget.Slider.FillColor : config?.fillColor;\r\n this.#borderColor = config?.borderColor === undefined ? Theme.Widget.Border.Color : config?.borderColor;\r\n this.#textStyle = new TextStyle(TextStyleFallback(config?.textStyle, {\r\n color: Theme.Widget.FontColor,\r\n }));\r\n this.#lastMousePosition = Zero();\r\n this.#clickStartMousePosition = Zero();\r\n this.#clicking = false;\r\n\r\n\r\n if (config?.property !== undefined && config?.property !== null) {\r\n node.addPropertyChangeListener(config.property, (oldVal, newVal) => {\r\n this.SetValue(newVal);\r\n });\r\n }\r\n\r\n this.SetValue(config?.value === undefined ? 0 : config?.value);\r\n\r\n // Setup change callback after we set the initial value to prevent the callback from being \r\n this.#change = config?.change;\r\n }\r\n\r\n SetValue(newValue: number): void {\r\n const cleanedValue = Clamp(newValue, this.#min, this.#max);\r\n if (this.#value === cleanedValue) {\r\n return;\r\n }\r\n\r\n this.#value = cleanedValue;\r\n\r\n if (this.#nodeProperty) {\r\n this.#node.setProperty(this.#nodeProperty, this.#value);\r\n }\r\n\r\n this.#text = this.#value.toFixed(3);\r\n if (this.#change !== undefined) {\r\n this.#change(this.#value);\r\n }\r\n }\r\n\r\n Size(): Vector2 {\r\n return { \"x\": width, \"y\": height }\r\n }\r\n\r\n ClickStart(): void {\r\n this.#clicking = true;\r\n CopyVector2(this.#clickStartMousePosition, this.#lastMousePosition)\r\n }\r\n\r\n ClickEnd(): void {\r\n this.#clicking = false;\r\n if (this.#release !== undefined) {\r\n this.#release(this.#value);\r\n }\r\n }\r\n\r\n Draw(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, mousePosition: Vector2 | undefined): Box {\r\n const scaledWidth = width * scale;\r\n const scaledHeight = height * scale;\r\n\r\n const scaledBorderThickness = Theme.Widget.Border.Size * scale;\r\n\r\n // Render background\r\n ctx.fillStyle = this.#backgroundColor;\r\n ctx.strokeStyle = this.#borderColor;\r\n ctx.lineWidth = scaledBorderThickness;\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n position.x,\r\n position.y,\r\n scaledWidth,\r\n scaledHeight,\r\n Theme.Widget.Border.Radius * scale\r\n );\r\n ctx.fill();\r\n ctx.stroke();\r\n\r\n // Render Fill\r\n const fill = Clamp01((this.#value - this.#min) / (this.#max - this.#min));\r\n ctx.fillStyle = this.#fillColor;\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n position.x + (scaledBorderThickness / 2),\r\n position.y + (scaledBorderThickness / 2),\r\n (scaledWidth * fill) - scaledBorderThickness,\r\n scaledHeight - scaledBorderThickness,\r\n Theme.Widget.Border.Radius * scale\r\n );\r\n ctx.fill();\r\n\r\n // Render Number\r\n ctx.textAlign = TextAlign.Center;\r\n ctx.textBaseline = TextBaseline.Middle;\r\n this.#textStyle.setupStyle(ctx, scale);\r\n ctx.fillText(\r\n this.#text,\r\n position.x + (scaledWidth / 2),\r\n position.y + (scaledHeight / 2),\r\n );\r\n\r\n // Update value based on mouse position\r\n if (mousePosition !== undefined) {\r\n CopyVector2(this.#lastMousePosition, mousePosition);\r\n if (this.#clicking) {\r\n const min = position.x + (scaledBorderThickness / 2);\r\n const max = min + scaledWidth - scaledBorderThickness;\r\n const p = Clamp01((this.#lastMousePosition.x - min) / (max - min));\r\n\r\n let value = (p * (this.#max - this.#min)) + this.#min;\r\n if (this.#snapIncrement !== undefined) {\r\n value = Math.round(value / this.#snapIncrement) * this.#snapIncrement;\r\n }\r\n\r\n this.SetValue(value);\r\n }\r\n }\r\n\r\n return {\r\n Position: { x: position.x, y: position.y },\r\n Size: {\r\n x: scaledWidth,\r\n y: scaledHeight\r\n }\r\n };\r\n }\r\n}", "import { Popup } from \"../popup\";\r\n\r\ninterface Config {\r\n title: string;\r\n startingValue: string;\r\n onUpdate: (newValue: string) => void;\r\n onCancel?: () => void;\r\n}\r\n\r\nexport function SetStringPopup(config: Config): Popup {\r\n let input: HTMLInputElement | null = null;\r\n\r\n return new Popup({\r\n title: config.title,\r\n options: [\"Set\", \"Cancel\"],\r\n content: () => {\r\n const container = document.createElement('div');\r\n input = document.createElement('input')\r\n input.value = config.startingValue;\r\n container.append(input);\r\n return container;\r\n },\r\n onClose: (button: string | null): void => {\r\n if (button !== \"Set\" || input === null) {\r\n if(config.onCancel) {\r\n config.onCancel();\r\n }\r\n return;\r\n }\r\n config.onUpdate(input.value);\r\n },\r\n });\r\n}", "import { Theme } from \"../theme\";\r\nimport { TextBoxStyle, TextBoxStyleConfig, TextBoxStyleWithFallback } from \"../styles/textBox\";\r\nimport { Box, InBox } from \"../types/box\";\r\nimport { CopyVector2, Vector2 } from \"../types/vector2\";\r\nimport { fitString } from \"../utils/string\";\r\nimport { height, width } from \"./widget\";\r\nimport { FlowNode } from '../node';\r\nimport { SetStringPopup } from \"../popups/string\";\r\n\r\nexport interface StringWidgetConfig {\r\n property?: string;\r\n\r\n value?: string;\r\n\r\n textBoxStyle?: TextBoxStyleConfig;\r\n\r\n callback?: (newString: string) => void;\r\n}\r\n\r\nexport class StringWidget {\r\n\r\n #value: string;\r\n\r\n #idleStyle: TextBoxStyle;\r\n\r\n #hoverStyle: TextBoxStyle;\r\n\r\n #callback?: (newString: string) => void;\r\n\r\n #node: FlowNode\r\n\r\n #nodeProperty: string | undefined;\r\n\r\n constructor(node: FlowNode, config?: StringWidgetConfig) {\r\n this.#value = \"\";\r\n \r\n this.#node = node;\r\n this.#nodeProperty = config?.property;\r\n this.#idleStyle = new TextBoxStyle(TextBoxStyleWithFallback(config?.textBoxStyle, {\r\n box: {\r\n color: Theme.Widget.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n },\r\n radius: Theme.Widget.Border.Radius\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }));\r\n\r\n this.#hoverStyle = new TextBoxStyle(TextBoxStyleWithFallback(config?.textBoxStyle, {\r\n box: {\r\n color: Theme.Widget.Hover.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n },\r\n radius: Theme.Widget.Border.Radius\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }));\r\n\r\n this.Set(config?.value === undefined ? \"\" : config?.value);\r\n this.#callback = config?.callback;\r\n if (this.#nodeProperty !== undefined) {\r\n this.#node.addPropertyChangeListener(this.#nodeProperty, (oldVal, newVal) => {\r\n this.Set(newVal);\r\n });\r\n }\r\n }\r\n\r\n Size(): Vector2 {\r\n return { \"x\": width, \"y\": height }\r\n }\r\n\r\n Set(value: string): void {\r\n if (this.#value === value) {\r\n return;\r\n }\r\n this.#value = value;\r\n\r\n if (this.#nodeProperty !== undefined) {\r\n this.#node.setProperty(this.#nodeProperty, this.#value)\r\n }\r\n\r\n if (this.#callback !== undefined) {\r\n this.#callback(this.#value);\r\n }\r\n }\r\n\r\n ClickStart(): void {\r\n }\r\n\r\n ClickEnd(): void {\r\n const popup = SetStringPopup({\r\n title: \"Set String\",\r\n startingValue: this.#value,\r\n onUpdate: (value: string): void => {\r\n this.Set(value);\r\n },\r\n });\r\n popup.Show();\r\n }\r\n\r\n Draw(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, mousePosition: Vector2 | undefined): Box {\r\n const box = {\r\n Position: { x: 0, y: 0 },\r\n Size: {\r\n x: width * scale,\r\n y: height * scale\r\n }\r\n };\r\n CopyVector2(box.Position, position);\r\n\r\n\r\n let style: TextBoxStyle = this.#idleStyle;\r\n\r\n if (mousePosition !== undefined) {\r\n if (InBox(box, mousePosition)) {\r\n style = this.#hoverStyle;\r\n }\r\n }\r\n\r\n style.DrawUnderline(ctx, box, scale, fitString(ctx, this.#value, box.Size.x - (20 * scale)))\r\n\r\n return box;\r\n }\r\n}", "import { Theme } from \"../theme\";\r\nimport { Box, InBox } from \"../types/box\";\r\nimport { CopyVector2, Vector2 } from \"../types/vector2\";\r\nimport { height, width } from \"./widget\";\r\nimport { TextBoxStyle, TextBoxStyleConfig, TextBoxStyleWithFallback } from \"../styles/textBox\";\r\nimport { FlowNode } from \"../node\";\r\n\r\nexport interface ToggleStyleConfig {\r\n idle?: TextBoxStyleConfig,\r\n hover?: TextBoxStyleConfig,\r\n lightColor?: string;\r\n lightBorderColor?: string;\r\n lightBlur?: number;\r\n}\r\n\r\nexport interface ToggleWidgetConfig {\r\n property?: string;\r\n value?: boolean;\r\n text?: string;\r\n callback?: () => void;\r\n enabledStyle?: ToggleStyleConfig;\r\n disabledStyle?: ToggleStyleConfig;\r\n}\r\n\r\nclass ToggleStyle {\r\n\r\n #idleStyle: TextBoxStyle;\r\n\r\n #hoverStyle: TextBoxStyle;\r\n\r\n #lightColor: string;\r\n\r\n #lightBorderColor: string;\r\n\r\n #lightBlur?: number;\r\n\r\n #box: Box;\r\n\r\n constructor(config?: ToggleStyleConfig) {\r\n this.#idleStyle = new TextBoxStyle(TextBoxStyleWithFallback(config?.idle, {\r\n box: {\r\n color: Theme.Widget.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n }\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }));\r\n this.#hoverStyle = new TextBoxStyle(TextBoxStyleWithFallback(config?.hover, {\r\n box: {\r\n color: Theme.Widget.Hover.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n }\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }));\r\n this.#lightColor = config?.lightColor === undefined ? \"#222222\" : config.lightColor;\r\n this.#lightBorderColor = config?.lightBorderColor === undefined ? \"black\" : config.lightBorderColor;\r\n this.#lightBlur = config?.lightBlur;\r\n\r\n this.#box = {Position: { x: 0, y: 0 }, Size: { x: 0, y: 0 } };\r\n }\r\n\r\n Draw(ctx: CanvasRenderingContext2D, pos: Vector2, scale: number, text: string, mousePosition: Vector2 | undefined): Box {\r\n const scaledWidth = width * scale;\r\n const scaledHeight = height * scale;\r\n this.#box.Size.x = scaledWidth;\r\n this.#box.Size.y = scaledHeight;\r\n CopyVector2(this.#box.Position, pos);\r\n\r\n // Background\r\n let style: TextBoxStyle = this.#idleStyle;\r\n if (mousePosition !== undefined) {\r\n if (InBox(this.#box, mousePosition)) {\r\n style = this.#hoverStyle;\r\n }\r\n }\r\n style.Draw(ctx, this.#box, scale, text);\r\n\r\n // Light\r\n const lightScale = Math.min(scaledWidth, scaledHeight);\r\n ctx.strokeStyle = this.#lightBorderColor;\r\n ctx.fillStyle = this.#lightColor\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n pos.x + (lightScale * .2),\r\n pos.y + (lightScale * .2),\r\n lightScale * .6,\r\n lightScale * .6,\r\n Theme.Widget.Border.Radius * scale\r\n );\r\n if (this.#lightBlur) {\r\n ctx.shadowBlur = this.#lightBlur * scale;\r\n ctx.shadowColor = this.#lightColor;\r\n }\r\n ctx.fill();\r\n if (this.#lightBlur) {\r\n ctx.shadowBlur = 0;\r\n }\r\n // ctx.stroke();\r\n\r\n return this.#box\r\n }\r\n}\r\n\r\nexport class ToggleWidget {\r\n\r\n #node: FlowNode;\r\n\r\n #nodeProperty: string | undefined;\r\n\r\n #value: boolean;\r\n\r\n #text: string;\r\n\r\n #enabledStyle: ToggleStyle;\r\n\r\n #disabledStyle: ToggleStyle;\r\n\r\n #callback?: (value: boolean) => void;\r\n\r\n constructor(node: FlowNode, config?: ToggleWidgetConfig) {\r\n this.#value = false;\r\n\r\n this.#node = node;\r\n this.#nodeProperty = config?.property;\r\n this.#text = config?.text === undefined ? \"Toggle\" : config?.text;\r\n\r\n this.#enabledStyle = new ToggleStyle({\r\n idle: TextBoxStyleWithFallback(config?.enabledStyle?.idle, {\r\n box: {\r\n color: Theme.Widget.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n }\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }),\r\n lightBorderColor: config?.enabledStyle?.lightBorderColor,\r\n lightColor: config?.enabledStyle?.lightColor === undefined ? \"#00FF00\" : config?.enabledStyle?.lightColor,\r\n lightBlur: config?.enabledStyle?.lightBlur === undefined ? 15 : config?.enabledStyle?.lightBlur\r\n });\r\n this.#disabledStyle = new ToggleStyle({\r\n idle: TextBoxStyleWithFallback(config?.disabledStyle?.idle, {\r\n box: {\r\n color: Theme.Widget.BackgroundColor,\r\n border: {\r\n size: Theme.Widget.Border.Size,\r\n color: Theme.Widget.Border.Color,\r\n }\r\n },\r\n text: { color: Theme.Widget.FontColor },\r\n }),\r\n lightBorderColor: config?.disabledStyle?.lightBorderColor,\r\n lightColor: config?.disabledStyle?.lightColor === undefined ? \"#004400\" : config?.enabledStyle?.lightColor,\r\n });\r\n\r\n this.Set(config?.value === undefined ? false : config?.value);\r\n this.#callback = config?.callback;\r\n if (this.#nodeProperty !== undefined) {\r\n this.#node.addPropertyChangeListener(this.#nodeProperty, (oldVal, newVal) => {\r\n this.Set(newVal);\r\n });\r\n }\r\n }\r\n\r\n Size(): Vector2 {\r\n return { \"x\": width, \"y\": height }\r\n }\r\n\r\n Draw(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, mousePosition: Vector2 | undefined): Box {\r\n let style = this.#value ? this.#enabledStyle : this.#disabledStyle;\r\n return style.Draw(ctx, position, scale, this.#text, mousePosition);\r\n }\r\n\r\n Toggle(): void {\r\n this.Set(!this.#value);\r\n }\r\n\r\n Set(value: boolean): void {\r\n if (this.#value === value) {\r\n return;\r\n }\r\n this.#value = value;\r\n\r\n if (this.#nodeProperty !== undefined) {\r\n this.#node.setProperty(this.#nodeProperty, this.#value);\r\n }\r\n\r\n if (this.#callback !== undefined) {\r\n this.#callback(this.#value);\r\n }\r\n }\r\n\r\n ClickStart(): void {\r\n this.Toggle();\r\n }\r\n\r\n ClickEnd(): void {\r\n }\r\n}", "import { Box } from \"../types/box\";\r\nimport { CopyVector2, Vector2 } from \"../types/vector2\";\r\n\r\nconst margin = 15;\r\n\r\nexport interface ImageWidgetConfig {\r\n image?: string;\r\n maxWidth?: number\r\n maxHeight?: number\r\n blob?: Blob;\r\n}\r\n\r\n/**\r\n * constructor(lightNode, nodeManager, id, parameterData, app) {\r\n this.lightNode = lightNode;\r\n this.id = id;\r\n this.app = app;\r\n this.lightNode.title = parameterData.name;\r\n\r\n this.lightNode.onDropFile = (file) => {\r\n // console.log(file)\r\n var reader = new FileReader();\r\n reader.onload = (evt) => {\r\n console.log(evt.target.result)\r\n nodeManager.nodeParameterChanged({\r\n id: id,\r\n data: evt.target.result,\r\n binary: true\r\n });\r\n }\r\n reader.readAsArrayBuffer(file);\r\n\r\n const url = URL.createObjectURL(file);\r\n // this.loadImage(this._url, function (img) {\r\n // that.size[1] = (img.height / img.width) * that.size[0];\r\n // });\r\n this.loadImgFromURL(url);\r\n }\r\n }\r\n\r\n loadImgFromURL(url) {\r\n const img = document.createElement(\"img\");\r\n img.src = url;\r\n img.onload = () => {\r\n // if (callback) {\r\n // callback(this);\r\n // }\r\n // console.log(\"Image loaded, size: \" + img.width + \"x\" + img.height);\r\n // this.dirty = true;\r\n // that.boxcolor = \"#9F9\";f\r\n // that.setDirtyCanvas(true);\r\n this.lightNode.widgets[0].image = img\r\n this.lightNode.setSize(this.lightNode.computeSize());\r\n };\r\n img.onerror = () => {\r\n console.log(\"error loading the image:\" + url);\r\n }\r\n }\r\n\r\n update(parameterData) {\r\n console.log(\"image parameter\", parameterData)\r\n const curVal = parameterData.currentValue;\r\n this.app.RequestManager.getParameterValue(this.id, (response) => {\r\n const url = URL.createObjectURL(response);\r\n this.loadImgFromURL(url)\r\n })\r\n }\r\n */\r\n\r\nexport class ImageWidget {\r\n\r\n #url: string | undefined;\r\n\r\n #image: HTMLImageElement | undefined;\r\n\r\n #maxWidth: number;\r\n\r\n #maxHeight: number;\r\n\r\n constructor(config?: ImageWidgetConfig) {\r\n this.#maxWidth = config?.maxWidth === undefined ? 150 : config?.maxWidth;\r\n this.#maxHeight = config?.maxHeight === undefined ? 150 : config?.maxHeight;\r\n if (config?.image) {\r\n this.SetUrl(config?.image);\r\n } else if (config?.blob) {\r\n this.SetBlob(config?.blob);\r\n }\r\n }\r\n\r\n SetBlob(blob: Blob) {\r\n const urlCreator = window.URL || window.webkitURL;\r\n const imageUrl = urlCreator.createObjectURL(blob);\r\n this.SetUrl(imageUrl);\r\n }\r\n\r\n SetUrl(url: string) {\r\n this.#image = undefined;\r\n this.#url = url;\r\n\r\n const img = document.createElement(\"img\");\r\n img.src = url;\r\n img.onload = () => {\r\n this.#image = img;\r\n };\r\n img.onerror = (event) => {\r\n console.log(\"error loading image:\", url, event);\r\n }\r\n }\r\n\r\n Size(): Vector2 {\r\n if (this.#image === undefined) {\r\n return { \"x\": 0, \"y\": 0 }\r\n }\r\n\r\n let adjust = 1;\r\n if (this.#image.width > this.#maxWidth) {\r\n adjust = this.#maxWidth / this.#image.width\r\n }\r\n\r\n if (this.#image.height > this.#maxHeight) {\r\n let heightAdjust = this.#maxHeight / this.#image.height\r\n if (heightAdjust < adjust) {\r\n adjust = heightAdjust;\r\n }\r\n }\r\n\r\n return {\r\n \"x\": adjust * this.#image.width,\r\n \"y\": adjust * this.#image.height\r\n }\r\n }\r\n\r\n ClickStart(): void {\r\n }\r\n\r\n ClickEnd(): void {\r\n }\r\n\r\n Draw(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, mousePosition: Vector2 | undefined): Box {\r\n const size = this.Size();\r\n const box: Box = {\r\n Position: { x: 0, y: 0 },\r\n Size: {\r\n x: size.x * scale,\r\n y: size.y * scale,\r\n }\r\n }\r\n CopyVector2(box.Position, position);\r\n\r\n if (!this.#image) {\r\n return box;\r\n }\r\n\r\n ctx.drawImage(\r\n this.#image,\r\n position.x,\r\n position.y,\r\n box.Size.x,\r\n box.Size.y\r\n );\r\n return box;\r\n }\r\n}", "import { Theme } from \"../theme\";\r\nimport { Box, InBox } from \"../types/box\";\r\nimport { CopyVector2, Vector2, Zero } from \"../types/vector2\";\r\nimport { FlowNode } from '../node';\r\nimport { Text } from \"../types/text\";\r\nimport { TextStyle, TextStyleConfig, TextStyleFallback } from \"../styles/text\";\r\n\r\nexport interface TextWidgetConfig {\r\n property?: string;\r\n\r\n value?: string;\r\n\r\n textBoxStyle?: TextStyleConfig;\r\n\r\n callback?: (newString: string) => void;\r\n}\r\n\r\nexport class TextWidget {\r\n\r\n #value: Text;\r\n\r\n #callback?: (newString: string) => void;\r\n\r\n #node: FlowNode\r\n\r\n #nodeProperty: string | undefined;\r\n\r\n #size: Vector2;\r\n\r\n constructor(node: FlowNode, config?: TextWidgetConfig) {\r\n this.#size = Zero();\r\n this.#node = node;\r\n this.#nodeProperty = config?.property;\r\n this.#value = new Text(\"\", TextStyleFallback(config?.textBoxStyle, {\r\n font: Theme.FontFamily,\r\n color: Theme.Widget.FontColor,\r\n size: Theme.Note.FontSize,\r\n }))\r\n\r\n this.Set(config?.value === undefined ? \"\" : config?.value);\r\n this.#callback = config?.callback;\r\n if (this.#nodeProperty !== undefined) {\r\n this.#node.addPropertyChangeListener(this.#nodeProperty, (oldVal, newVal) => {\r\n this.Set(newVal);\r\n });\r\n }\r\n }\r\n\r\n Size(): Vector2 {\r\n return this.#size;\r\n }\r\n\r\n Set(value: string): void {\r\n if (this.#value.get() === value) {\r\n return;\r\n }\r\n this.#value.set(value);\r\n\r\n if (this.#nodeProperty !== undefined) {\r\n this.#node.setProperty(this.#nodeProperty, value)\r\n }\r\n\r\n if (this.#callback !== undefined) {\r\n this.#callback(value);\r\n }\r\n }\r\n\r\n ClickStart(): void {\r\n // Left blank for implementing Widget interface\r\n }\r\n\r\n ClickEnd(): void {\r\n // Left blank for implementing Widget interface\r\n }\r\n\r\n\r\n Draw(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, mousePosition: Vector2 | undefined): Box {\r\n this.#value.size(ctx, scale, this.#size);\r\n const box = {\r\n Position: { x: 0, y: 0 },\r\n Size: this.#size\r\n };\r\n CopyVector2(box.Position, position);\r\n this.#value.size(ctx, 1, this.#size);\r\n \r\n ctx.textAlign = \"left\";\r\n this.#value.render(ctx, scale, box.Position);\r\n // this.#idleStyle.DrawUnderline(ctx, box, scale, fitString(ctx, this.#value, box.Size.x - (20 * scale)))\r\n\r\n return box;\r\n }\r\n}", "import { Widget } from \"./widget\";\r\nimport { NumberWidget, NumberWidgetConfig } from './number';\r\nimport { ButtonWidget, ButtonWidgetConfig } from './button';\r\nimport { ColorWidget, ColorWidgetConfig } from './color';\r\nimport { SliderWidget, SliderWidgetConfig } from './slider';\r\nimport { StringWidget, StringWidgetConfig } from './string';\r\nimport { ToggleWidget, ToggleWidgetConfig } from './toggle';\r\nimport { FlowNode } from \"../node\";\r\nimport { ImageWidget, ImageWidgetConfig } from \"./image\";\r\nimport { TextWidget, TextWidgetConfig } from \"./text\";\r\n\r\nexport type WidgetBuilder = (node: FlowNode, confg?: any) => Widget;\r\n\r\nclass WidgetFactory {\r\n\r\n #registeredWidgets: Map<string, WidgetBuilder>\r\n\r\n constructor() {\r\n this.#registeredWidgets = new Map<string, WidgetBuilder>();\r\n }\r\n\r\n register(widgetType: string, builder: WidgetBuilder): void {\r\n this.#registeredWidgets.set(widgetType, builder);\r\n }\r\n\r\n create(node: FlowNode, widgetType: string, config: any): Widget {\r\n const builder = this.#registeredWidgets.get(widgetType)\r\n if (builder === undefined) {\r\n throw new Error(\"no builder registered for widget: \" + widgetType);\r\n }\r\n return builder(node, config);\r\n }\r\n}\r\n\r\nconst GlobalWidgetFactory = new WidgetFactory();\r\n\r\nGlobalWidgetFactory.register(\"button\", (node: FlowNode, config?: ButtonWidgetConfig) => new ButtonWidget(config));\r\nGlobalWidgetFactory.register(\"number\", (node: FlowNode, config?: NumberWidgetConfig) => new NumberWidget(node, config));\r\nGlobalWidgetFactory.register(\"color\", (node: FlowNode, config?: ColorWidgetConfig) => new ColorWidget(node, config));\r\nGlobalWidgetFactory.register(\"slider\", (node: FlowNode, config?: SliderWidgetConfig) => new SliderWidget(node, config));\r\nGlobalWidgetFactory.register(\"string\", (node: FlowNode, config?: StringWidgetConfig) => new StringWidget(node, config));\r\nGlobalWidgetFactory.register(\"toggle\", (node: FlowNode, config?: ToggleWidgetConfig) => new ToggleWidget(node, config));\r\nGlobalWidgetFactory.register(\"image\", (node: FlowNode, config?: ImageWidgetConfig) => new ImageWidget(config));\r\nGlobalWidgetFactory.register(\"text\", (node: FlowNode, config?: TextWidgetConfig) => new TextWidget(node, config));\r\n\r\nexport { GlobalWidgetFactory };", "import { FlowNode } from \"./node\";\r\nimport { Port } from \"./port\";\r\nimport { BoxCenter, InBox } from \"./types/box\";\r\nimport { Vector2, Zero } from \"./types/vector2\";\r\n\r\nexport interface ConnectionRendererParams {\r\n ctx: CanvasRenderingContext2D;\r\n start: Vector2;\r\n end: Vector2;\r\n graphScale: number;\r\n mouseOver: boolean;\r\n\r\n inNode: FlowNode | null;\r\n inPort: Port | null;\r\n outNode: FlowNode | null;\r\n outPort: Port | null;\r\n}\r\n\r\nexport type ConnectionRenderer = (params: ConnectionRendererParams) => void\r\n\r\nexport function DefaultConnectionRenderer(connectionSize: number, connectionColor: string | undefined, mouseOverSize: number, mouseOverColor: string | undefined): ConnectionRenderer {\r\n return (params: ConnectionRendererParams) => {\r\n\r\n let color = \"#00FF00\";\r\n if (params.outPort !== null) {\r\n color = params.outPort.filledStyleColor()\r\n } else if (params.inPort !== null) {\r\n color = params.inPort.filledStyleColor()\r\n }\r\n\r\n let lineSize = connectionSize * params.graphScale;\r\n if (connectionColor !== undefined) {\r\n color = connectionColor;\r\n }\r\n\r\n if (params.mouseOver || params.inNode?.selected() || params.outNode?.selected()) {\r\n lineSize = mouseOverSize * params.graphScale;\r\n params.ctx.shadowBlur = 25 * params.graphScale;\r\n\r\n if (mouseOverColor !== undefined) {\r\n color = mouseOverColor;\r\n }\r\n\r\n params.ctx.shadowColor = color;\r\n }\r\n\r\n params.ctx.strokeStyle = color;\r\n params.ctx.lineWidth = lineSize;\r\n\r\n // Draw\r\n params.ctx.beginPath();\r\n params.ctx.moveTo(params.start.x, params.start.y);\r\n const midX = (params.start.x + params.end.x) / 2;\r\n params.ctx.bezierCurveTo(midX, params.start.y, midX, params.end.y, params.end.x, params.end.y);\r\n params.ctx.stroke();\r\n params.ctx.shadowBlur = 0;\r\n }\r\n}\r\n\r\nexport class Connection {\r\n\r\n // Variables for holding temp data, preventing object allocations each\r\n // frame\r\n #inPos: Vector2;\r\n #outPos: Vector2;\r\n\r\n #inNode: FlowNode | null;\r\n #inNodePortIndex: number;\r\n #outNode: FlowNode | null;\r\n #outNodePortIndex: number;\r\n #renderer: ConnectionRenderer;\r\n\r\n constructor(\r\n inNode: FlowNode | null,\r\n inNodePortIndex: number,\r\n outNode: FlowNode | null,\r\n outNodePortIndex: number,\r\n renderer: ConnectionRenderer,\r\n ) {\r\n\r\n this.#inNode = inNode;\r\n this.#inNodePortIndex = inNodePortIndex;\r\n this.#outNode = outNode;\r\n this.#outNodePortIndex = outNodePortIndex;\r\n this.#renderer = renderer;\r\n \r\n this.#inPos = Zero();\r\n this.#outPos = Zero();\r\n\r\n if (inNode !== null) {\r\n inNode.inputPort(this.#inNodePortIndex).addConnection(this);\r\n }\r\n\r\n if (outNode !== null) {\r\n outNode.outputPort(this.#outNodePortIndex).addConnection(this);\r\n }\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, graphScale: number, mouseOver: boolean, mousePosition: Vector2 | undefined): void {\r\n\r\n // Not sure what to do here? Maybe we should throw an error in the \r\n // future?\r\n if (this.#inNode === null && this.#outNode === null) {\r\n return;\r\n }\r\n\r\n if (this.#inNode !== null) {\r\n const inPortBox = this.#inNode.inputPortPosition(this.#inNodePortIndex)\r\n if (inPortBox === undefined) {\r\n return;\r\n }\r\n BoxCenter(inPortBox, this.#inPos);\r\n } else if (mousePosition !== undefined) {\r\n this.#inPos.x = mousePosition.x;\r\n this.#inPos.y = mousePosition.y;\r\n } else {\r\n return;\r\n }\r\n\r\n if (this.#outNode !== null) {\r\n const outPortBox = this.#outNode.outputPortPosition(this.#outNodePortIndex);\r\n if (outPortBox === undefined) {\r\n return;\r\n }\r\n BoxCenter(outPortBox, this.#outPos);\r\n } else if (mousePosition !== undefined) {\r\n this.#outPos.x = mousePosition.x;\r\n this.#outPos.y = mousePosition.y;\r\n } else {\r\n return;\r\n }\r\n\r\n this.#renderer({\r\n ctx: ctx,\r\n start: this.#inPos,\r\n end: this.#outPos,\r\n graphScale: graphScale,\r\n mouseOver: mouseOver,\r\n\r\n inPort: this.inPort(),\r\n inNode: this.#inNode,\r\n outPort: this.outPort(),\r\n outNode: this.#outNode,\r\n });\r\n }\r\n\r\n inNode(): FlowNode | null {\r\n return this.#inNode;\r\n }\r\n\r\n outNode(): FlowNode | null {\r\n return this.#outNode;\r\n }\r\n\r\n clearPort(mousePosition: Vector2): void {\r\n if (this.#inNode !== null) {\r\n const inPortBox = this.#inNode.inputPortPosition(this.#inNodePortIndex)\r\n if (inPortBox !== undefined && InBox(inPortBox, mousePosition)) {\r\n this.clearInput();\r\n }\r\n }\r\n\r\n if (this.#outNode !== null) {\r\n const outPortBox = this.#outNode.outputPortPosition(this.#outNodePortIndex);\r\n if (outPortBox !== undefined && InBox(outPortBox, mousePosition)) {\r\n this.clearOutput();\r\n }\r\n }\r\n }\r\n\r\n clearPorts(): void {\r\n this.clearInput();\r\n this.clearOutput();\r\n }\r\n\r\n setInput(node: FlowNode, portIndex: number, replace?: boolean): void {\r\n this.#inNode = node;\r\n this.#inNodePortIndex = portIndex;\r\n\r\n const port = this.#inNode.inputPort(portIndex);\r\n if(!!replace && port.connections().length > 0) {\r\n port.replaceConnection(this, 0);\r\n } else {\r\n port.addConnection(this);\r\n }\r\n }\r\n\r\n setOutput(node: FlowNode, portIndex: number): void {\r\n this.#outNode = node;\r\n this.#outNodePortIndex = portIndex;\r\n this.#outNode.outputPort(portIndex).addConnection(this);\r\n }\r\n\r\n clearInput() {\r\n this.#inNode?.inputPort(this.#inNodePortIndex).clearConnection(this);\r\n this.#inNode = null;\r\n this.#inNodePortIndex = -1;\r\n }\r\n\r\n clearOutput() {\r\n this.#outNode?.outputPort(this.#outNodePortIndex).clearConnection(this);\r\n this.#outNode = null;\r\n this.#outNodePortIndex = -1;\r\n }\r\n\r\n mouseOverPort(mousePosition: Vector2): Port | null {\r\n if (this.#inNode !== null) {\r\n const inPortBox = this.#inNode.inputPortPosition(this.#inNodePortIndex)\r\n if (inPortBox !== undefined && InBox(inPortBox, mousePosition)) {\r\n return this.#inNode.inputPort(this.#inNodePortIndex)\r\n }\r\n }\r\n\r\n if (this.#outNode !== null) {\r\n const outPortBox = this.#outNode.outputPortPosition(this.#outNodePortIndex);\r\n if (outPortBox !== undefined && InBox(outPortBox, mousePosition)) {\r\n return this.#outNode.outputPort(this.#outNodePortIndex)\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n outPort(): Port | null {\r\n if (this.#outNode === null) {\r\n return null;\r\n }\r\n return this.#outNode.outputPort(this.#outNodePortIndex);\r\n }\r\n\r\n inPort(): Port | null {\r\n if (this.#inNode === null) {\r\n return null;\r\n }\r\n return this.#inNode.inputPort(this.#inNodePortIndex);\r\n }\r\n\r\n referencesNode(node: FlowNode): boolean {\r\n if (this.#inNode === node) {\r\n return true;\r\n }\r\n\r\n if (this.#outNode === node) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n}", "import { Vector2, Zero } from \"./types/vector2\";\r\n\r\nexport class Camera {\r\n\r\n zoom: number;\r\n\r\n position: Vector2;\r\n\r\n constructor() {\r\n this.zoom = 1;\r\n this.position = Zero();\r\n }\r\n\r\n screenSpaceToGraphSpace(screenPosition: Vector2, out: Vector2): void {\r\n const scale = this.zoom;\r\n out.x = (screenPosition.x / scale) - (this.position.x / scale);\r\n out.y = (screenPosition.y / scale) - (this.position.y / scale);\r\n }\r\n\r\n graphSpaceToScreenSpace(graphPosition: Vector2, out: Vector2): void {\r\n out.x = this.position.x + (graphPosition.x * this.zoom);\r\n out.y = this.position.y + (graphPosition.y * this.zoom);\r\n }\r\n\r\n reset(): void {\r\n this.zoom = 1;\r\n this.position.x = 0;\r\n this.position.y = 0;\r\n }\r\n}", "import { Camera } from \"./camera\";\r\nimport { NodeFlowGraph } from \"./graph\";\r\nimport { FlowNode } from \"./node\";\r\nimport { NodeSubsystem } from \"./nodes/subsystem\";\r\nimport { Box } from \"./types/box\";\r\n\r\n// TODO: Cyclical dependencies will end our life\r\n\r\nfunction MarkInputs(graph: NodeSubsystem, positions: Array<number>, nodeLUT: Map<FlowNode, number>, node: number, depth: number, shouldSort: Map<FlowNode, boolean>) {\r\n const inputs = graph.connectedInputsNodeReferencesByIndex(node);\r\n for (let i = 0; i < inputs.length; i++) {\r\n const nodeIndex = nodeLUT.get(inputs[i]) as number;\r\n\r\n if (!shouldSort.has(inputs[i])) {\r\n continue;\r\n }\r\n\r\n positions[nodeIndex] = depth;\r\n MarkInputs(graph, positions, nodeLUT, nodeIndex, depth - 1, shouldSort);\r\n }\r\n}\r\n\r\nfunction MarkOutputs(graph: NodeSubsystem, positions: Array<number>, nodeLUT: Map<FlowNode, number>, node: number, depth: number, shouldSort: Map<FlowNode, boolean>) {\r\n const outputs = graph.connectedInputsNodeReferencesByIndex(node);\r\n for (let i = 0; i < outputs.length; i++) {\r\n const nodeIndex = nodeLUT.get(outputs[i]) as number;\r\n\r\n if (!shouldSort.has(outputs[i])) {\r\n continue;\r\n }\r\n\r\n positions[nodeIndex] = depth;\r\n MarkOutputs(graph, positions, nodeLUT, nodeIndex, depth + 1, shouldSort);\r\n }\r\n}\r\n\r\nexport function Organize(ctx: CanvasRenderingContext2D, graph: NodeSubsystem, nodesToSort?: Array<number>): void {\r\n const nodes = graph.getNodes();\r\n const nodeLUT = new Map<FlowNode, number>();\r\n const bounds = new Array<Box>(nodes.length);\r\n const relativePosition = new Array<Array<number>>(nodes.length);\r\n const claimed = new Array<boolean>(nodes.length);\r\n const shouldSort = new Map<FlowNode, boolean>(); // TODO: we don't really need a Map, is their a Set data structure?\r\n\r\n if (nodesToSort) {\r\n if (nodesToSort.length < 2) {\r\n return;\r\n }\r\n for (let i = 0; i < nodesToSort.length; i++) {\r\n shouldSort.set(nodes[nodesToSort[i]], true);\r\n }\r\n } else {\r\n for (let i = 0; i < nodes.length; i++) {\r\n shouldSort.set(nodes[i], true);\r\n }\r\n }\r\n\r\n const camera = new Camera();\r\n\r\n // Initialize everything\r\n for (let i = 0; i < nodes.length; i++) {\r\n bounds[i] = nodes[i].calculateBounds(ctx, camera);\r\n relativePosition[i] = new Array<number>(nodes.length);\r\n nodeLUT.set(nodes[i], i);\r\n claimed[i] = false;\r\n }\r\n\r\n for (let i = 0; i < nodes.length; i++) {\r\n relativePosition[i][i] = 0;\r\n MarkInputs(graph, relativePosition[i], nodeLUT, i, -1, shouldSort);\r\n MarkOutputs(graph, relativePosition[i], nodeLUT, i, 1, shouldSort);\r\n }\r\n\r\n interface entry {\r\n node: number;\r\n length: number;\r\n min: number;\r\n max: number\r\n }\r\n\r\n let entries = new Array<entry>(shouldSort.size);\r\n\r\n let nodeIndex = 0;\r\n for (let i = 0; i < nodes.length; i++) {\r\n if (!shouldSort.has(nodes[i])) {\r\n continue;\r\n }\r\n\r\n let min = 0;\r\n let max = 0;\r\n for (let x = 0; x < nodes.length; x++) {\r\n const val = relativePosition[i][x];\r\n if (val === undefined) {\r\n continue;\r\n }\r\n\r\n min = Math.min(min, val);\r\n max = Math.max(max, val);\r\n }\r\n entries[nodeIndex] = {\r\n length: max - min,\r\n node: i,\r\n min: min,\r\n max: max\r\n }\r\n nodeIndex++\r\n }\r\n\r\n\r\n entries.sort((a, b) => b.length - a.length);\r\n\r\n interface Column {\r\n Nodes: Array<FlowNode>;\r\n Width: number;\r\n }\r\n\r\n const columns = Array<Column>(entries[0].length + 1);\r\n for (let i = 0; i < columns.length; i++) {\r\n columns[i] = {\r\n Nodes: new Array<FlowNode>(),\r\n Width: 0\r\n };\r\n }\r\n\r\n for (let i = 0; i < entries.length; i++) {\r\n const entry = entries[i];\r\n if (claimed[entry.node] === true) {\r\n continue;\r\n }\r\n\r\n const positions = relativePosition[entry.node];\r\n\r\n for (let p = 0; p < positions.length; p++) {\r\n const position = positions[p];\r\n if (position === undefined) {\r\n continue;\r\n }\r\n\r\n if (claimed[p] === true) {\r\n continue;\r\n }\r\n\r\n const nodeBounds = bounds[p];\r\n const column = columns[position - entry.min];\r\n column.Nodes.push(nodes[p])\r\n column.Width = Math.max(column.Width, nodeBounds.Size.x)\r\n\r\n claimed[p] = true;\r\n }\r\n }\r\n\r\n let allColumnsWidths = 0;\r\n for (let c = 0; c < columns.length; c++) {\r\n allColumnsWidths += columns[c].Width;\r\n }\r\n\r\n const widthSpacing = 100;\r\n const heightSpacing = 50;\r\n\r\n let widthOffset = 0;\r\n for (let c = 0; c < columns.length; c++) {\r\n var column = columns[c];\r\n let heightOffset = 0;\r\n\r\n widthOffset -= widthSpacing + column.Width;\r\n\r\n for (let n = 0; n < column.Nodes.length; n++) {\r\n const node = column.Nodes[n];\r\n const nodeBounds = bounds[nodeLUT.get(node) as number];\r\n\r\n let pos = {\r\n x: widthOffset + allColumnsWidths + (columns.length * widthSpacing),\r\n y: heightOffset\r\n }\r\n\r\n heightOffset += nodeBounds.Size.y + heightSpacing\r\n node.setPosition(pos);\r\n }\r\n }\r\n\r\n}", "export function TimeExecution(name: string, callback: Function) {\r\n const start = name + \"_Start\";\r\n const end = name + \"_End\";\r\n\r\n performance.mark(start);\r\n callback();\r\n performance.mark(end);\r\n performance.measure(name, start, end);\r\n}", "import { ContextMenuConfig, ContextMenuItemConfig } from \"../contextMenu\";\r\nimport { FlowNode, FlowNodeConfig } from '../node';\r\nimport { Vector2 } from \"../types/vector2\";\r\nimport { NodeSubsystem } from \"./subsystem\";\r\n\r\ninterface PublisherNodes {\r\n [name: string]: FlowNodeConfig\r\n}\r\n\r\nexport interface PublisherConfig {\r\n name?: string;\r\n description?: string;\r\n version?: string;\r\n nodes?: PublisherNodes\r\n}\r\n\r\nexport class Publisher {\r\n\r\n #name: string;\r\n\r\n #description: string;\r\n\r\n #version: string;\r\n\r\n #registeredNodes: Map<string, FlowNodeConfig>\r\n\r\n constructor(config?: PublisherConfig) {\r\n this.#name = config?.name === undefined ? \"Unknown\" : config.name;\r\n this.#description = config?.description === undefined ? \"\" : config.description;\r\n this.#version = config?.version === undefined ? \"v0.0.0\" : config.version;\r\n\r\n this.#registeredNodes = new Map<string, FlowNodeConfig>();\r\n\r\n if (config?.nodes !== undefined) {\r\n for (const nodeKey in config.nodes) {\r\n this.register(nodeKey, config.nodes[nodeKey]);\r\n }\r\n }\r\n }\r\n\r\n nodes(): Map<string, FlowNodeConfig> {\r\n return this.#registeredNodes;\r\n }\r\n\r\n register(nodeType: string, config: FlowNodeConfig): void {\r\n this.#registeredNodes.set(nodeType, config);\r\n }\r\n\r\n unregister(nodeType: string): boolean {\r\n return this.#registeredNodes.delete(nodeType);\r\n }\r\n\r\n #recurseBuildMenu(graph: NodeSubsystem, name: string, subMenu: Map<string, FlowNodeConfig>, position: Vector2): ContextMenuConfig {\r\n const items: Array<ContextMenuItemConfig> = [];\r\n const subMenus = new Map<string, Map<string, FlowNodeConfig>>();\r\n\r\n for (let [key, nodeConfig] of subMenu) {\r\n const slashIndex = key.indexOf(\"/\")\r\n const bracketIndex = key.indexOf(\"[\")\r\n\r\n if (slashIndex === -1 || (bracketIndex !== -1 && bracketIndex < slashIndex)) {\r\n items.push({\r\n name: key,\r\n callback: () => {\r\n const node = new FlowNode(nodeConfig);\r\n node.setPosition(position);\r\n graph.addNode(node);\r\n },\r\n });\r\n } else {\r\n const elements = key.split(\"/\");\r\n if (!subMenus.has(elements[0])) {\r\n subMenus.set(elements[0], new Map<string, FlowNodeConfig>());\r\n }\r\n\r\n const menu = subMenus.get(elements[0]);\r\n elements.shift();\r\n menu?.set(elements.join(\"/\"), nodeConfig)\r\n }\r\n }\r\n\r\n const menus: Array<ContextMenuConfig> = [];\r\n for (let [key, nodes] of subMenus) {\r\n menus.push(this.#recurseBuildMenu(graph, key, nodes, position))\r\n }\r\n\r\n return {\r\n name: name,\r\n items: items,\r\n subMenus: menus\r\n }\r\n }\r\n\r\n contextMenu(graph: NodeSubsystem, position: Vector2): ContextMenuConfig {\r\n return this.#recurseBuildMenu(graph, this.#name, this.#registeredNodes, position);\r\n }\r\n\r\n create(nodeType: string): FlowNode {\r\n const config = this.#registeredNodes.get(nodeType)\r\n if (config === undefined) {\r\n throw new Error(\"no builder registered for node: \" + nodeType);\r\n }\r\n return new FlowNode(config);\r\n }\r\n}", "import { FlowNode } from \"../node\";\r\nimport { Publisher, PublisherConfig } from \"./publisher\";\r\nimport { ContextMenuConfig } from \"../contextMenu\";\r\nimport { Vector2 } from \"../types/vector2\";\r\nimport { nodeFlowGroup as nodeFlowContextMenuGroup, NodeSubsystem } from \"./subsystem\";\r\n\r\nexport type NodeCreatedCallback = (publisher: string, nodeType: string, node: FlowNode) => void;\r\n\r\ninterface NodeFactoryPublishers {\r\n [name: string]: PublisherConfig\r\n}\r\n\r\nexport interface NodeFactoryConfig {\r\n publishers?: NodeFactoryPublishers\r\n onNodeCreated?: NodeCreatedCallback;\r\n}\r\n\r\nexport class NodeFactory {\r\n #registeredPublishers: Map<string, Publisher>;\r\n\r\n #registeredCallbacks: Array<NodeCreatedCallback>;\r\n\r\n constructor(config?: NodeFactoryConfig) {\r\n this.#registeredPublishers = new Map<string, Publisher>();\r\n this.#registeredCallbacks = new Array<NodeCreatedCallback>();\r\n\r\n if (config?.onNodeCreated) {\r\n this.#registeredCallbacks.push(config?.onNodeCreated);\r\n }\r\n\r\n if (config?.publishers !== undefined) {\r\n for (let entry in config.publishers) {\r\n this.addPublisher(entry, new Publisher(config.publishers[entry]));\r\n }\r\n }\r\n }\r\n\r\n public addOnNodeCreatedListener(callback: NodeCreatedCallback): void {\r\n this.#registeredCallbacks.push(callback);\r\n }\r\n\r\n public addPublisher(identifier: string, publisher: Publisher): void {\r\n this.#registeredPublishers.set(identifier, publisher);\r\n }\r\n\r\n // I'm not even sure if I want this here? You can register on Publishers...\r\n // So why not just make people register with the publisher.\r\n // public register(publisher: string, nodeType: string, config: FlowNodeConfiguration): void {\r\n // const foundPublisher = this.#registeredPublishers.get(publisher);\r\n // if (foundPublisher === undefined) {\r\n // console.error(\"no publisher registered with identifier:\" + publisher);\r\n // return;\r\n // }\r\n\r\n // foundPublisher.register(nodeType, config);\r\n // }\r\n\r\n public create(publisher: string, nodeType: string): FlowNode {\r\n const publisherIdentifier = this.#registeredPublishers.get(publisher)\r\n if (publisherIdentifier === undefined) {\r\n throw new Error(\"no publisher registered with identifier: \" + publisher);\r\n }\r\n const node = publisherIdentifier.create(nodeType);\r\n\r\n for (let i = 0; i < this.#registeredCallbacks.length; i++) {\r\n const callback = this.#registeredCallbacks[i];\r\n callback(publisher, nodeType, node);\r\n }\r\n return node;\r\n }\r\n\r\n public newNodeSubmenus(graph: NodeSubsystem, position: Vector2): Array<ContextMenuConfig> {\r\n const menus: Array<ContextMenuConfig> = [];\r\n for (let [_, publisher] of this.#registeredPublishers) {\r\n menus.push(publisher.contextMenu(graph, position))\r\n }\r\n return menus;\r\n }\r\n\r\n public openMenu(graph: NodeSubsystem, position: Vector2): ContextMenuConfig {\r\n return {\r\n name: \"New Node\",\r\n group: nodeFlowContextMenuGroup,\r\n subMenus: this.newNodeSubmenus(graph, position),\r\n };\r\n }\r\n} \r\n", "import { Camera } from \"../camera\";\r\nimport { Connection, ConnectionRenderer, DefaultConnectionRenderer } from \"../connection\";\r\nimport { CombineContextMenus, ContextMenuConfig } from \"../contextMenu\";\r\nimport { RenderResults } from \"../graphSubsystem\";\r\nimport { FlowNode, NodeState } from \"../node\";\r\nimport { Organize } from \"../organize\";\r\nimport { PassSubsystem } from \"../pass/subsystem\";\r\nimport { TimeExecution } from \"../performance\";\r\nimport { Port, PortType } from \"../port\";\r\nimport { BoxStyle } from \"../styles/box\";\r\nimport { CursorStyle } from \"../styles/cursor\";\r\nimport { Theme } from \"../theme\";\r\nimport { Box, BoxIntersection } from \"../types/box\";\r\nimport { List } from \"../types/list\";\r\nimport { Pool, VectorPool } from \"../types/pool\";\r\nimport { AddVector2, CopyVector2, SubVector2, Vector2, Zero } from \"../types/vector2\";\r\nimport { Widget } from \"../widgets/widget\";\r\nimport { NodeCreatedCallback, NodeFactory, NodeFactoryConfig } from \"./factory\";\r\nimport { Publisher } from \"./publisher\";\r\n\r\nexport type NodeAddedCallback = (node: FlowNode) => void;\r\nexport type NodeRemovedCallback = (node: FlowNode) => void;\r\n\r\nexport const nodeFlowGroup = \"node-flow-graph-node-menu\";\r\n\r\nexport interface ConnectionRendererConfiguration {\r\n size?: number;\r\n color?: string;\r\n\r\n mouseOverSize?: number;\r\n mouseOverColor?: string;\r\n\r\n renderer?: ConnectionRenderer;\r\n}\r\n\r\nfunction BuildConnectionRenderer(config: ConnectionRendererConfiguration | undefined): ConnectionRenderer {\r\n if (config?.renderer !== undefined) {\r\n return config.renderer;\r\n }\r\n\r\n return DefaultConnectionRenderer(\r\n config?.size === undefined ? 2 : config.size,\r\n undefined, // config?.color === undefined ? \"#00FF00\" : config.color,\r\n config?.mouseOverSize === undefined ? 4 : config.mouseOverSize,\r\n undefined, // config?.mouseOverColor === undefined ? \"#00FF22\" : config.mouseOverColor\r\n );\r\n}\r\n\r\ninterface PortIntersection {\r\n Node: FlowNode;\r\n Port: Port;\r\n Index: number;\r\n InputPort: boolean;\r\n}\r\n\r\ninterface NodeSubsystemConfig {\r\n idleConnection?: ConnectionRendererConfiguration\r\n nodes?: NodeFactoryConfig\r\n}\r\n\r\nexport class NodeSubsystem {\r\n\r\n #postProcessPass: PassSubsystem;\r\n\r\n #nodes: Array<FlowNode>;\r\n\r\n #connections: Array<Connection>;\r\n\r\n #nodeHovering: number;\r\n\r\n #nodesGrabbed: List<number>;\r\n\r\n #connectionSelected: Connection | null;\r\n\r\n #idleConnectionRenderer: ConnectionRenderer\r\n\r\n #portHovering: PortIntersection | null;\r\n\r\n #widgetHovering: Widget | null;\r\n\r\n #widgetCurrentlyClicking: Widget | null;\r\n\r\n #cursor: CursorStyle;\r\n\r\n #nodeFactory: NodeFactory;\r\n\r\n #boxSelect: boolean;\r\n\r\n #boxSelectStart_graphSpace: Vector2;\r\n\r\n #boxSelectEnd_graphSpace: Vector2;\r\n\r\n #boxSelectionNodes: List<number>;\r\n\r\n #boxSelectStyle: BoxStyle;\r\n\r\n // LISTENERS ==============================================================\r\n\r\n #nodeRemovedCallbacks: Array<NodeRemovedCallback>;\r\n\r\n #registeredNodeAddedCallbacks: Array<NodeAddedCallback>;\r\n\r\n // ========================================================================\r\n\r\n constructor(postProcessPass: PassSubsystem, config?: NodeSubsystemConfig) {\r\n this.#postProcessPass = postProcessPass;\r\n this.#nodes = [];\r\n this.#nodeHovering = -1;\r\n this.#nodesGrabbed = new List<number>();\r\n this.#connectionSelected = null;\r\n this.#portHovering = null;\r\n this.#widgetHovering = null;\r\n this.#widgetCurrentlyClicking = null;\r\n this.#connections = new Array<Connection>();\r\n this.#nodeFactory = new NodeFactory(config?.nodes);\r\n this.#idleConnectionRenderer = BuildConnectionRenderer(config?.idleConnection);\r\n this.#registeredNodeAddedCallbacks = new Array<NodeAddedCallback>();\r\n this.#nodeRemovedCallbacks = new Array<NodeRemovedCallback>();\r\n this.#cursor = CursorStyle.Default;\r\n\r\n this.#boxSelect = false;\r\n this.#boxSelectStart_graphSpace = Zero();\r\n this.#boxSelectEnd_graphSpace = Zero();\r\n this.#boxSelectionNodes = new List<number>();\r\n this.#boxSelectStyle = new BoxStyle({\r\n border: {\r\n color: Theme.BoxSelect.Color,\r\n size: Theme.BoxSelect.Size,\r\n },\r\n color: \"rgba(0,0,0,0)\",\r\n radius: Theme.BoxSelect.Radius\r\n });\r\n }\r\n\r\n public addPublisher(identifier: string, publisher: Publisher): void {\r\n this.#nodeFactory.addPublisher(identifier, publisher);\r\n }\r\n\r\n public addOnNodeCreatedListener(callback: NodeCreatedCallback): void {\r\n this.#nodeFactory.addOnNodeCreatedListener(callback);\r\n }\r\n\r\n public nodeFactory(): NodeFactory {\r\n return this.#nodeFactory;\r\n }\r\n\r\n public addOnNodeAddedListener(callback: NodeAddedCallback): void {\r\n if (callback === null || callback === undefined) {\r\n return;\r\n }\r\n this.#registeredNodeAddedCallbacks.push(callback);\r\n }\r\n\r\n public addOnNodeRemovedListener(callback: NodeRemovedCallback): void {\r\n if (callback === null || callback === undefined) {\r\n return;\r\n }\r\n this.#nodeRemovedCallbacks.push(callback);\r\n }\r\n\r\n clickStart(mousePosition: Vector2, camera: Camera, ctrlKey: boolean): boolean {\r\n this.#boxSelect = false;\r\n\r\n let hoveringSomething = false;\r\n if (this.#nodeHovering > -1) {\r\n this.#selectNodeByIndex(this.#nodeHovering, !ctrlKey);\r\n\r\n for (let i = 0; i < this.#nodes.length; i++) {\r\n if (this.#nodes[i].selected()) {\r\n this.#nodesGrabbed.Push(i);\r\n }\r\n }\r\n\r\n hoveringSomething = true;\r\n }\r\n\r\n if (this.#widgetHovering !== null) {\r\n this.#widgetHovering.ClickStart();\r\n this.#widgetCurrentlyClicking = this.#widgetHovering;\r\n hoveringSomething = true;\r\n }\r\n\r\n if (this.#portHovering === null) {\r\n\r\n if (ctrlKey && !hoveringSomething) {\r\n camera.screenSpaceToGraphSpace(mousePosition, this.#boxSelectStart_graphSpace)\r\n CopyVector2(this.#boxSelectEnd_graphSpace, this.#boxSelectStart_graphSpace);\r\n this.#boxSelect = true;\r\n }\r\n\r\n return hoveringSomething || ctrlKey;\r\n }\r\n\r\n if (this.#portHovering.InputPort) {\r\n for (let i = 0; i < this.#connections.length; i++) {\r\n if (this.#connections[i].inPort() === this.#portHovering.Port) {\r\n this.#connections[i].clearInput();\r\n this.#connectionSelected = this.#connections[i];\r\n break;\r\n }\r\n }\r\n } else {\r\n let inNode: FlowNode | null = this.#portHovering.Node\r\n let inNodeIndex = this.#portHovering.Index\r\n let outNode: FlowNode | null = this.#portHovering.Node\r\n let outNodeIndex = this.#portHovering.Index\r\n\r\n if (this.#portHovering.InputPort) {\r\n outNode = null;\r\n outNodeIndex = -1;\r\n } else {\r\n inNode = null;\r\n inNodeIndex = -1;\r\n }\r\n\r\n const connection = new Connection(inNode, inNodeIndex, outNode, outNodeIndex, this.#idleConnectionRenderer);\r\n this.#connectionSelected = connection;\r\n this.#connections.push(connection);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n mouseDragEvent(delta: Vector2, scale: number): boolean {\r\n let nodeMoved = false;\r\n\r\n VectorPool.run(() => {\r\n const scaledDelta = VectorPool.get();\r\n scaledDelta.x = delta.x / scale;\r\n scaledDelta.y = delta.y / scale;\r\n AddVector2(this.#boxSelectEnd_graphSpace, this.#boxSelectEnd_graphSpace, scaledDelta);\r\n\r\n if (this.#interactingWithNode()) {\r\n for (let i = 0; i < this.#nodesGrabbed.Count(); i++) {\r\n const node = this.#nodes[this.#nodesGrabbed.At(i)];\r\n if (node.locked()) {\r\n continue;\r\n }\r\n node.translate(scaledDelta);\r\n nodeMoved = true;\r\n }\r\n }\r\n });\r\n\r\n if (nodeMoved) {\r\n return true;\r\n }\r\n return this.#interactingWithConnection() || this.#interactingWithWidget() || this.#boxSelect;\r\n }\r\n\r\n clearNodeInputConnection(node: FlowNode, index: number): void {\r\n const port = node.inputPort(index);\r\n for (let i = this.#connections.length - 1; i >= 0; i--) {\r\n if (this.#connections[i].inPort() === port) {\r\n this.#removeConnection(this.#connections[i], true);\r\n }\r\n }\r\n }\r\n\r\n clickEnd(): void {\r\n\r\n for (let i = 0; i < this.#nodesGrabbed.Count(); i++) {\r\n const node = this.#nodes[this.#nodesGrabbed.At(i)];\r\n node.raiseDragStoppedEvent();\r\n }\r\n this.#nodesGrabbed.Clear();\r\n\r\n if (this.#boxSelect) {\r\n for (let i = 0; i < this.#boxSelectionNodes.Count(); i++) {\r\n this.#selectNode(this.#nodes[this.#boxSelectionNodes.At(i)], false);\r\n }\r\n\r\n this.#boxSelectionNodes.Clear();\r\n this.#boxSelect = false;\r\n }\r\n\r\n if (this.#widgetCurrentlyClicking !== null) {\r\n this.#widgetCurrentlyClicking.ClickEnd();\r\n this.#widgetCurrentlyClicking = null;\r\n }\r\n\r\n if (this.#connectionSelected === null) {\r\n return;\r\n }\r\n\r\n if (this.#portHovering === null) {\r\n this.#clearCurrentlySelectedConnection();\r\n return;\r\n }\r\n\r\n const port = this.#portHovering.Port;\r\n const conn = this.#connectionSelected;\r\n\r\n // If the port we're hovering is the one we started the connection \r\n // with...\r\n if (port === conn.inPort() || port === conn.outPort()) {\r\n this.#clearCurrentlySelectedConnection();\r\n return;\r\n }\r\n\r\n // If the port we're hoving is input, and also we started the \r\n // connection with an input, we can't do anything. We can't connect\r\n // input to input\r\n if (this.#portHovering.InputPort && conn.inPort() !== null) {\r\n this.#clearCurrentlySelectedConnection();\r\n return;\r\n }\r\n\r\n // Same with out. Can't connect output to output\r\n if (!this.#portHovering.InputPort && conn.outPort() !== null) {\r\n this.#clearCurrentlySelectedConnection();\r\n return;\r\n }\r\n\r\n // Different types, can't connect\r\n if (this.#portHovering.InputPort && this.#portHovering.Port.getDataType() !== conn.outPort()?.getDataType()) {\r\n this.#clearCurrentlySelectedConnection();\r\n return;\r\n }\r\n\r\n // Different types, can't connect\r\n if (!this.#portHovering.InputPort && this.#portHovering.Port.getDataType() !== conn.inPort()?.getDataType()) {\r\n this.#clearCurrentlySelectedConnection();\r\n return;\r\n }\r\n\r\n // Ight. Let's make the connection.\r\n if (this.#portHovering.InputPort) {\r\n let replace = false;\r\n const inputPort = this.#portHovering.Node.inputPort(this.#portHovering.Index);\r\n if (this.#portHovering.Port.getPortType() !== PortType.InputArray && inputPort.connections().length > 0) {\r\n replace = true;\r\n }\r\n\r\n if (replace) {\r\n // Remove input port's connection's output\r\n inputPort.connections()[0].clearOutput();\r\n\r\n // Remove connection from this subsystem\r\n this.#removeConnection(inputPort.connections()[0], false);\r\n }\r\n conn.setInput(this.#portHovering.Node, this.#portHovering.Index, replace);\r\n\r\n } else {\r\n conn.setOutput(this.#portHovering.Node, this.#portHovering.Index);\r\n }\r\n\r\n this.#connectionSelected = null;\r\n }\r\n\r\n connectNodes(nodeOut: FlowNode, outPort: number, nodeIn: FlowNode, inPort: number): Connection | undefined {\r\n const outType = nodeOut.outputPort(outPort).getDataType();\r\n const inType = nodeIn.inputPort(inPort).getDataType();\r\n if (outType !== inType) {\r\n console.error(\"can't connect nodes of different types\", outType, inType);\r\n return;\r\n }\r\n\r\n // Check and make sure the nodes aren't already connected\r\n const existingInputConnections = nodeIn.inputPort(inPort).connections();\r\n for (let i = 0; i < existingInputConnections.length; i++) {\r\n const connection = existingInputConnections[i];\r\n\r\n\r\n if (connection.outNode() !== nodeOut) {\r\n continue;\r\n }\r\n\r\n if (connection.outPort() !== nodeOut.outputPort(outPort)) {\r\n continue;\r\n }\r\n\r\n // This kind of connection already *exists*. Let's not add a duplicate\r\n return;\r\n }\r\n\r\n const connection = new Connection(\r\n nodeIn, inPort,\r\n nodeOut, outPort,\r\n this.#idleConnectionRenderer,\r\n );\r\n this.#connections.push(connection);\r\n return connection;\r\n }\r\n\r\n getNodes(): Array<FlowNode> {\r\n return this.#nodes;\r\n }\r\n\r\n /**\r\n * Returns all nodes who are connected to the inputs of the \r\n * node in question\r\n * \r\n * @param nodeIndex index of the node to examine inputs to\r\n */\r\n connectedInputsNodeReferencesByIndex(nodeIndex: number): Array<FlowNode> {\r\n return this.connectedInputsNodeReferences(this.#nodes[nodeIndex]);\r\n }\r\n\r\n connectedInputsNodeReferences(node: FlowNode): Array<FlowNode> {\r\n const connections = new Array<FlowNode>();\r\n for (let i = 0; i < this.#connections.length; i++) {\r\n const connection = this.#connections[i];\r\n if (node !== connection.inNode()) {\r\n continue;\r\n }\r\n\r\n const outNode = connection.outNode();\r\n if (outNode === null) {\r\n continue;\r\n }\r\n\r\n connections.push(outNode);\r\n }\r\n return connections;\r\n }\r\n\r\n connectedOutputsNodeReferences(nodeIndex: number): Array<FlowNode> {\r\n const node = this.#nodes[nodeIndex]\r\n const connections = new Array<FlowNode>();\r\n for (let i = 0; i < this.#connections.length; i++) {\r\n const connection = this.#connections[i];\r\n if (node !== connection.outNode()) {\r\n continue;\r\n }\r\n\r\n const inNode = connection.inNode();\r\n if (inNode === null) {\r\n continue;\r\n }\r\n\r\n connections.push(inNode);\r\n }\r\n return connections;\r\n }\r\n\r\n addNode(node: FlowNode): void {\r\n this.#nodes.push(node);\r\n for (let i = 0; i < this.#registeredNodeAddedCallbacks.length; i++) {\r\n const callback = this.#registeredNodeAddedCallbacks[i];\r\n if (!callback) {\r\n continue;\r\n }\r\n callback(node);\r\n }\r\n }\r\n\r\n fileDrop(file: File): boolean {\r\n if (this.#nodeHovering === -1) {\r\n return false;\r\n }\r\n this.#nodes[this.#nodeHovering].dropFile(file);\r\n return true;\r\n }\r\n\r\n #removeNodeConnections(nodeIndex: number): void {\r\n if (nodeIndex >= this.#nodes.length || nodeIndex < 0) {\r\n console.error(\"invalid node connection\");\r\n return;\r\n }\r\n for (let i = this.#connections.length - 1; i >= 0; i--) {\r\n if (this.#connections[i].referencesNode(this.#nodes[nodeIndex])) {\r\n this.#removeConnectionByIndex(i, true);\r\n }\r\n }\r\n }\r\n\r\n #interactingWithNode(): boolean {\r\n return this.#nodesGrabbed.Count() > 0;\r\n }\r\n\r\n #interactingWithConnection(): boolean {\r\n return this.#connectionSelected !== null;\r\n }\r\n\r\n #interactingWithWidget(): boolean {\r\n return this.#widgetCurrentlyClicking !== null;\r\n }\r\n\r\n removeNode(node: FlowNode): void {\r\n for (let i = 0; i < this.#nodes.length; i++) {\r\n if (this.#nodes[i] === node) {\r\n this.#removeNodeByIndex(i);\r\n }\r\n }\r\n }\r\n\r\n #removeNodeByIndex(nodeIndex: number): void {\r\n this.#removeNodeConnections(nodeIndex);\r\n const node = this.#nodes[nodeIndex];\r\n this.#nodes.splice(nodeIndex, 1);\r\n for (let i = 0; i < this.#nodeRemovedCallbacks.length; i++) {\r\n this.#nodeRemovedCallbacks[i](node);\r\n }\r\n }\r\n\r\n #removeConnectionByIndex(index: number, clearPorts: boolean): void {\r\n if (clearPorts) {\r\n this.#connections[index].clearPorts();\r\n }\r\n this.#connections.splice(index, 1);\r\n }\r\n\r\n #removeConnection(connection: Connection, clearPorts: boolean): void {\r\n const index = this.#connections.indexOf(connection);\r\n if (index > -1) {\r\n this.#removeConnectionByIndex(index, clearPorts);\r\n } else {\r\n console.error(\"no connection found to remove\");\r\n }\r\n }\r\n\r\n organize(ctx: CanvasRenderingContext2D): void {\r\n Organize(ctx, this);\r\n }\r\n\r\n #nodesSelected(): Array<number> {\r\n const selected = new Array<number>();\r\n for (let i = 0; i < this.#nodes.length; i++) {\r\n if (this.#nodes[i].selected()) {\r\n selected.push(i);\r\n }\r\n }\r\n return selected;\r\n }\r\n\r\n #organizeSelected(ctx: CanvasRenderingContext2D): void {\r\n Organize(ctx, this, this.#nodesSelected());\r\n }\r\n\r\n openContextMenu(ctx: CanvasRenderingContext2D, position: Vector2): ContextMenuConfig | null {\r\n\r\n const organizeNodesSubMenu: ContextMenuConfig = {\r\n name: \"Organize\",\r\n group: nodeFlowGroup,\r\n items: [\r\n {\r\n name: \"All Nodes\",\r\n group: nodeFlowGroup,\r\n callback: () => {\r\n this.organize(ctx);\r\n }\r\n }\r\n ]\r\n }\r\n\r\n let config: ContextMenuConfig = {\r\n items: [],\r\n subMenus: [\r\n organizeNodesSubMenu,\r\n this.#nodeFactory.openMenu(this, position)\r\n ]\r\n }\r\n\r\n if (this.#nodesSelected().length > 0) {\r\n organizeNodesSubMenu.items?.push({\r\n name: \"Selected Nodes\",\r\n group: nodeFlowGroup,\r\n callback: () => {\r\n this.#organizeSelected(ctx)\r\n }\r\n })\r\n }\r\n\r\n if (this.#nodeHovering > -1) {\r\n const nodeToReview = this.#nodeHovering;\r\n const nodeToReviewNode = this.#nodes[nodeToReview];\r\n\r\n config.subMenus?.push({\r\n group: nodeFlowGroup,\r\n name: \"Select\",\r\n items: [\r\n {\r\n name: \"Direct Connected Nodes\",\r\n group: nodeFlowGroup,\r\n callback: () => {\r\n this.#selectConnectedNodes(nodeToReview);\r\n }\r\n },\r\n {\r\n name: \"Input Nodes + Descendents\",\r\n group: nodeFlowGroup,\r\n callback: () => {\r\n this.#selectInputNodesAndDescendents(nodeToReviewNode);\r\n }\r\n },\r\n ]\r\n })\r\n\r\n config.subMenus?.push({\r\n group: nodeFlowGroup,\r\n name: \"Delete\",\r\n items: [\r\n {\r\n name: \"Node\",\r\n group: nodeFlowGroup,\r\n callback: () => {\r\n this.#removeNodeByIndex(nodeToReview);\r\n }\r\n },\r\n {\r\n name: \"Connections\",\r\n group: nodeFlowGroup,\r\n callback: () => {\r\n this.#removeNodeConnections(nodeToReview);\r\n }\r\n }\r\n ]\r\n })\r\n config = CombineContextMenus(config, nodeToReviewNode.contextMenu());\r\n }\r\n return config;\r\n }\r\n\r\n #selectInputNodesAndDescendents(node: FlowNode): void {\r\n if (node === undefined) {\r\n return;\r\n }\r\n this.#selectNode(node, false);\r\n\r\n const inputs = this.connectedInputsNodeReferences(node);\r\n for (let i = 0; i < inputs.length; i++) {\r\n this.#selectInputNodesAndDescendents(inputs[i]);\r\n }\r\n }\r\n\r\n #selectConnectedNodes(nodeIndex: number): void {\r\n const node = this.#nodes[nodeIndex];\r\n if (node === undefined) {\r\n return;\r\n }\r\n this.#selectNode(node, false);\r\n\r\n const outputs = this.connectedOutputsNodeReferences(nodeIndex);\r\n for (let i = 0; i < outputs.length; i++) {\r\n this.#selectNode(outputs[i], false);\r\n }\r\n\r\n const inputs = this.connectedInputsNodeReferencesByIndex(nodeIndex);\r\n for (let i = 0; i < inputs.length; i++) {\r\n this.#selectNode(inputs[i], false);\r\n }\r\n }\r\n\r\n #selectNodeByIndex(nodeIndex: number, unselectOthers: boolean): void {\r\n this.#selectNode(this.#nodes[nodeIndex], unselectOthers);\r\n }\r\n\r\n #selectNode(node: FlowNode, unselectOthers: boolean): void {\r\n node.select();\r\n\r\n if (!unselectOthers) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < this.#nodes.length; i++) {\r\n if (node === this.#nodes[i]) {\r\n continue\r\n }\r\n this.#nodes[i].unselect();\r\n }\r\n }\r\n\r\n #clearCurrentlySelectedConnection(): void {\r\n if (this.#connectionSelected === null) {\r\n return;\r\n }\r\n this.#removeConnection(this.#connectionSelected, true);\r\n this.#connectionSelected = null;\r\n }\r\n\r\n #renderConnections(ctx: CanvasRenderingContext2D, camera: Camera, mousePosition: Vector2 | undefined): void {\r\n for (let i = 0; i < this.#connections.length; i++) {\r\n let portMousedOver = false;\r\n if (mousePosition !== undefined) {\r\n portMousedOver = this.#connections[i].mouseOverPort(mousePosition) !== null;\r\n }\r\n this.#connections[i].render(ctx, camera.zoom, portMousedOver, mousePosition);\r\n }\r\n }\r\n\r\n #renderNodes(ctx: CanvasRenderingContext2D, camera: Camera, mousePosition: Vector2 | undefined) {\r\n this.#portHovering = null;\r\n this.#widgetHovering = null;\r\n this.#nodeHovering = -1;\r\n this.#boxSelectionNodes.Clear();\r\n\r\n const selectedBox_Screenspace = this.#boxSelectionScreenspaceBox(camera);\r\n\r\n for (let i = 0; i < this.#nodes.length; i++) {\r\n let state = NodeState.Idle;\r\n\r\n if (mousePosition !== undefined && !this.#boxSelect) {\r\n const intersection = this.#nodes[i].inBounds(ctx, camera, mousePosition);\r\n\r\n if (intersection.Node !== undefined && intersection.PortIndex === undefined && intersection.Widget === undefined) {\r\n state = NodeState.MouseOver;\r\n this.#nodeHovering = i;\r\n this.#cursor = CursorStyle.Grab;\r\n }\r\n\r\n if (intersection.Widget !== undefined) {\r\n // console.log(i, this.#nodes[i].title(), \"widget\")\r\n this.#widgetHovering = intersection.Widget\r\n this.#cursor = CursorStyle.Pointer;\r\n }\r\n\r\n if (intersection.Port !== undefined && intersection.Node !== undefined && intersection.PortIndex !== undefined && intersection.PortIsInput !== undefined) {\r\n this.#portHovering = {\r\n Index: intersection.PortIndex,\r\n Node: intersection.Node,\r\n Port: intersection.Port,\r\n InputPort: intersection.PortIsInput\r\n };\r\n }\r\n } else if (this.#boxSelect) {\r\n const nodeBounds = this.#nodes[i].calculateBounds(ctx, camera);\r\n\r\n if (BoxIntersection(selectedBox_Screenspace, nodeBounds)) {\r\n state = NodeState.MouseOver;\r\n this.#boxSelectionNodes.Push(i);\r\n }\r\n }\r\n\r\n // if (i === this.#nodeSelected) {\r\n // state = NodeState.Selected;\r\n // }\r\n\r\n if (this.#nodes[i].selected() && this.#nodesGrabbed.Count() > 0) {\r\n state = NodeState.Grabbed;\r\n this.#cursor = CursorStyle.Grabbing;\r\n }\r\n\r\n this.#nodes[i].render(ctx, camera, state, mousePosition, this.#postProcessPass);\r\n }\r\n }\r\n\r\n #boxSelectionScreenspaceBox(camera: Camera): Box {\r\n const box = { Position: Zero(), Size: Zero() }\r\n\r\n camera.graphSpaceToScreenSpace(this.#boxSelectStart_graphSpace, box.Position);\r\n camera.graphSpaceToScreenSpace(this.#boxSelectEnd_graphSpace, box.Size);\r\n\r\n SubVector2(box.Size, box.Size, box.Position);\r\n\r\n return box;\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, camera: Camera, mousePosition: Vector2 | undefined): RenderResults | undefined {\r\n this.#cursor = CursorStyle.Default;\r\n TimeExecution(\"Render_Connections\", () => {\r\n this.#renderConnections(ctx, camera, mousePosition);\r\n })\r\n TimeExecution(\"Render_Nodes\", () => {\r\n this.#renderNodes(ctx, camera, mousePosition);\r\n })\r\n\r\n if (this.#boxSelect) {\r\n const box = this.#boxSelectionScreenspaceBox(camera);\r\n ctx.setLineDash([Theme.BoxSelect.LineDashLength]);\r\n this.#boxSelectStyle.Draw(ctx, box, 1);\r\n ctx.setLineDash([]);\r\n }\r\n\r\n return { cursorStyle: this.#cursor }\r\n }\r\n\r\n}", "import { Popup } from \"../popup\";\r\n\r\ninterface FormValue {\r\n name: string;\r\n\r\n // https://html.spec.whatwg.org/multipage/input.html#dom-input-type\r\n type: string;\r\n\r\n startingValue: any;\r\n}\r\n\r\ninterface Config {\r\n title: string;\r\n form: Array<FormValue>;\r\n onUpdate: (newValue: Array<any>) => void;\r\n onCancel?: () => void;\r\n}\r\n\r\nexport function FormPopup(config: Config): Popup {\r\n let input = new Array<HTMLInputElement | null>();\r\n\r\n const setOption = \"Set\";\r\n const cancelOption = \"Cancel\";\r\n\r\n return new Popup({\r\n title: config.title,\r\n options: [setOption, cancelOption],\r\n content: () => {\r\n const container = document.createElement('div');\r\n container.style.flexDirection = \"column\";\r\n container.style.display = \"flex\";\r\n\r\n for (let i = 0; i < config.form.length; i++) {\r\n const title = document.createElement(\"h4\");\r\n title.innerText = config.form[i].name;\r\n container.append(title);\r\n\r\n const ele = document.createElement('input');\r\n ele.value = config.form[i].startingValue;\r\n ele.type = config.form[i].type;\r\n container.append(ele);\r\n input.push(ele);\r\n container.append(document.createElement(\"br\"));\r\n }\r\n\r\n return container;\r\n },\r\n onClose: (button: string | null): void => {\r\n if (button !== setOption || input === null) {\r\n if (config.onCancel) {\r\n config.onCancel();\r\n }\r\n return;\r\n }\r\n\r\n const values = new Array<any>();\r\n for (let i = 0; i < config.form.length; i++) {\r\n values[i] = input[i]?.value;\r\n }\r\n config.onUpdate(values);\r\n },\r\n });\r\n}\r\n", "import { Port, PortConfig, PortType } from \"./port\";\r\nimport { FontWeight, TextStyle, TextStyleConfig, TextStyleFallback } from \"./styles/text\";\r\nimport { Box, InBox } from \"./types/box\";\r\nimport { CopyVector2, Distance, ScaleVector, Vector2, Zero } from \"./types/vector2\";\r\nimport { Widget } from './widgets/widget';\r\nimport { List } from './types/list';\r\nimport { BoxStyle, BoxStyleConfig, BoxStyleWithFallback } from \"./styles/box\";\r\nimport { Text } from \"./types/text\";\r\nimport { GlobalWidgetFactory } from \"./widgets/factory\";\r\nimport { Theme } from \"./theme\";\r\nimport { TextAlign } from \"./styles/canvasTextAlign\";\r\nimport { TextBaseline } from \"./styles/canvasTextBaseline\";\r\nimport { CombineContextMenus, ContextMenuConfig, ContextMenuItemConfig } from \"./contextMenu\";\r\nimport { nodeFlowGroup } from \"./nodes/subsystem\";\r\nimport { SetStringPopup } from \"./popups/string\";\r\nimport { ButtonWidget } from \"./widgets/button\";\r\nimport { FormPopup } from \"./popups/form\";\r\nimport { NumberWidget } from \"./widgets/number\";\r\nimport { StringWidget } from \"./widgets/string\";\r\nimport { ToggleWidget } from \"./widgets/toggle\";\r\nimport { ColorWidget } from \"./widgets/color\";\r\nimport { SliderWidget } from \"./widgets/slider\";\r\nimport { ImageWidget } from \"./widgets/image\";\r\nimport { VectorPool } from \"./types/pool\";\r\nimport { Camera } from \"./camera\";\r\nimport { PassSubsystem } from \"./pass/subsystem\";\r\nimport { splitString, splitStringIntoLines } from \"./utils/string\";\r\nimport { Metadata } from './metadata';\r\n\r\nconst MINIMUM_NODE_WIDTH = 150;\r\n\r\ntype AnyPropertyChangeCallback = (propertyName: string, oldValue: any, newValue: any) => void\r\ntype PropertyChangeCallback = (oldValue: any, newValue: any) => void\r\ntype TitleChangeCallback = (node: FlowNode, oldTitle: string, newTitle: string) => void\r\ntype InfoChangeCallback = (node: FlowNode, oldInfo: string, newInfo: string) => void\r\n\r\n\r\nexport interface WidgetConfig {\r\n type?: string,\r\n config?: any\r\n}\r\n\r\nexport interface FlowNodeTitleConfig {\r\n textStyle?: TextStyleConfig;\r\n color?: string;\r\n padding?: number;\r\n}\r\n\r\nexport interface FlowNodeStyle {\r\n title?: FlowNodeTitleConfig;\r\n idle?: BoxStyleConfig;\r\n mouseOver?: BoxStyleConfig;\r\n grabbed?: BoxStyleConfig;\r\n selected?: BoxStyleConfig;\r\n portText?: TextStyleConfig;\r\n}\r\n\r\nexport enum MessageType {\r\n Info = \"info\",\r\n Warning = \"warning\",\r\n Error = \"error\"\r\n};\r\n\r\nfunction MessageTypeColor(messageType: MessageType): string {\r\n switch (messageType) {\r\n case MessageType.Info:\r\n return Theme.Node.Message.InfoColor;\r\n\r\n case MessageType.Warning:\r\n return Theme.Node.Message.WarnColor;\r\n\r\n case MessageType.Error:\r\n return Theme.Node.Message.ErrorColor;\r\n\r\n default:\r\n throw new Error(`unrecognized message type ${messageType}`)\r\n }\r\n}\r\n\r\nexport interface NodeMessageConfig {\r\n message: string;\r\n type?: MessageType;\r\n alwaysShow?: boolean;\r\n color?: string;\r\n}\r\n\r\nexport interface FlowNodeConfig {\r\n position?: Vector2;\r\n title?: string;\r\n subTitle?: string;\r\n info?: string;\r\n messages?: Array<NodeMessageConfig>\r\n locked?: boolean;\r\n data?: Metadata;\r\n contextMenu?: ContextMenuConfig;\r\n metadata?: any;\r\n\r\n canEditTitle?: boolean;\r\n canEditInfo?: boolean;\r\n canEditPorts?: boolean;\r\n\r\n // Ports\r\n inputs?: Array<PortConfig>;\r\n outputs?: Array<PortConfig>;\r\n\r\n // Callbacks\r\n onGrab?: () => void;\r\n onRelease?: () => void;\r\n onSelect?: () => void;\r\n onUnselect?: () => void;\r\n onDragStop?: (FlowNode: FlowNode) => void;\r\n onFileDrop?: (file: File) => void;\r\n onTitleChange?: TitleChangeCallback;\r\n onInfoChange?: InfoChangeCallback;\r\n\r\n // Widgets\r\n widgets?: Array<WidgetConfig>;\r\n\r\n // Styling\r\n style?: FlowNodeStyle;\r\n}\r\n\r\nexport enum NodeState {\r\n Idle,\r\n MouseOver,\r\n Grabbed\r\n}\r\n\r\nexport interface NodeIntersection {\r\n Node?: FlowNode\r\n\r\n // Port\r\n Port?: Port\r\n PortIndex?: number\r\n PortIsInput?: boolean\r\n\r\n // Widget\r\n Widget?: Widget\r\n WidgetIndex?: number\r\n\r\n}\r\n\r\nclass MessageRenderer {\r\n\r\n #text: Text;\r\n\r\n #alwaysShow: boolean;\r\n\r\n constructor(config: NodeMessageConfig) {\r\n this.#alwaysShow = config.alwaysShow ? config.alwaysShow : false;\r\n this.#text = new Text(config.message,\r\n {\r\n color: config.color ? config.color : MessageTypeColor(config.type ? config.type : MessageType.Info),\r\n },\r\n {\r\n LineSpacing: 2.5,\r\n MaxWidth: 200\r\n }\r\n );\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, scale: number, position: Vector2, hovering: boolean): number {\r\n if (!this.#alwaysShow && !hovering) {\r\n return 0;\r\n }\r\n ctx.textAlign = TextAlign.Center;\r\n this.#text.render(ctx, scale, position);\r\n return this.#text.height(ctx) * scale;\r\n }\r\n}\r\n\r\nexport class FlowNode {\r\n\r\n #position: Vector2;\r\n\r\n #title: Text;\r\n\r\n #subTitle: Text;\r\n\r\n #infoSymbol: Text;\r\n\r\n #infoText: string;\r\n\r\n #messages: Array<MessageRenderer>\r\n\r\n #input: Array<Port>;\r\n\r\n #output: Array<Port>;\r\n\r\n #widgets: Array<Widget>;\r\n\r\n #locked: boolean;\r\n\r\n #canEditTitle: boolean;\r\n\r\n #canEditInfo: boolean;\r\n\r\n #canEditPorts: boolean;\r\n\r\n #contextMenu: ContextMenuConfig | null;\r\n\r\n #metadata: any;\r\n\r\n // Callbacks\r\n\r\n #onSelect: Array<() => void>;\r\n\r\n #onUnselect: Array<() => void>;\r\n\r\n #onFiledrop: Array<(file: File) => void>;\r\n\r\n #onDragStop: Array<(node: FlowNode) => void>;\r\n\r\n #titleChangeCallback: Array<TitleChangeCallback>;\r\n\r\n #infoChangeCallback: Array<InfoChangeCallback>;\r\n\r\n // Styling ================================================================\r\n\r\n #titleColor: string;\r\n\r\n #selectedStyle: BoxStyle;\r\n\r\n #stateStyles: Map<NodeState, BoxStyle>;\r\n\r\n #padding: number;\r\n\r\n #portTextStyle: TextStyle;\r\n\r\n #elementSpacing: number;\r\n\r\n // Runtime ================================================================\r\n\r\n #selected: boolean;\r\n\r\n #inputPortPositions: List<Box>;\r\n\r\n #outputPortPositions: List<Box>;\r\n\r\n #widgetPositions: List<Box>;\r\n\r\n #data: Metadata;\r\n\r\n #registeredAnyPropertyChangeCallbacks: Array<AnyPropertyChangeCallback>;\r\n\r\n #registeredPropertyChangeCallbacks: Map<string, Array<PropertyChangeCallback>>;\r\n\r\n constructor(config?: FlowNodeConfig) {\r\n this.#input = new Array<Port>();\r\n this.#output = new Array<Port>();\r\n this.#widgets = new Array<Widget>();\r\n this.#inputPortPositions = new List<Box>();\r\n this.#outputPortPositions = new List<Box>();\r\n this.#widgetPositions = new List<Box>();\r\n this.#elementSpacing = 15;\r\n this.#locked = config?.locked === undefined ? false : config.locked;\r\n this.#data = config?.data === undefined ? {} : config?.data;\r\n this.#registeredPropertyChangeCallbacks = new Map<string, Array<PropertyChangeCallback>>();\r\n this.#registeredAnyPropertyChangeCallbacks = new Array<AnyPropertyChangeCallback>();\r\n this.#canEditPorts = config?.canEditPorts === undefined ? false : config.canEditPorts;\r\n this.#canEditTitle = config?.canEditTitle === undefined ? false : config.canEditTitle;\r\n this.#canEditInfo = config?.canEditInfo === undefined ? false : config.canEditInfo;\r\n this.#contextMenu = config?.contextMenu === undefined ? null : config.contextMenu;\r\n this.#metadata = config?.metadata;\r\n\r\n this.#messages = [];\r\n if (config?.messages) {\r\n for (let i = 0; i < config.messages.length; i++) {\r\n const message = config.messages[i];\r\n this.#messages.push(new MessageRenderer(message));\r\n }\r\n }\r\n\r\n this.#selected = false;\r\n this.#onSelect = new Array<() => void>();\r\n this.#onUnselect = new Array<() => void>();\r\n this.#onFiledrop = new Array<(file: File) => void>();\r\n this.#onDragStop = new Array<() => void>();\r\n this.#titleChangeCallback = new Array<TitleChangeCallback>();\r\n this.#infoChangeCallback = new Array<InfoChangeCallback>();\r\n\r\n if (config?.onSelect) {\r\n this.#onSelect.push(config?.onSelect);\r\n }\r\n\r\n if (config?.onUnselect) {\r\n this.#onUnselect.push(config?.onUnselect);\r\n }\r\n\r\n if (config?.onFileDrop) {\r\n this.#onFiledrop.push(config?.onFileDrop);\r\n }\r\n\r\n if (config?.onDragStop) {\r\n this.#onDragStop.push(config.onDragStop);\r\n }\r\n\r\n if (config?.onTitleChange) {\r\n this.#titleChangeCallback.push(config.onTitleChange);\r\n }\r\n\r\n if (config?.onInfoChange) {\r\n this.#infoChangeCallback.push(config.onInfoChange);\r\n }\r\n\r\n this.#position = config?.position === undefined ? { x: 0, y: 0 } : config.position;\r\n this.#title = new Text(\r\n config?.title === undefined ? \"\" : config.title,\r\n TextStyleFallback(config?.style?.title?.textStyle, {\r\n size: 16,\r\n weight: FontWeight.Bold,\r\n color: Theme.Node.FontColor\r\n })\r\n );\r\n\r\n this.#subTitle = new Text(\r\n config?.subTitle === undefined ? \"\" : config.subTitle,\r\n TextStyleFallback(config?.style?.title?.textStyle, {\r\n size: 10,\r\n weight: FontWeight.Bold,\r\n color: Theme.Node.FontColor\r\n })\r\n );\r\n\r\n this.#infoSymbol = new Text(\r\n \"i\",\r\n {\r\n size: 13,\r\n weight: FontWeight.Bold,\r\n color: Theme.Node.FontColor\r\n }\r\n );\r\n this.#infoText = config?.info ? config?.info : \"\";\r\n\r\n this.#titleColor = config?.style?.title?.color === undefined ? \"#154050\" : config?.style?.title?.color;\r\n\r\n this.#padding = config?.style?.title?.padding === undefined ? 15 : config?.style?.title?.padding;\r\n\r\n this.#stateStyles = new Map<NodeState, BoxStyle>();\r\n this.#stateStyles.set(NodeState.Idle, new BoxStyle(BoxStyleWithFallback(config?.style?.idle, {\r\n border: { color: Theme.Node.Border.Idle, size: 1 },\r\n radius: Theme.Node.BorderRadius,\r\n color: Theme.Node.BackgroundColor,\r\n })));\r\n this.#stateStyles.set(NodeState.MouseOver, new BoxStyle(BoxStyleWithFallback(config?.style?.mouseOver, {\r\n border: { color: Theme.Node.Border.MouseOver, size: 1.1, },\r\n radius: Theme.Node.BorderRadius,\r\n color: Theme.Node.BackgroundColor,\r\n })));\r\n this.#stateStyles.set(NodeState.Grabbed, new BoxStyle(BoxStyleWithFallback(config?.style?.grabbed, {\r\n border: { color: Theme.Node.Border.Grabbed, size: 2, },\r\n radius: Theme.Node.BorderRadius,\r\n color: Theme.Node.BackgroundColor,\r\n })));\r\n\r\n this.#selectedStyle = new BoxStyle(BoxStyleWithFallback(config?.style?.selected, {\r\n border: { color: Theme.Node.Border.Selected, size: 1, },\r\n radius: Theme.Node.BorderRadius,\r\n color: Theme.Node.BackgroundColor,\r\n }));\r\n\r\n this.#portTextStyle = new TextStyle({\r\n size: config?.style?.portText?.size === undefined ? 14 : config?.style?.portText?.size,\r\n color: config?.style?.portText?.color === undefined ? Theme.Node.Port.FontColor : config?.style?.portText?.color,\r\n font: config?.style?.portText?.font,\r\n weight: config?.style?.portText?.weight,\r\n });\r\n\r\n if (config?.inputs !== undefined) {\r\n for (let i = 0; i < config.inputs.length; i++) {\r\n this.addInput(config.inputs[i]);\r\n }\r\n }\r\n\r\n if (config?.outputs !== undefined) {\r\n for (let i = 0; i < config.outputs.length; i++) {\r\n this.addOutput(config.outputs[i]);\r\n }\r\n }\r\n\r\n if (config?.widgets !== undefined) {\r\n for (let i = 0; i < config.widgets.length; i++) {\r\n const widget = config.widgets[i];\r\n if (widget.type === undefined) {\r\n continue;\r\n }\r\n this.addWidget(GlobalWidgetFactory.create(this, widget.type, widget.config))\r\n }\r\n }\r\n }\r\n\r\n public metadata(): any {\r\n return this.#metadata;\r\n }\r\n\r\n public selected(): boolean {\r\n return this.#selected;\r\n }\r\n\r\n public select(): void {\r\n if (this.#selected) {\r\n return;\r\n }\r\n this.#selected = true;\r\n for (let i = 0; i < this.#onSelect.length; i++) {\r\n this.#onSelect[i]();\r\n }\r\n }\r\n\r\n public raiseDragStoppedEvent() {\r\n for (let i = 0; i < this.#onDragStop.length; i++) {\r\n this.#onDragStop[i](this);\r\n }\r\n }\r\n\r\n public addTitleChangeListener(callback: TitleChangeCallback): void {\r\n if (callback === undefined || callback === null) {\r\n }\r\n this.#titleChangeCallback.push(callback);\r\n }\r\n\r\n public addInfoChangeListener(callback: InfoChangeCallback): void {\r\n if (callback === undefined || callback === null) {\r\n }\r\n this.#infoChangeCallback.push(callback);\r\n }\r\n\r\n\r\n public addDragStoppedListener(callback: (node: FlowNode) => void): void {\r\n if (callback === undefined || callback === null) {\r\n }\r\n this.#onDragStop.push(callback);\r\n }\r\n\r\n public addAnyPropertyChangeListener(callback: AnyPropertyChangeCallback): void {\r\n if (callback === undefined || callback === null) {\r\n }\r\n this.#registeredAnyPropertyChangeCallbacks.push(callback);\r\n }\r\n\r\n public addPropertyChangeListener(name: string, callback: PropertyChangeCallback): void {\r\n if (!this.#registeredPropertyChangeCallbacks.has(name)) {\r\n this.#registeredPropertyChangeCallbacks.set(name, []);\r\n }\r\n\r\n const callbacks = this.#registeredPropertyChangeCallbacks.get(name);\r\n if (callbacks === undefined) {\r\n return;\r\n }\r\n callbacks.push(callback);\r\n }\r\n\r\n public setProperty(name: string, value: any): void {\r\n const oldValue = this.#data[name];\r\n if (oldValue === value) {\r\n return;\r\n }\r\n\r\n this.#data[name] = value;\r\n\r\n for (let i = 0; i < this.#registeredAnyPropertyChangeCallbacks.length; i++) {\r\n this.#registeredAnyPropertyChangeCallbacks[i](name, oldValue, value);\r\n }\r\n\r\n const callbacks = this.#registeredPropertyChangeCallbacks.get(name);\r\n if (callbacks === undefined) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < callbacks.length; i++) {\r\n callbacks[i](oldValue, value);\r\n }\r\n }\r\n\r\n public getProperty(name: string): any {\r\n return this.#data[name];\r\n }\r\n\r\n #popupNodeTitleSelection(): void {\r\n SetStringPopup({\r\n title: \"Set Node Title\",\r\n startingValue: this.title(),\r\n onUpdate: (value: string): void => {\r\n this.setTitle(value);\r\n },\r\n }).Show();\r\n }\r\n\r\n #popupNodeInfoSelection(): void {\r\n SetStringPopup({\r\n title: \"Set Node Info\",\r\n startingValue: this.#infoText,\r\n onUpdate: (value: string): void => {\r\n this.setInfo(value);\r\n },\r\n }).Show();\r\n }\r\n\r\n #popupNewButtonWidget(): void {\r\n SetStringPopup({\r\n title: \"New Button Widget Text\",\r\n startingValue: \"My Button\",\r\n onUpdate: (value: string): void => {\r\n this.addWidget(new ButtonWidget({\r\n text: value\r\n }));\r\n },\r\n }).Show()\r\n }\r\n\r\n #widgetSubmenu(): ContextMenuConfig {\r\n return {\r\n name: \"Widget\",\r\n items: [\r\n {\r\n name: \"Button\",\r\n callback: this.#popupNewButtonWidget.bind(this),\r\n },\r\n {\r\n name: \"Number\",\r\n callback: () => {\r\n this.addWidget(new NumberWidget(this))\r\n }\r\n },\r\n {\r\n name: \"Color\",\r\n callback: () => {\r\n this.addWidget(new ColorWidget(this))\r\n }\r\n },\r\n {\r\n name: \"Slider\",\r\n callback: () => {\r\n FormPopup({\r\n title: \"New Slider\",\r\n form: [\r\n {\r\n name: \"min\",\r\n type: \"number\",\r\n startingValue: 0\r\n },\r\n {\r\n name: \"max\",\r\n type: \"number\",\r\n startingValue: 100\r\n }\r\n ],\r\n onUpdate: (data: Array<any>) => {\r\n this.addWidget(new SliderWidget(this, {\r\n min: data[0],\r\n max: data[1],\r\n }));\r\n }\r\n }).Show();\r\n }\r\n },\r\n {\r\n name: \"String\",\r\n callback: () => {\r\n this.addWidget(new StringWidget(this))\r\n }\r\n },\r\n {\r\n name: \"Toggle\",\r\n callback: () => {\r\n this.addWidget(new ToggleWidget(this))\r\n }\r\n },\r\n {\r\n name: \"Image\",\r\n callback: () => {\r\n FormPopup({\r\n title: \"New Image\",\r\n form: [\r\n {\r\n name: \"URL\",\r\n type: \"text\",\r\n startingValue: \"https://pbs.twimg.com/media/GYabtu6bsAA7m99?format=jpg&name=medium\"\r\n },\r\n {\r\n name: \"Max Width\",\r\n type: \"number\",\r\n startingValue: MINIMUM_NODE_WIDTH\r\n },\r\n {\r\n name: \"Max Height\",\r\n type: \"number\",\r\n startingValue: MINIMUM_NODE_WIDTH\r\n }\r\n ],\r\n onUpdate: (data: Array<any>) => {\r\n this.addWidget(new ImageWidget({\r\n image: data[0],\r\n maxWidth: data[1],\r\n maxHeight: data[2],\r\n }));\r\n }\r\n }).Show();\r\n }\r\n }\r\n ]\r\n };\r\n }\r\n\r\n public contextMenu(): ContextMenuConfig {\r\n let config: ContextMenuConfig = {\r\n group: nodeFlowGroup,\r\n items: [\r\n // {\r\n // name: \"Debug\",\r\n // callback: () => {\r\n // console.log(this);\r\n // }\r\n // }\r\n ],\r\n subMenus: [],\r\n }\r\n\r\n if (this.canEditPorts() || this.canEditTitle() || this.#canEditInfo) {\r\n\r\n const items = new Array<ContextMenuItemConfig>();\r\n if (this.canEditTitle()) {\r\n items.push({\r\n name: \"Title\",\r\n callback: () => {\r\n this.#popupNodeTitleSelection();\r\n }\r\n })\r\n }\r\n\r\n if (this.#canEditInfo) {\r\n items.push({\r\n name: \"Info\",\r\n callback: () => {\r\n this.#popupNodeInfoSelection();\r\n }\r\n })\r\n }\r\n\r\n const submenus = new Array<ContextMenuConfig>();\r\n if (this.canEditPorts()) {\r\n submenus.push({\r\n name: \"Add\",\r\n items: [\r\n {\r\n name: \"Input\",\r\n callback: () => {\r\n FormPopup({\r\n title: \"New Input\",\r\n form: [\r\n {\r\n name: \"name\",\r\n type: \"text\",\r\n startingValue: \"input\"\r\n },\r\n {\r\n name: \"type\",\r\n type: \"text\",\r\n startingValue: \"string\"\r\n }\r\n ],\r\n onUpdate: (data: Array<any>) => {\r\n this.addInput({\r\n name: data[0],\r\n type: data[1]\r\n })\r\n }\r\n }).Show();\r\n }\r\n },\r\n {\r\n name: \"Output\",\r\n callback: () => {\r\n FormPopup({\r\n title: \"New Output\",\r\n form: [\r\n {\r\n name: \"name\",\r\n type: \"text\",\r\n startingValue: \"output\"\r\n },\r\n {\r\n name: \"type\",\r\n type: \"text\",\r\n startingValue: \"string\"\r\n }\r\n ],\r\n onUpdate: (data: Array<any>) => {\r\n this.addOutput({\r\n name: data[0],\r\n type: data[1]\r\n })\r\n }\r\n }).Show();\r\n }\r\n },\r\n ],\r\n subMenus: [\r\n this.#widgetSubmenu(),\r\n ]\r\n });\r\n }\r\n\r\n config.subMenus?.push({\r\n group: nodeFlowGroup,\r\n name: \"Edit\",\r\n items: items,\r\n subMenus: submenus,\r\n })\r\n }\r\n\r\n if (this.locked()) {\r\n config.items?.push({\r\n name: \"Unlock Node Position\",\r\n group: nodeFlowGroup,\r\n callback: this.unlock.bind(this),\r\n });\r\n } else {\r\n config.items?.push({\r\n name: \"Lock Node Position\",\r\n group: nodeFlowGroup,\r\n callback: this.lock.bind(this),\r\n })\r\n }\r\n\r\n if (this.#contextMenu !== null) {\r\n config = CombineContextMenus(config, this.#contextMenu)\r\n }\r\n\r\n return config;\r\n }\r\n\r\n public unselect(): void {\r\n if (!this.#selected) {\r\n return;\r\n }\r\n this.#selected = false;\r\n for (let i = 0; i < this.#onUnselect.length; i++) {\r\n this.#onUnselect[i]();\r\n }\r\n }\r\n\r\n public addUnselectListener(callback: () => void): void {\r\n this.#onUnselect.push(callback);\r\n }\r\n\r\n public addSelectListener(callback: () => void): void {\r\n this.#onSelect.push(callback);\r\n }\r\n\r\n public dropFile(file: File): void {\r\n for (let i = 0; i < this.#onFiledrop.length; i++) {\r\n this.#onFiledrop[i](file);\r\n }\r\n }\r\n\r\n public addFileDropListener(callback: (file: File) => void): void {\r\n this.#onFiledrop.push(callback);\r\n }\r\n\r\n public locked(): boolean {\r\n return this.#locked;\r\n }\r\n\r\n public lock(): void {\r\n this.#locked = true;\r\n }\r\n\r\n public unlock(): void {\r\n this.#locked = false;\r\n }\r\n\r\n public setPosition(position: Vector2): void {\r\n CopyVector2(this.#position, position);\r\n }\r\n\r\n public getPosition(): Vector2 {\r\n return this.#position;\r\n }\r\n\r\n // #measureTitleText(ctx: CanvasRenderingContext2D, scale: number): Vector2 {\r\n // return this.#titleTextStyle.measure(ctx, scale, this.#title);\r\n // }\r\n\r\n public calculateBounds(ctx: CanvasRenderingContext2D, camera: Camera): Box {\r\n const tempMeasurement = Zero();\r\n\r\n const doublePadding = this.#padding * 2;\r\n\r\n const screenSpacePosition = Zero();\r\n camera.graphSpaceToScreenSpace(this.#position, screenSpacePosition);\r\n\r\n const size = Zero();\r\n this.#title.size(ctx, 1, size);\r\n\r\n const subtitleSize = Zero();\r\n this.#subTitle.size(ctx, 1, subtitleSize);\r\n size.x = Math.max(size.x, subtitleSize.x);\r\n\r\n if (this.#infoText !== \"\") {\r\n size.x += (size.y * 4);\r\n }\r\n\r\n size.x += doublePadding;\r\n size.y += doublePadding + (this.#elementSpacing * this.#input.length);\r\n\r\n for (let i = 0; i < this.#input.length; i++) {\r\n const port = this.#input[i];\r\n this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);\r\n size.y += tempMeasurement.y;\r\n size.x = Math.max(size.x, tempMeasurement.x + doublePadding)\r\n }\r\n\r\n size.y += (this.#elementSpacing * this.#output.length);\r\n\r\n for (let i = 0; i < this.#output.length; i++) {\r\n const port = this.#output[i];\r\n this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);\r\n size.y += tempMeasurement.y;\r\n size.x = Math.max(size.x, tempMeasurement.x + doublePadding)\r\n }\r\n\r\n size.y += (this.#elementSpacing * this.#widgets.length);\r\n for (let i = 0; i < this.#widgets.length; i++) {\r\n const element = this.#widgets[i];\r\n const eleSize = element.Size();\r\n size.y += eleSize.y\r\n size.x = Math.max(size.x, (eleSize.x) + doublePadding)\r\n }\r\n\r\n // Add some padding at the end!\r\n size.y += this.#elementSpacing\r\n\r\n size.x = Math.max(size.x, MINIMUM_NODE_WIDTH)\r\n ScaleVector(size, camera.zoom);\r\n\r\n return {\r\n Position: screenSpacePosition,\r\n Size: size,\r\n }\r\n }\r\n\r\n addInput(config: PortConfig): Port {\r\n const port = new Port(this, config.array ? PortType.InputArray : PortType.Input, config);\r\n this.#input.push(port);\r\n return port;\r\n }\r\n\r\n addOutput(config: PortConfig): Port {\r\n const port = new Port(this, PortType.Output, config);\r\n this.#output.push(port);\r\n return port;\r\n }\r\n\r\n addWidget(widget: Widget): void {\r\n this.#widgets.push(widget);\r\n }\r\n\r\n removeWidget(widget: Widget): void {\r\n const index = this.#widgets.indexOf(widget, 0);\r\n if (index === -1) {\r\n throw new Error(\"node does not contain widget\");\r\n }\r\n this.#widgets.splice(index, 1);\r\n }\r\n\r\n getWidget(index: number): Widget {\r\n return this.#widgets[index];\r\n }\r\n\r\n widgetCount(): number {\r\n return this.#widgets.length;\r\n }\r\n\r\n translate(delta: Vector2): void {\r\n this.#position.x += delta.x;\r\n this.#position.y += delta.y;\r\n }\r\n\r\n inBounds(ctx: CanvasRenderingContext2D, camera: Camera, position: Vector2): NodeIntersection {\r\n var intersection: NodeIntersection = {}\r\n\r\n const box = this.calculateBounds(ctx, camera);\r\n if (InBox(box, position)) {\r\n intersection.Node = this;\r\n }\r\n\r\n for (let i = 0; i < this.#inputPortPositions.Count(); i++) {\r\n if (InBox(this.#inputPortPositions.At(i), position)) {\r\n intersection.Node = this;\r\n intersection.PortIndex = i;\r\n intersection.PortIsInput = true;\r\n intersection.Port = this.#input[i]\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.#outputPortPositions.Count(); i++) {\r\n if (InBox(this.#outputPortPositions.At(i), position)) {\r\n intersection.Node = this;\r\n intersection.PortIndex = i;\r\n intersection.PortIsInput = false;\r\n intersection.Port = this.#output[i];\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.#widgetPositions.Count(); i++) {\r\n if (InBox(this.#widgetPositions.At(i), position)) {\r\n intersection.Node = this;\r\n intersection.WidgetIndex = i;\r\n intersection.Widget = this.#widgets[i];\r\n }\r\n }\r\n\r\n return intersection;\r\n }\r\n\r\n canEditTitle(): boolean {\r\n return this.#canEditTitle;\r\n }\r\n\r\n canEditPorts(): boolean {\r\n return this.#canEditPorts;\r\n }\r\n\r\n title(): string {\r\n return this.#title.get();\r\n }\r\n\r\n setTitle(newTitle: string): void {\r\n if (!this.#canEditTitle) {\r\n console.warn(\"setTitle instruction ignored, as node has been marked un-editable\");\r\n return;\r\n }\r\n\r\n let cleaned = newTitle;\r\n if (cleaned === null || cleaned === undefined) {\r\n cleaned = \"\";\r\n }\r\n\r\n const old = this.title();\r\n if (cleaned === old) {\r\n return;\r\n }\r\n\r\n this.#title.set(cleaned);\r\n\r\n for (let i = 0; i < this.#titleChangeCallback.length; i++) {\r\n const callback = this.#titleChangeCallback[i];\r\n callback(this, old, cleaned);\r\n }\r\n }\r\n\r\n setInfo(newInfo: string): void {\r\n if (!this.#canEditInfo) {\r\n console.warn(\"setInfo instruction ignored, as node has been marked un-editable\");\r\n }\r\n\r\n let cleaned = newInfo;\r\n if (cleaned === null || cleaned === undefined) {\r\n cleaned = \"\";\r\n }\r\n\r\n if (cleaned === this.#infoText) {\r\n return;\r\n }\r\n\r\n const old = this.#infoText;\r\n this.#infoText = cleaned;\r\n\r\n for (let i = 0; i < this.#infoChangeCallback.length; i++) {\r\n const callback = this.#infoChangeCallback[i];\r\n callback(this, old, cleaned);\r\n }\r\n }\r\n\r\n inputPortPosition(index: number): Box {\r\n return this.#inputPortPositions.At(index);\r\n }\r\n\r\n inputPort(index: number): Port {\r\n return this.#input[index];\r\n }\r\n\r\n inputs(): number {\r\n return this.#input.length;\r\n }\r\n\r\n outputPortPosition(index: number): Box {\r\n return this.#outputPortPositions.At(index);\r\n }\r\n\r\n outputPort(index: number): Port {\r\n return this.#output[index];\r\n }\r\n\r\n outputs(): number {\r\n return this.#output.length;\r\n }\r\n\r\n #calculateStyle(state: NodeState): BoxStyle {\r\n // Let the node being selected override the idle style\r\n if (this.#selected && state === NodeState.Idle) {\r\n return this.#selectedStyle;\r\n }\r\n\r\n let boxStyle = this.#stateStyles.get(state);\r\n if (boxStyle === undefined) {\r\n throw new Error(\"no registered border style for state: \" + state)\r\n }\r\n return boxStyle;\r\n }\r\n\r\n addMessage(message: NodeMessageConfig): void {\r\n this.#messages.push(new MessageRenderer(message));\r\n }\r\n\r\n clearMessages(): void {\r\n this.#messages = [];\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, camera: Camera, state: NodeState, mousePosition: Vector2 | undefined, postProcess: PassSubsystem): void {\r\n VectorPool.run(() => {\r\n const tempMeasurement = VectorPool.get();\r\n\r\n this.#inputPortPositions.Clear();\r\n this.#outputPortPositions.Clear();\r\n this.#widgetPositions.Clear();\r\n const scaledPadding = this.#padding * camera.zoom;\r\n const scaledElementSpacing = this.#elementSpacing * camera.zoom;\r\n\r\n const nodeBounds = this.calculateBounds(ctx, camera);\r\n\r\n // Background\r\n const nodeStyle = this.#calculateStyle(state);\r\n nodeStyle.Draw(ctx, nodeBounds, camera.zoom);\r\n\r\n // Title\r\n const borderSize = nodeStyle.borderSize();\r\n ctx.textAlign = TextAlign.Center;\r\n ctx.textBaseline = TextBaseline.Middle;\r\n\r\n const titleSize = VectorPool.get();\r\n this.#title.size(ctx, camera.zoom, titleSize);\r\n\r\n const subtitleSize = VectorPool.get();\r\n this.#subTitle.size(ctx, camera.zoom, subtitleSize);\r\n\r\n const titleBoxSize = VectorPool.get();\r\n titleBoxSize.x = nodeBounds.Size.x;\r\n titleBoxSize.y = titleSize.y + (scaledPadding * 2);\r\n\r\n ctx.fillStyle = this.#titleColor;\r\n ctx.beginPath();\r\n const titleX = nodeBounds.Position.x + (borderSize * camera.zoom * 0.5)\r\n const titleY = nodeBounds.Position.y + (borderSize * camera.zoom * 0.5)\r\n const titleWidth = titleBoxSize.x - (borderSize * camera.zoom);\r\n const titleHeight = titleBoxSize.y - (borderSize * camera.zoom * 0.5);\r\n ctx.roundRect(\r\n titleX, titleY, titleWidth, titleHeight,\r\n [nodeStyle.radius() * camera.zoom, nodeStyle.radius() * camera.zoom, 0, 0]\r\n );\r\n ctx.fill();\r\n // ctx.stroke();\r\n\r\n const titlePosition = VectorPool.get();\r\n titlePosition.x = nodeBounds.Position.x + (nodeBounds.Size.x / 2)\r\n titlePosition.y = nodeBounds.Position.y + scaledPadding + (titleSize.y / 2)\r\n\r\n if (this.#subTitle.get() !== \"\") {\r\n const subtitlePosition = VectorPool.get();\r\n CopyVector2(subtitlePosition, titlePosition);\r\n\r\n // TODO: I'm fudging a bunch of numbers ot make it fit nicely \r\n // together. \r\n // \r\n // Need to come up with like, proper logic about how we ensure \r\n // title and subtitle fit together\r\n subtitlePosition.y -= titleSize.y / 1.5;\r\n titlePosition.y += scaledPadding / 2\r\n\r\n this.#subTitle.render(ctx, camera.zoom, subtitlePosition);\r\n }\r\n\r\n this.#title.render(ctx, camera.zoom, titlePosition);\r\n\r\n // Info symbol\r\n if (this.#infoText !== \"\") {\r\n const infoRadius = titleHeight * .25;\r\n const centerX = titleX + titleWidth - (titleHeight * .25) - infoRadius;\r\n const centerY = titleY + (titleHeight * .25) + infoRadius;\r\n\r\n const infoPosition = VectorPool.get();\r\n infoPosition.x = centerX;\r\n infoPosition.y = centerY + (titleHeight * .025);\r\n\r\n let infoLineThickness = 1.5 * camera.zoom;\r\n\r\n if (mousePosition && Distance(infoPosition, mousePosition) <= infoRadius) {\r\n infoLineThickness *= 1.5;\r\n\r\n // This is a slightly expensive function if we're not \r\n // caching, but it only executes while we're mousing over \r\n // the info symbol, so I'm not particularly obligated to\r\n // optimize it. \r\n //\r\n // If you're just bored, def cache the split string method,\r\n // and figure out a system to recalculate as a node has its\r\n // title, port, or widgets change.\r\n //\r\n // Should probably break out the lambda into a proper \r\n // function as well. I think as it is, we're creating a new\r\n // lambda function per frame?\r\n postProcess.queue(() => {\r\n this.#infoSymbol.style().setupStyle(ctx, camera.zoom);\r\n ctx.textAlign = TextAlign.Center;\r\n\r\n const infoBoxWidth = titleWidth * 1.5;\r\n const textEntries = splitStringIntoLines(ctx, this.#infoText, infoBoxWidth);\r\n\r\n const lineHeight = (this.#infoSymbol.style().getSize() + 2);\r\n const infoBoxHeight = lineHeight * textEntries.length * camera.zoom;\r\n const scaledLineHeight = lineHeight * camera.zoom;\r\n const start = titleY - infoBoxHeight - (scaledLineHeight / 2);\r\n\r\n // Draw box\r\n ctx.fillStyle = this.#titleColor;\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n centerX - (infoBoxWidth / 2) - (scaledLineHeight / 2),\r\n start - scaledLineHeight,\r\n infoBoxWidth + scaledLineHeight,\r\n infoBoxHeight + scaledLineHeight,\r\n nodeStyle.radius() * camera.zoom\r\n );\r\n ctx.fill();\r\n\r\n // Render Text\r\n this.#infoSymbol.style().setupStyle(ctx, camera.zoom);\r\n for (let i = 0; i < textEntries.length; i++) {\r\n const entry = textEntries[i];\r\n ctx.fillText(entry, centerX, start + (i * lineHeight * camera.zoom));\r\n }\r\n });\r\n }\r\n\r\n ctx.beginPath();\r\n ctx.arc(centerX, centerY, infoRadius, 0, 2 * Math.PI, false);\r\n ctx.lineWidth = infoLineThickness;\r\n ctx.strokeStyle = this.#infoSymbol.getColor();\r\n ctx.stroke();\r\n\r\n ctx.textAlign = TextAlign.Center;\r\n this.#infoSymbol.render(ctx, camera.zoom, infoPosition);\r\n }\r\n\r\n\r\n // Input Ports\r\n let startY = nodeBounds.Position.y + (scaledPadding * 2) + titleSize.y + scaledElementSpacing;\r\n const leftSide = nodeBounds.Position.x + scaledPadding;\r\n for (let i = 0; i < this.#input.length; i++) {\r\n ctx.textAlign = TextAlign.Left;\r\n const port = this.#input[i];\r\n this.#portTextStyle.measure(ctx, camera.zoom, port.getDisplayName(), tempMeasurement);\r\n const position = VectorPool.get();\r\n\r\n position.x = nodeBounds.Position.x;\r\n position.y = startY + (tempMeasurement.y / 2);\r\n\r\n // Text\r\n this.#portTextStyle.setupStyle(ctx, camera.zoom);\r\n ctx.fillText(port.getDisplayName(), leftSide, position.y);\r\n\r\n // Port\r\n this.#inputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));\r\n\r\n startY += tempMeasurement.y + scaledElementSpacing;\r\n }\r\n\r\n // Output Ports\r\n const rightSide = nodeBounds.Position.x + nodeBounds.Size.x;\r\n ctx.textAlign = TextAlign.Right;\r\n for (let i = 0; i < this.#output.length; i++) {\r\n const port = this.#output[i];\r\n this.#portTextStyle.measure(ctx, camera.zoom, port.getDisplayName(), tempMeasurement);\r\n const position = VectorPool.get();\r\n position.x = rightSide;\r\n position.y = startY + (tempMeasurement.y / 2);\r\n\r\n // Text\r\n this.#portTextStyle.setupStyle(ctx, camera.zoom);\r\n ctx.fillText(port.getDisplayName(), rightSide - scaledPadding, position.y);\r\n\r\n // Port\r\n this.#outputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));\r\n\r\n startY += tempMeasurement.y + scaledElementSpacing;\r\n }\r\n\r\n // Widgets\r\n for (let i = 0; i < this.#widgets.length; i++) {\r\n const widget = this.#widgets[i];\r\n const widgetSize = widget.Size();\r\n const scaledWidgetWidth = widgetSize.x * camera.zoom;\r\n\r\n const position = VectorPool.get();\r\n position.x = nodeBounds.Position.x + ((nodeBounds.Size.x - scaledWidgetWidth) / 2);\r\n position.y = startY;\r\n\r\n this.#widgetPositions.Push(widget.Draw(ctx, position, camera.zoom, mousePosition));\r\n startY += (widgetSize.y * camera.zoom) + scaledElementSpacing;\r\n }\r\n\r\n // Messages\r\n const messageStart = VectorPool.get();\r\n messageStart.x = nodeBounds.Position.x + (nodeBounds.Size.x / 2);\r\n messageStart.y = nodeBounds.Position.y + nodeBounds.Size.y + (15 * camera.zoom);\r\n for (let i = 0; i < this.#messages.length; i++) {\r\n const message = this.#messages[i];\r\n messageStart.y += message.render(ctx, camera.zoom, messageStart, !(state === NodeState.Idle)) + (10 * camera.zoom);\r\n }\r\n })\r\n }\r\n}\r\n", "export enum MarkdownTokenType {\r\n Text = \"Text\",\r\n H1 = \"H1\",\r\n H2 = \"H2\",\r\n H3 = \"H3\",\r\n NewLine = \"New Line\",\r\n Star = \"Star\",\r\n Space = \"Space\",\r\n BackTick = \"`\"\r\n}\r\n\r\nexport class MarkdownToken {\r\n\r\n #type: MarkdownTokenType;\r\n\r\n #lexeme: string\r\n\r\n #tokenStart: number\r\n\r\n #tokenEnd: number\r\n\r\n constructor(type: MarkdownTokenType, lexeme: string, tokenStart: number, tokenEnd: number) {\r\n this.#type = type;\r\n this.#lexeme = lexeme;\r\n this.#tokenStart = tokenStart;\r\n this.#tokenEnd = tokenEnd;\r\n }\r\n\r\n type(): MarkdownTokenType {\r\n return this.#type;\r\n }\r\n\r\n lexeme(): string {\r\n return this.#lexeme;\r\n }\r\n\r\n tokenStart(): number {\r\n return this.#tokenStart;\r\n }\r\n tokenEnd(): number {\r\n return this.#tokenEnd;\r\n }\r\n}\r\n", "import { MarkdownToken, MarkdownTokenType } from \"./token\";\r\n\r\nexport class MarkdownLexicalParser {\r\n\r\n #body: string;\r\n\r\n #index: number\r\n\r\n #tokens: Array<MarkdownToken>;\r\n\r\n constructor(body: string) {\r\n this.#index = 0;\r\n this.#body = body;\r\n this.#tokens = new Array<MarkdownToken>();\r\n }\r\n\r\n tokens(): Array<MarkdownToken> {\r\n return this.#tokens;\r\n }\r\n\r\n #current(): string {\r\n if (this.#index > this.#body.length - 1) {\r\n return \"\"\r\n }\r\n return this.#body.charAt(this.#index);\r\n }\r\n\r\n #inc(): void {\r\n this.#index++\r\n }\r\n\r\n #next(): string {\r\n this.#index++\r\n if (this.#index > this.#body.length - 1) {\r\n return \"\"\r\n }\r\n return this.#body.charAt(this.#index);\r\n }\r\n\r\n #lastToken = 0;\r\n \r\n #addToken(token: MarkdownTokenType, lexeme: string): void {\r\n this.#tokens.push(new MarkdownToken(token, lexeme, this.#lastToken, this.#index));\r\n this.#lastToken = this.#index;\r\n }\r\n\r\n #h2(): void {\r\n let char = this.#next();\r\n if (char === \"#\") {\r\n this.#addToken(MarkdownTokenType.H3, \"###\");\r\n\r\n // Move it off the character for the next reading\r\n this.#inc();\r\n } else {\r\n this.#addToken(MarkdownTokenType.H2, \"##\");\r\n }\r\n }\r\n\r\n #h1(): void {\r\n let char = this.#next();\r\n if (char === \"#\") {\r\n this.#h2();\r\n } else {\r\n this.#addToken(MarkdownTokenType.H1, \"#\");\r\n }\r\n }\r\n\r\n #whiteSpace(): void {\r\n let char = this.#current();\r\n\r\n while (char !== \"\") {\r\n if (char !== \" \" && char !== \"\\t\") {\r\n break;\r\n }\r\n char = this.#next();\r\n }\r\n\r\n this.#addToken(MarkdownTokenType.Space, \" \")\r\n }\r\n\r\n #text(): void {\r\n let char = this.#current();\r\n\r\n let started = -1;\r\n\r\n while (char !== \"\") {\r\n if (char === \" \" || char === \"\\t\") {\r\n\r\n // Eat white space if we haven't seen anything yet!\r\n if (started === -1) {\r\n this.#inc();\r\n continue;\r\n }\r\n }\r\n\r\n // End of the line!\r\n if (char === \"\\n\" || char === \"*\" || char === \"`\") {\r\n if (started != -1) {\r\n this.#addToken(MarkdownTokenType.Text, this.#body.substring(started, this.#index))\r\n }\r\n return;\r\n }\r\n\r\n\r\n if (started === -1) {\r\n started = this.#index;\r\n }\r\n\r\n char = this.#next();\r\n }\r\n\r\n if (started != -1) {\r\n this.#addToken(MarkdownTokenType.Text, this.#body.substring(started, this.#index))\r\n }\r\n }\r\n\r\n // S( ) => S\r\n // S(\\t) => S\r\n // S(#) => H1\r\n // H1(#) => H2\r\n // H1(!#) => S\r\n // H2(#) => H3\r\n // H2(#) => H3\r\n parse(): void {\r\n let char = this.#current();\r\n\r\n while (char !== \"\") {\r\n if (char === \" \" || char === \"\\t\") {\r\n this.#whiteSpace();\r\n } else if (char === \"#\") {\r\n this.#h1();\r\n } else if (char === \"\\n\") {\r\n this.#addToken(MarkdownTokenType.NewLine, \"\\n\");\r\n this.#inc();\r\n } else if (char === \"*\") {\r\n this.#addToken(MarkdownTokenType.Star, \"*\");\r\n this.#inc();\r\n } else if (char === \"`\") {\r\n this.#addToken(MarkdownTokenType.BackTick, \"`\");\r\n this.#inc();\r\n } else {\r\n this.#text();\r\n }\r\n\r\n char = this.#current();\r\n }\r\n }\r\n}\r\n", "import { Theme } from \"../theme\";\r\nimport { List } from \"../types/list\";\r\nimport { Text } from \"../types/text\";\r\nimport { CopyVector2, Vector2, Zero } from \"../types/vector2\";\r\n\r\nexport interface MarkdownEntry {\r\n render(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, maxWidth: number): number\r\n}\r\n\r\nexport class CodeBlockEntry {\r\n\r\n #text: Text\r\n\r\n #calculatedPositions: List<Vector2>\r\n\r\n #calculatedEntries: List<Text>\r\n\r\n #calculatedForWidth: number;\r\n\r\n constructor(text: Text) {\r\n this.#text = text;\r\n this.#calculatedForWidth = -1\r\n\r\n this.#calculatedEntries = new List<Text>();\r\n this.#calculatedPositions = new List<Vector2>();\r\n\r\n document.fonts.addEventListener(\"loadingdone\", (event) => {\r\n this.#calculatedForWidth = -1\r\n });\r\n }\r\n\r\n #calculateLayout(ctx: CanvasRenderingContext2D, maxWidth: number): void {\r\n if (this.#calculatedForWidth === maxWidth) {\r\n return;\r\n }\r\n\r\n let adjustedWith = maxWidth;\r\n adjustedWith -= Theme.Note.CodeBlock.Padding * 2;\r\n\r\n this.#calculatedEntries.Clear();\r\n this.#calculatedPositions.Clear();\r\n\r\n let curHeight = 0;\r\n const lineInc = this.#text.style().getSize() + Theme.Note.LineSpacing;\r\n\r\n let entries = this.#text.split(\"\\n\")\r\n\r\n for (let entryIndex = 0; entryIndex < entries.length; entryIndex++) {\r\n const entry = entries[entryIndex];\r\n\r\n let lines = entry.breakIntoLines(ctx, adjustedWith);\r\n for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {\r\n\r\n this.#calculatedEntries.Push(lines[lineIndex])\r\n this.#calculatedPositions.Push({\r\n x: 0,\r\n y: curHeight,\r\n })\r\n \r\n curHeight += lineInc;\r\n }\r\n }\r\n\r\n this.#calculatedForWidth = maxWidth;\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, maxWidth: number): number {\r\n this.#calculateLayout(ctx, maxWidth);\r\n\r\n let padding = Theme.Note.CodeBlock.Padding * scale;\r\n\r\n let max = 0;\r\n for (let i = 0; i < this.#calculatedEntries.Count(); i++) {\r\n const pos = this.#calculatedPositions.At(i);\r\n max = Math.max(max, pos.y * scale)\r\n }\r\n\r\n const y = position.y + max + (scale * 5)\r\n ctx.fillStyle = Theme.Note.CodeBlock.BackgroundColor;\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n position.x,\r\n position.y,\r\n maxWidth * scale,\r\n max + (padding * 2),\r\n Theme.Note.CodeBlock.BorderRadius * scale\r\n );\r\n ctx.fill();\r\n\r\n\r\n for (let i = 0; i < this.#calculatedEntries.Count(); i++) {\r\n const entry = this.#calculatedEntries.At(i);\r\n const pos = this.#calculatedPositions.At(i);\r\n\r\n entry.render(ctx, scale, {\r\n x: (pos.x * scale) + position.x + padding,\r\n y: (pos.y * scale) + position.y + padding\r\n });\r\n\r\n max = Math.max(max, pos.y * scale)\r\n }\r\n\r\n\r\n return max + (padding * 2);\r\n }\r\n}\r\n\r\nexport class UnorderedListMarkdownEntry {\r\n\r\n #entries: Array<BasicMarkdownEntry>;\r\n\r\n constructor(entries: Array<BasicMarkdownEntry>) {\r\n this.#entries = entries;\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, maxWidth: number): number {\r\n let offset = 0;\r\n let shift = 20;\r\n\r\n let pos = {\r\n x: position.x + (shift * scale),\r\n y: position.y\r\n }\r\n\r\n let dot = Theme.Note.DotSize * scale;\r\n\r\n for (let i = 0; i < this.#entries.length; i++) {\r\n\r\n ctx.beginPath();\r\n ctx.arc(position.x + dot, pos.y + (dot * 3), dot, 0, 2 * Math.PI);\r\n ctx.fill();\r\n\r\n offset += this.#entries[i].render(ctx, pos, scale, maxWidth - shift) + (scale * Theme.Note.LineSpacing * 2);\r\n pos.y = position.y + offset;\r\n }\r\n\r\n return offset;\r\n }\r\n}\r\n\r\nexport class BasicMarkdownEntry {\r\n\r\n #underline: boolean;\r\n\r\n #background: boolean;\r\n\r\n #entries: Array<Text>\r\n\r\n #calculatedPositions: List<Vector2>\r\n\r\n #calculatedEntries: List<Text>\r\n\r\n #calculatedForWidth: number;\r\n\r\n constructor(lines: Array<Text>, underline: boolean, background: boolean) {\r\n this.#entries = lines;\r\n this.#underline = underline;\r\n this.#background = background;\r\n this.#calculatedForWidth = -1\r\n\r\n this.#calculatedEntries = new List<Text>();\r\n this.#calculatedPositions = new List<Vector2>();\r\n\r\n document.fonts.addEventListener(\"loadingdone\", (event) => {\r\n this.#calculatedForWidth = -1\r\n });\r\n }\r\n\r\n #calculateLayout(ctx: CanvasRenderingContext2D, maxWidth: number): void {\r\n if (this.#calculatedForWidth === maxWidth) {\r\n return;\r\n }\r\n\r\n let adjustedWith = maxWidth;\r\n if (this.#background) {\r\n adjustedWith -= Theme.Note.CodeBlock.Padding * 2;\r\n }\r\n\r\n this.#calculatedEntries.Clear();\r\n this.#calculatedPositions.Clear();\r\n\r\n const curPosition: Vector2 = Zero();\r\n const texSize: Vector2 = Zero();\r\n\r\n let currentLineHeight = 0;\r\n const currentLineText = new List<Text>();\r\n const currentLineWidths = new List<number>();\r\n\r\n for (let entryIndex = 0; entryIndex < this.#entries.length; entryIndex++) {\r\n const entry = this.#entries[entryIndex];\r\n\r\n let lines = entry.splitAtWidth(ctx, adjustedWith - curPosition.x);\r\n let i = 0;\r\n while (lines.length > 1 && i < 100) {\r\n i++\r\n\r\n // We can't collapse this thing any further. Break out of the \r\n // while loop before we have infinite loop on our hands\r\n // if (lines[0].get() === \"\" && lines[1].get().length === 1) {\r\n // lines[0] = lines[1];\r\n // break;\r\n // }\r\n\r\n // We can't collapse this thing any further. Break out of the \r\n // while loop before we have infinite loop on our hands\r\n if (lines[0].get() === \"\" && currentLineText.Count() === 0) {\r\n\r\n if (lines[1].get().length === 1) {\r\n lines[0] = lines[1];\r\n break;\r\n } else {\r\n lines = lines[1].splitAtIndex(1);\r\n }\r\n\r\n }\r\n\r\n // This effectiviely finishes off the line we're currenly working on.\r\n if (lines[0].get() !== \"\") {\r\n lines[0].size(ctx, 1, texSize);\r\n currentLineHeight = Math.max(currentLineHeight, texSize.y);\r\n\r\n currentLineText.Push(lines[0]);\r\n currentLineWidths.Push(curPosition.x);\r\n }\r\n\r\n curPosition.y += currentLineHeight;\r\n\r\n // Take everything we're working with and finalize it\r\n for (let i = 0; i < currentLineText.Count(); i++) {\r\n this.#calculatedEntries.Push(currentLineText.At(i));\r\n this.#calculatedPositions.Push({ x: currentLineWidths.At(i), y: curPosition.y })\r\n }\r\n\r\n currentLineText.Clear();\r\n currentLineWidths.Clear();\r\n\r\n curPosition.y += Theme.Note.LineSpacing;\r\n currentLineHeight = 0;\r\n curPosition.x = 0;\r\n\r\n lines = lines[1].splitAtWidth(ctx, adjustedWith);\r\n }\r\n if (i === 100) {\r\n console.log(lines)\r\n }\r\n\r\n lines[0].size(ctx, 1, texSize);\r\n currentLineHeight = Math.max(currentLineHeight, texSize.y)\r\n\r\n currentLineText.Push(lines[0]);\r\n currentLineWidths.Push(curPosition.x);\r\n\r\n curPosition.x += texSize.x;\r\n }\r\n\r\n curPosition.y += currentLineHeight;\r\n\r\n // Take everything we're working with and finalize it\r\n for (let i = 0; i < currentLineText.Count(); i++) {\r\n this.#calculatedEntries.Push(currentLineText.At(i));\r\n this.#calculatedPositions.Push({ x: currentLineWidths.At(i), y: curPosition.y })\r\n }\r\n\r\n this.#calculatedForWidth = maxWidth;\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, position: Vector2, scale: number, maxWidth: number): number {\r\n this.#calculateLayout(ctx, maxWidth);\r\n\r\n let padding = 0;\r\n if (this.#background) {\r\n padding += Theme.Note.CodeBlock.Padding * scale;\r\n }\r\n\r\n\r\n if (this.#background) {\r\n let max = 0;\r\n for (let i = 0; i < this.#calculatedEntries.Count(); i++) {\r\n const pos = this.#calculatedPositions.At(i);\r\n max = Math.max(max, pos.y * scale)\r\n }\r\n\r\n const y = position.y + max + (scale * 5)\r\n ctx.fillStyle = Theme.Note.CodeBlock.BackgroundColor;\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n position.x,\r\n position.y,\r\n maxWidth * scale,\r\n max + (padding * 2),\r\n Theme.Note.CodeBlock.BorderRadius * scale\r\n );\r\n ctx.fill();\r\n }\r\n\r\n\r\n let max = 0;\r\n for (let i = 0; i < this.#calculatedEntries.Count(); i++) {\r\n const entry = this.#calculatedEntries.At(i);\r\n const pos = this.#calculatedPositions.At(i);\r\n\r\n entry.render(ctx, scale, {\r\n x: (pos.x * scale) + position.x + padding,\r\n y: (pos.y * scale) + position.y + padding\r\n });\r\n\r\n max = Math.max(max, pos.y * scale)\r\n }\r\n\r\n // Add underline \r\n if (this.#underline) {\r\n const y = position.y + max + (scale * 5)\r\n ctx.strokeStyle = Theme.Note.FontColor;\r\n ctx.lineWidth = Theme.Note.HeaderLineWidth * scale;\r\n ctx.beginPath();\r\n ctx.moveTo(position.x, y);\r\n ctx.lineTo(position.x + (maxWidth * scale), y);\r\n ctx.stroke();\r\n }\r\n\r\n return max + (padding * 2);\r\n }\r\n}\r\n", "import { FontStyle, FontWeight, TextStyleConfig } from \"../styles/text\";\r\nimport { Theme } from \"../theme\";\r\nimport { Text } from \"../types/text\";\r\nimport { BasicMarkdownEntry, CodeBlockEntry, MarkdownEntry, UnorderedListMarkdownEntry } from \"./entry\";\r\nimport { MarkdownToken, MarkdownTokenType } from \"./token\";\r\n\r\nexport class MarkdownSyntaxParser {\r\n\r\n #tokens: Array<MarkdownToken>;\r\n\r\n #index: number;\r\n\r\n #originalText: string;\r\n\r\n constructor(originalText: string, tokens: Array<MarkdownToken>) {\r\n this.#originalText = originalText;\r\n this.#index = 0;\r\n this.#tokens = tokens;\r\n }\r\n\r\n #current(): MarkdownToken | null {\r\n if (this.#index > this.#tokens.length - 1) {\r\n return null\r\n }\r\n return this.#tokens[this.#index];\r\n }\r\n\r\n #inc(): void {\r\n this.#index++\r\n }\r\n\r\n #next(): MarkdownToken | null {\r\n this.#index++\r\n if (this.#index >= this.#tokens.length - 1) {\r\n return null\r\n }\r\n return this.#tokens[this.#index];\r\n }\r\n\r\n #peak(): MarkdownToken | null {\r\n if (this.#index + 1 >= this.#tokens.length - 1) {\r\n return null\r\n }\r\n return this.#tokens[this.#index + 1];\r\n }\r\n\r\n #peakInto(amount: number): MarkdownToken | null {\r\n if (this.#index + amount >= this.#tokens.length - 1) {\r\n return null\r\n }\r\n return this.#tokens[this.#index + amount];\r\n }\r\n\r\n #emphasis(): Array<Text> {\r\n\r\n // Cases to consider\r\n // =================\r\n // 1. *a*: <i>a</i>\r\n // 2. **a**: <b>a</b>\r\n // 3. **a*: *<i>a</i> <----- fuck this one\r\n // 4. ***a**: *<b>a</b> <----- fuck this one\r\n // 5. *a**: <i>a</i>*\r\n // 6. **a***: <b>a</b>*\r\n // 7. * a *: * a *\r\n // 8. ** a **: ** a **\r\n // 9. **a **: **a **\r\n // 10. **a f**: <b>a f<b>\r\n // 11. * Test: <ul>Test</ul> \r\n\r\n let token = this.#next();\r\n if (token?.type() === MarkdownTokenType.Space) {\r\n return [new Text(\"*\")];\r\n }\r\n\r\n let bold = false;\r\n // Read off all leading stars\r\n while (token !== null && token.type() === MarkdownTokenType.Star) {\r\n bold = true;\r\n token = this.#next();\r\n }\r\n\r\n let textContent = \"\";\r\n\r\n let boldClosed = false;\r\n let startingClose = false;\r\n let validClose = false;\r\n while (token !== null && token.type() !== MarkdownTokenType.NewLine) {\r\n if (token.type() === MarkdownTokenType.Star) {\r\n\r\n // This is the second star we've seen in a row. We're done!\r\n if (startingClose) {\r\n boldClosed = true;\r\n break;\r\n }\r\n\r\n // If we're not bold, we just need a single star to close this off.\r\n startingClose = true;\r\n if (bold === false) {\r\n break;\r\n }\r\n }\r\n\r\n if (startingClose && token.type() !== MarkdownTokenType.Star) {\r\n break;\r\n }\r\n\r\n // Add to string content...\r\n if (token.type() === MarkdownTokenType.Text) {\r\n textContent += token.lexeme();\r\n validClose = true;\r\n }\r\n\r\n if (token.type() === MarkdownTokenType.Space) {\r\n textContent += token.lexeme();\r\n validClose = false;\r\n }\r\n\r\n token = this.#next();\r\n }\r\n\r\n const style: TextStyleConfig = {}\r\n\r\n if (validClose && startingClose) {\r\n if (boldClosed) {\r\n style.weight = FontWeight.Bold;\r\n } else {\r\n style.style = FontStyle.Italic;\r\n }\r\n }\r\n\r\n return [new Text(textContent, style)]\r\n }\r\n\r\n #text(): Array<Text> {\r\n let contents: Array<Text> = new Array<Text>();\r\n let textContent = \"\";\r\n\r\n let token = this.#current();\r\n\r\n // Read off all starting whitespace \r\n while (token !== null && token.type() === MarkdownTokenType.Space) {\r\n token = this.#next();\r\n }\r\n\r\n while (token !== null && token.type() !== MarkdownTokenType.NewLine) {\r\n switch (token.type()) {\r\n case MarkdownTokenType.Text:\r\n case MarkdownTokenType.H1:\r\n case MarkdownTokenType.H2:\r\n case MarkdownTokenType.H3:\r\n case MarkdownTokenType.Space:\r\n textContent += token.lexeme();\r\n break;\r\n\r\n case MarkdownTokenType.Star:\r\n if (textContent !== \"\") {\r\n contents.push(new Text(textContent))\r\n textContent = \"\";\r\n }\r\n let starText = this.#emphasis()\r\n for (let i = 0; i < starText.length; i++) {\r\n contents.push(starText[i]);\r\n }\r\n break;\r\n }\r\n\r\n token = this.#next();\r\n }\r\n\r\n if (textContent !== \"\") {\r\n contents.push(new Text(textContent))\r\n }\r\n\r\n return contents;\r\n }\r\n\r\n #h1(): BasicMarkdownEntry {\r\n // Move off of the header token\r\n this.#inc();\r\n\r\n const text = this.#text();\r\n for (let i = 0; i < text.length; i++) {\r\n text[i].setColor(Theme.Note.FontColor);\r\n text[i].setSize(Theme.Note.H1.FontSize);\r\n text[i].setWeight(FontWeight.Bold);\r\n }\r\n\r\n return new BasicMarkdownEntry(text, true, false);\r\n }\r\n\r\n #h2(): BasicMarkdownEntry {\r\n // Move off of the header token\r\n this.#inc();\r\n\r\n const text = this.#text();\r\n for (let i = 0; i < text.length; i++) {\r\n text[i].setColor(Theme.Note.FontColor);\r\n text[i].setSize(Theme.Note.H2.FontSize);\r\n text[i].setWeight(FontWeight.Bold);\r\n }\r\n\r\n return new BasicMarkdownEntry(text, true, false);\r\n }\r\n\r\n #h3(): BasicMarkdownEntry {\r\n // Move off of the header token\r\n this.#inc();\r\n\r\n const text = this.#text();\r\n for (let i = 0; i < text.length; i++) {\r\n text[i].setColor(Theme.Note.FontColor);\r\n text[i].setSize(Theme.Note.H3.FontSize);\r\n text[i].setWeight(FontWeight.Bold);\r\n }\r\n\r\n return new BasicMarkdownEntry(text, false, false);\r\n }\r\n\r\n #starLineStart(): MarkdownEntry {\r\n if (this.#peak()?.type() !== MarkdownTokenType.Space) {\r\n const starEntries = this.#text();\r\n this.#assignStandardStyling(starEntries);\r\n return new BasicMarkdownEntry(starEntries, false, false);\r\n }\r\n\r\n // We've begun with a space, which means unordered list!\r\n\r\n const entries = new Array<BasicMarkdownEntry>();\r\n\r\n while (this.#current()?.type() === MarkdownTokenType.Star && this.#peak()?.type() === MarkdownTokenType.Space) {\r\n this.#inc();\r\n const starEntries = this.#text();\r\n this.#assignStandardStyling(starEntries);\r\n entries.push(new BasicMarkdownEntry(starEntries, false, false));\r\n\r\n // Text reads to the end of the line, which means we're at the new\r\n // line character. Move forward 1. \r\n this.#inc();\r\n }\r\n\r\n return new UnorderedListMarkdownEntry(entries);\r\n\r\n }\r\n\r\n #assignStandardStyling(textEntries: Array<Text>): void {\r\n for (let i = 0; i < textEntries.length; i++) {\r\n textEntries[i].setColor(Theme.Note.FontColor);\r\n textEntries[i].setSize(Theme.Note.FontSize);\r\n }\r\n }\r\n\r\n #backtickLineStart(): MarkdownEntry {\r\n\r\n // If we're not a ```, just treat as regular text\r\n if (this.#peak()?.type() !== MarkdownTokenType.BackTick || this.#peakInto(2)?.type() !== MarkdownTokenType.BackTick) {\r\n const starEntries = this.#text();\r\n this.#assignStandardStyling(starEntries);\r\n return new BasicMarkdownEntry(starEntries, false, false);\r\n }\r\n this.#inc();\r\n this.#inc();\r\n\r\n let token = this.#next();\r\n\r\n // Eat the first new line character\r\n if (token?.type() === MarkdownTokenType.NewLine) {\r\n token = this.#next();\r\n }\r\n\r\n let start = token?.tokenStart();\r\n let end = start;\r\n\r\n // Read until we hit another ``` \r\n while (token !== null) {\r\n\r\n if (\r\n token.type() === MarkdownTokenType.BackTick &&\r\n this.#peak()?.type() === MarkdownTokenType.BackTick &&\r\n this.#peakInto(2)?.type() === MarkdownTokenType.BackTick\r\n ) {\r\n end = token.tokenEnd() - 1;\r\n break;\r\n }\r\n\r\n token = this.#next();\r\n }\r\n\r\n this.#inc(); // puts us on the 2nd\r\n this.#inc(); // puts us on the 3rd\r\n this.#inc(); // puts us on the next token\r\n\r\n const codeBlockText = this.#originalText.substring(start as number, end);\r\n const entryText = new Text(codeBlockText);\r\n this.#assignStandardStyling([entryText])\r\n return new CodeBlockEntry(entryText)\r\n }\r\n\r\n parse(): Array<MarkdownEntry> {\r\n let token = this.#current();\r\n\r\n const entries = new Array<MarkdownEntry>();\r\n\r\n while (token !== null) {\r\n switch (token.type()) {\r\n case MarkdownTokenType.H1:\r\n entries.push(this.#h1());\r\n break;\r\n\r\n case MarkdownTokenType.H2:\r\n entries.push(this.#h2());\r\n break;\r\n\r\n case MarkdownTokenType.H3:\r\n entries.push(this.#h3());\r\n break;\r\n\r\n case MarkdownTokenType.Text:\r\n const textEntries = this.#text();\r\n this.#assignStandardStyling(textEntries);\r\n entries.push(new BasicMarkdownEntry(textEntries, false, false));\r\n break;\r\n\r\n case MarkdownTokenType.Star:\r\n entries.push(this.#starLineStart());\r\n break;\r\n\r\n case MarkdownTokenType.NewLine:\r\n this.#inc();\r\n break;\r\n\r\n case MarkdownTokenType.BackTick:\r\n entries.push(this.#backtickLineStart());\r\n break;\r\n\r\n default:\r\n this.#inc();\r\n }\r\n\r\n token = this.#current();\r\n }\r\n\r\n return entries;\r\n }\r\n}\r\n", "import { MarkdownEntry } from \"./entry\";\r\nimport { MarkdownLexicalParser } from \"./lexicalParser\";\r\nimport { MarkdownSyntaxParser } from \"./syntaxParser\";\r\n\r\nexport function BuildMarkdown(data: string): Array<MarkdownEntry> {\r\n const lexicalParser = new MarkdownLexicalParser(data);\r\n lexicalParser.parse();\r\n // console.log(lexicalParser.tokens());\r\n\r\n const syntaxParser = new MarkdownSyntaxParser(data, lexicalParser.tokens());\r\n const contents = syntaxParser.parse()\r\n // console.log(contents);\r\n return contents;\r\n}", "import { BuildMarkdown } from \"../markdown/markdown\";\r\nimport { MarkdownEntry } from \"../markdown/entry\";\r\nimport { Popup } from \"../popup\";\r\nimport { BoxStyle } from \"../styles/box\";\r\nimport { TextAlign } from \"../styles/canvasTextAlign\";\r\nimport { TextBaseline } from \"../styles/canvasTextBaseline\";\r\nimport { TextStyleConfig } from \"../styles/text\";\r\nimport { Theme } from \"../theme\";\r\nimport { Box } from \"../types/box\";\r\nimport { CopyVector2, Vector2, Zero } from \"../types/vector2\";\r\nimport { Camera } from \"../camera\";\r\nimport { Metadata } from \"../metadata\";\r\n\r\nexport type NoteContentChangeCallback = (node: FlowNote, newContents: string) => void\r\nexport type NoteWidthChangeCallback = (node: FlowNote, newWidth: number) => void\r\n\r\nexport interface FlowNoteConfig {\r\n text?: string;\r\n style?: TextStyleConfig;\r\n metadata?: Metadata;\r\n position?: Vector2;\r\n width?: number;\r\n locked?: boolean;\r\n onWidthChange?: NoteWidthChangeCallback;\r\n onContentChange?: NoteContentChangeCallback;\r\n}\r\n\r\nexport enum DragHandle {\r\n None,\r\n Left,\r\n Right\r\n};\r\n\r\nconst BOUNDS_SPACING = 20;\r\nconst BOX_SIZE = 10;\r\n\r\nexport class FlowNote {\r\n\r\n #originalText: string;\r\n\r\n #document: Array<MarkdownEntry>;\r\n\r\n #width: number;\r\n\r\n #edittingStyle: BoxStyle;\r\n\r\n // Runtime ================================================================\r\n\r\n #data: Metadata;\r\n\r\n #position: Vector2;\r\n\r\n #handleSelected: DragHandle;\r\n\r\n #edittingLayout: boolean;\r\n\r\n #lastRenderedBox: Box;\r\n\r\n #hovering: boolean;\r\n\r\n // Callbacks ==============================================================\r\n\r\n #widthChangeCallbacks: Array<NoteWidthChangeCallback>;\r\n\r\n #contentChangeCallbacks: Array<NoteContentChangeCallback>;\r\n\r\n // ========================================================================\r\n\r\n constructor(config?: FlowNoteConfig) {\r\n this.#widthChangeCallbacks = new Array<NoteWidthChangeCallback>();\r\n this.#contentChangeCallbacks = new Array<NoteContentChangeCallback>();\r\n this.#data = config?.metadata === undefined ? {} : config?.metadata;\r\n this.#document = [];\r\n this.#originalText = \"\";\r\n this.#hovering = false;\r\n this.#edittingLayout = config?.locked === undefined ? true : !config?.locked;\r\n this.#width = config?.width === undefined ? 500 : config.width;\r\n this.#position = config?.position === undefined ? { x: 0, y: 0 } : config.position;\r\n this.setText(config?.text === undefined ? \"\" : config?.text);\r\n this.#lastRenderedBox = { Position: { x: 0, y: 0 }, Size: { x: 0, y: 0 } };\r\n this.#handleSelected = DragHandle.None;\r\n\r\n this.#edittingStyle = new BoxStyle({\r\n border: {\r\n color: \"white\",\r\n size: 1\r\n },\r\n })\r\n\r\n if (config?.onWidthChange) {\r\n this.#widthChangeCallbacks.push(config.onWidthChange);\r\n }\r\n\r\n if (config?.onContentChange) {\r\n this.#contentChangeCallbacks.push(config.onContentChange);\r\n }\r\n }\r\n\r\n setText(text: string): void {\r\n this.#originalText = text;\r\n this.#document = BuildMarkdown(this.#originalText);\r\n for (let i = 0; i < this.#contentChangeCallbacks.length; i++) {\r\n this.#contentChangeCallbacks[i](this, text);\r\n }\r\n }\r\n\r\n public setMetadataProperty(name: string, value: any): void {\r\n this.#data[name] = value;\r\n }\r\n\r\n public getMetadataProperty(name: string): any {\r\n return this.#data[name];\r\n }\r\n\r\n text(): string {\r\n return this.#originalText;\r\n }\r\n\r\n width(): number {\r\n return this.#width;\r\n }\r\n\r\n position(): Vector2 {\r\n return this.#position;\r\n }\r\n\r\n translate(delta: Vector2): void {\r\n this.#position.x += delta.x;\r\n this.#position.y += delta.y;\r\n }\r\n\r\n setPosition(position: Vector2): void {\r\n CopyVector2(this.#position, position);\r\n }\r\n\r\n handleSelected(): DragHandle {\r\n return this.#handleSelected;\r\n }\r\n\r\n selectHandle(handle: DragHandle): void {\r\n this.#handleSelected = handle;\r\n }\r\n\r\n #tempPosition: Vector2 = Zero();\r\n\r\n public setWidth(newWidth: number): void {\r\n if (newWidth === undefined) {\r\n console.error(\"Attempted to set note's width to undefined\");\r\n }\r\n this.#width = newWidth;\r\n for (let i = 0; i < this.#widthChangeCallbacks.length; i++) {\r\n this.#widthChangeCallbacks[i](this, newWidth);\r\n }\r\n }\r\n\r\n public addWidthChangeListener(callback: NoteWidthChangeCallback): void {\r\n if (callback === null || callback === undefined) {\r\n return;\r\n }\r\n this.#widthChangeCallbacks.push(callback);\r\n }\r\n\r\n public addContentChangeListener(callback: NoteContentChangeCallback): void {\r\n if (callback === null || callback === undefined) {\r\n return;\r\n }\r\n this.#contentChangeCallbacks.push(callback);\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, camera: Camera, mousePosition: Vector2 | undefined): void {\r\n if (this.#edittingLayout && (this.#hovering || this.#handleSelected !== DragHandle.None)) {\r\n\r\n if (mousePosition) {\r\n if (this.#handleSelected === DragHandle.Right) {\r\n\r\n const leftPosition = (this.#position.x * camera.zoom) + camera.position.x;\r\n this.setWidth(Math.max((mousePosition.x - leftPosition) / camera.zoom, 1));\r\n\r\n } else if (this.#handleSelected === DragHandle.Left) {\r\n\r\n const scaledWidth = this.#width * camera.zoom;\r\n const rightPosition = (this.#position.x * camera.zoom) + camera.position.x + scaledWidth;\r\n this.setWidth(Math.max((rightPosition - mousePosition.x) / camera.zoom, 1));\r\n this.#position.x = rightPosition - (this.#width * camera.zoom) - camera.position.x;\r\n this.#position.x /= camera.zoom;\r\n }\r\n }\r\n\r\n this.#edittingStyle.Outline(ctx, this.leftResizeHandleBox(), camera.zoom, 2);\r\n this.#edittingStyle.Outline(ctx, this.rightResizeHandleBox(), camera.zoom, 2);\r\n\r\n ctx.beginPath();\r\n const left = this.#lastRenderedBox.Position.x;\r\n const right = this.#lastRenderedBox.Position.x + this.#lastRenderedBox.Size.x;\r\n const bottom = this.#lastRenderedBox.Position.y;\r\n const top = this.#lastRenderedBox.Position.y + this.#lastRenderedBox.Size.y;\r\n ctx.moveTo(left, bottom + (this.#lastRenderedBox.Size.y / 2) - (BOX_SIZE));\r\n ctx.lineTo(left, bottom);\r\n ctx.lineTo(right, bottom);\r\n ctx.lineTo(right, bottom + (this.#lastRenderedBox.Size.y / 2) - (BOX_SIZE));\r\n\r\n ctx.moveTo(left, top - (this.#lastRenderedBox.Size.y / 2) + (BOX_SIZE));\r\n ctx.lineTo(left, top);\r\n ctx.lineTo(right, top);\r\n ctx.lineTo(right, top - (this.#lastRenderedBox.Size.y / 2) + (BOX_SIZE));\r\n ctx.stroke();\r\n // this.#edittingStyle.Outline(ctx, bigBox, camera.zoom, 2);\r\n }\r\n\r\n camera.graphSpaceToScreenSpace(this.#position, this.#tempPosition);\r\n CopyVector2(this.#lastRenderedBox.Position, this.#tempPosition)\r\n\r\n const startY = this.#tempPosition.y;\r\n const lineSpacing = Theme.Note.EntrySpacing * camera.zoom;\r\n\r\n ctx.textAlign = TextAlign.Left;\r\n ctx.textBaseline = TextBaseline.Alphabetic;\r\n for (let i = 0; i < this.#document.length; i++) {\r\n const text = this.#document[i];\r\n this.#tempPosition.y += text.render(ctx, this.#tempPosition, camera.zoom, this.#width) + lineSpacing;\r\n }\r\n\r\n this.#lastRenderedBox.Position.x -= BOUNDS_SPACING\r\n this.#lastRenderedBox.Position.y -= BOUNDS_SPACING\r\n this.#lastRenderedBox.Size.x = camera.zoom * this.#width + (BOUNDS_SPACING * 2);\r\n this.#lastRenderedBox.Size.y = this.#tempPosition.y - startY + (BOUNDS_SPACING * 2);\r\n }\r\n\r\n leftResizeHandleBox(): Box {\r\n return {\r\n Position: {\r\n x: this.#lastRenderedBox.Position.x - (BOX_SIZE / 2),\r\n y: this.#lastRenderedBox.Position.y + (this.#lastRenderedBox.Size.y / 2) - (BOX_SIZE / 2),\r\n },\r\n Size: { x: BOX_SIZE, y: BOX_SIZE, }\r\n };\r\n }\r\n\r\n rightResizeHandleBox(): Box {\r\n return {\r\n Position: {\r\n x: this.#lastRenderedBox.Position.x - (BOX_SIZE / 2) + this.#lastRenderedBox.Size.x,\r\n y: this.#lastRenderedBox.Position.y + (this.#lastRenderedBox.Size.y / 2) - (BOX_SIZE / 2),\r\n },\r\n Size: { x: BOX_SIZE, y: BOX_SIZE, }\r\n };\r\n }\r\n\r\n edittingLayout(): boolean {\r\n return this.#edittingLayout;\r\n }\r\n\r\n setHovering(hovering: boolean): void {\r\n this.#hovering = hovering;\r\n }\r\n\r\n editContent(): void {\r\n let input: HTMLTextAreaElement | null = null;\r\n let saveText = \"Save\";\r\n\r\n const popup = new Popup({\r\n title: \"Edit Note\",\r\n options: [saveText, \"Cancel\"],\r\n content: () => {\r\n const container = document.createElement('div');\r\n input = document.createElement('textarea')\r\n input.rows = 8;\r\n input.cols = 50;\r\n input.value = this.#originalText;\r\n container.append(input);\r\n return container;\r\n },\r\n onClose: (button: string | null): void => {\r\n if (button !== saveText || input === null) {\r\n return;\r\n }\r\n this.setText(input.value);\r\n },\r\n });\r\n\r\n popup.Show();\r\n }\r\n\r\n lock(): void {\r\n this.#edittingLayout = false;\r\n }\r\n\r\n unlock(): void {\r\n this.#edittingLayout = true;\r\n }\r\n\r\n bounds(): Box {\r\n return this.#lastRenderedBox;\r\n }\r\n}", "import { Camera } from \"../camera\";\r\nimport { ContextMenuConfig } from \"../contextMenu\";\r\nimport { RenderResults } from \"../graphSubsystem\";\r\nimport { InBox } from \"../types/box\";\r\nimport { Vector2 } from \"../types/vector2\";\r\nimport { DragHandle, FlowNote, FlowNoteConfig } from './note';\r\n\r\n\r\nexport type NoteAddedCallback = (addedNote: FlowNote) => void\r\nexport type NoteRemovedCallback = (noteRemoved: FlowNote) => void\r\n\r\nexport type NoteDragStartCallback = (nodeDragged: FlowNote) => void\r\nexport type NoteDragStopCallback = (nodeDragged: FlowNote) => void\r\n\r\n\r\nexport interface NoteSubsystemConfig {\r\n onNoteAdded?: NoteAddedCallback;\r\n onNoteRemoved?: NoteRemovedCallback;\r\n onNoteDragStop?: NoteDragStopCallback\r\n onNoteDragStart?: NoteDragStartCallback\r\n notes?: Array<FlowNoteConfig>\r\n}\r\n\r\nexport class NoteSubsystem {\r\n\r\n #notes: Array<FlowNote>;\r\n\r\n #noteHovering: FlowNote | null;\r\n\r\n #noteSelected: FlowNote | null;\r\n\r\n #hoveringHandle: DragHandle;\r\n\r\n #onNoteAddedCallbacks: Array<NoteAddedCallback>;\r\n\r\n #onNoteRemovedCallbacks: Array<NoteRemovedCallback>;\r\n\r\n #onNoteDragStartCallbacks: Array<NoteDragStartCallback>;\r\n\r\n #onNoteDragStopCallbacks: Array<NoteDragStopCallback>;\r\n\r\n constructor(config?: NoteSubsystemConfig) {\r\n this.#hoveringHandle = DragHandle.None;\r\n this.#notes = [];\r\n this.#noteHovering = null;\r\n this.#noteSelected = null;\r\n\r\n // Callbacks\r\n this.#onNoteAddedCallbacks = new Array<NoteAddedCallback>();\r\n this.#onNoteRemovedCallbacks = new Array<NoteRemovedCallback>();\r\n this.#onNoteDragStartCallbacks = new Array<NoteDragStartCallback>();\r\n this.#onNoteDragStopCallbacks = new Array<NoteDragStopCallback>();\r\n\r\n if (config?.notes !== undefined) {\r\n for (let i = 0; i < config?.notes.length; i++) {\r\n this.addNote(new FlowNote(config?.notes[i]));\r\n }\r\n }\r\n\r\n // Add callback *after* we added all the initial notes\r\n if (config?.onNoteAdded !== undefined) {\r\n this.#onNoteAddedCallbacks.push(config?.onNoteAdded);\r\n }\r\n\r\n if (config?.onNoteDragStop !== undefined) {\r\n this.#onNoteDragStopCallbacks.push(config?.onNoteDragStop);\r\n }\r\n\r\n if (config?.onNoteDragStart !== undefined) {\r\n this.#onNoteDragStartCallbacks.push(config?.onNoteDragStart);\r\n }\r\n\r\n if (config?.onNoteRemoved !== undefined) {\r\n this.#onNoteRemovedCallbacks.push(config?.onNoteRemoved);\r\n }\r\n }\r\n\r\n addNote(note: FlowNote): void {\r\n if (note === null || note === undefined) {\r\n return;\r\n }\r\n\r\n this.#notes.push(note);\r\n for (let i = 0; i < this.#onNoteAddedCallbacks.length; i++) {\r\n this.#onNoteAddedCallbacks[i](note);\r\n }\r\n }\r\n\r\n getNotes(): Array<FlowNote> {\r\n return this.#notes;\r\n }\r\n\r\n public addNoteAddedListener(callback: NoteAddedCallback): void {\r\n if (callback === null || callback === undefined) {\r\n return;\r\n }\r\n this.#onNoteAddedCallbacks.push(callback);\r\n }\r\n\r\n public addNoteRemovedListener(callback: NoteRemovedCallback): void {\r\n if (callback === null || callback === undefined) {\r\n return;\r\n }\r\n this.#onNoteRemovedCallbacks.push(callback);\r\n }\r\n\r\n public addNoteDragStartListener(callback: NoteDragStartCallback): void {\r\n if (callback === null || callback === undefined) {\r\n return;\r\n }\r\n this.#onNoteDragStartCallbacks.push(callback);\r\n }\r\n\r\n public addNoteDragStopListener(callback: NoteDragStopCallback): void {\r\n if (callback === null || callback === undefined) {\r\n return;\r\n }\r\n this.#onNoteDragStopCallbacks.push(callback);\r\n }\r\n\r\n openContextMenu(ctx: CanvasRenderingContext2D, position: Vector2): ContextMenuConfig | null {\r\n const group = \"node-flow-graph-note-menu\";\r\n\r\n const result: ContextMenuConfig = {\r\n items: [\r\n {\r\n name: \"New Note\",\r\n group: group,\r\n callback: () => {\r\n this.addNote(new FlowNote({\r\n text: \"#Note\\n\\nRight-click this note and select \\\"edit note\\\" to put what you want here.\",\r\n width: 300,\r\n position: position\r\n }))\r\n }\r\n }\r\n ],\r\n subMenus: [],\r\n }\r\n\r\n if (this.#noteHovering !== null) {\r\n const noteToReview = this.#noteHovering;\r\n result.items?.push(\r\n {\r\n name: \"Delete Note\",\r\n group: group,\r\n callback: () => {\r\n this.removeNote(noteToReview);\r\n }\r\n },\r\n {\r\n name: \"Edit Note\",\r\n group: group,\r\n callback: noteToReview.editContent.bind(noteToReview),\r\n },\r\n );\r\n\r\n if (!noteToReview.edittingLayout()) {\r\n result.items?.push({\r\n name: \"Unlock Note\",\r\n group: group,\r\n callback: noteToReview.unlock.bind(noteToReview),\r\n })\r\n } else {\r\n result.items?.push({\r\n name: \"Lock Note\",\r\n group: group,\r\n callback: noteToReview.lock.bind(noteToReview),\r\n })\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n clickStart(mousePosition: Vector2, camera: Camera, ctrlKey: boolean): boolean {\r\n if (this.#noteHovering !== null && this.#noteHovering.edittingLayout()) {\r\n this.#noteSelected = this.#noteHovering;\r\n this.#noteSelected.selectHandle(this.#hoveringHandle);\r\n\r\n for (let i = 0; i < this.#onNoteDragStartCallbacks.length; i++) {\r\n this.#onNoteDragStartCallbacks[i](this.#noteSelected);\r\n }\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n clickEnd(): void {\r\n if (this.#noteSelected !== null) {\r\n this.#noteSelected.selectHandle(DragHandle.None);\r\n for (let i = 0; i < this.#onNoteDragStopCallbacks.length; i++) {\r\n this.#onNoteDragStopCallbacks[i](this.#noteSelected);\r\n }\r\n }\r\n this.#noteSelected = null;\r\n }\r\n\r\n mouseDragEvent(delta: Vector2, scale: number): boolean {\r\n if (this.#noteSelected === null) {\r\n return false;\r\n }\r\n\r\n // Return early so we don't translate since we're moving a drag handle\r\n if (this.#noteSelected.handleSelected()) {\r\n return true;\r\n }\r\n\r\n this.#noteSelected.translate({\r\n x: delta.x * (1 / scale),\r\n y: delta.y * (1 / scale)\r\n });\r\n return true;\r\n }\r\n\r\n fileDrop(file: File): boolean {\r\n return false;\r\n }\r\n\r\n removeNote(note: FlowNote): void {\r\n const index = this.#notes.indexOf(note);\r\n if (index > -1) {\r\n const noteRemoved = this.#notes[index];\r\n this.#notes.splice(index, 1);\r\n\r\n for (let i = 0; i < this.#onNoteRemovedCallbacks.length; i++) {\r\n this.#onNoteRemovedCallbacks[i](noteRemoved)\r\n }\r\n } else {\r\n console.error(\"no note found to remove\");\r\n }\r\n }\r\n\r\n removeAllNotes(): void {\r\n const notes = this.#notes;\r\n this.#notes = [];\r\n this.#noteHovering = null;\r\n this.#noteSelected = null;\r\n\r\n for (let i = 0; i < notes.length; i++) {\r\n for (let j = 0; j < this.#onNoteRemovedCallbacks.length; j++) {\r\n this.#onNoteRemovedCallbacks[j](notes[i]);\r\n }\r\n }\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, camera: Camera, mousePosition: Vector2 | undefined): RenderResults | undefined {\r\n this.#noteHovering = null;\r\n this.#hoveringHandle = DragHandle.None;\r\n\r\n // Set hovering to false on everything\r\n if (mousePosition) {\r\n for (let i = 0; i < this.#notes.length; i++) {\r\n this.#notes[i].setHovering(false);\r\n if (InBox(this.#notes[i].bounds(), mousePosition)) {\r\n this.#noteHovering = this.#notes[i];\r\n }\r\n }\r\n }\r\n\r\n // The note on top of everything is the one that get's to be in a \r\n // hover state\r\n if (this.#noteHovering != null) {\r\n this.#noteHovering.setHovering(true);\r\n if (mousePosition) {\r\n if (InBox(this.#noteHovering.leftResizeHandleBox(), mousePosition)) {\r\n this.#hoveringHandle = DragHandle.Left;\r\n } else if (InBox(this.#noteHovering.rightResizeHandleBox(), mousePosition)) {\r\n this.#hoveringHandle = DragHandle.Right;\r\n }\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.#notes.length; i++) {\r\n this.#notes[i].render(ctx, camera, mousePosition);\r\n }\r\n return;\r\n }\r\n}", "import { Camera } from \"../camera\";\r\nimport { ContextMenuConfig } from \"../contextMenu\";\r\nimport { RenderResults } from \"../graphSubsystem\";\r\nimport { List } from \"../types/list\";\r\nimport { Vector2 } from \"../types/vector2\";\r\n\r\ntype RenderLambda = () => void\r\n\r\n\r\n/**\r\n * Generic subsystem meant for other sybsystems to pass whatever to to render \r\n * at a certain time.\r\n * \r\n * Initial inspriation is for a subsytem to submit something to render on top \r\n * of all other subsystems.\r\n */\r\nexport class PassSubsystem {\r\n\r\n #queue: List<RenderLambda>\r\n\r\n constructor() {\r\n this.#queue = new List<RenderLambda>();\r\n }\r\n\r\n queue(lambda: RenderLambda): void {\r\n if(!lambda) {\r\n return;\r\n }\r\n this.#queue.Push(lambda);\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, camera: Camera, mousePosition: Vector2 | undefined): RenderResults | undefined {\r\n for (let i = 0; i < this.#queue.Count(); i++) {\r\n this.#queue.At(i)();\r\n }\r\n this.#queue.Clear();\r\n return;\r\n }\r\n\r\n openContextMenu(ctx: CanvasRenderingContext2D, position: Vector2): ContextMenuConfig | null {\r\n // Left intentionally blank\r\n return null;\r\n }\r\n\r\n clickStart(mousePosition: Vector2, camera: Camera, ctrlKey: boolean): boolean {\r\n // Left intentionally blank\r\n return false;\r\n }\r\n\r\n mouseDragEvent(delta: Vector2, scale: number): boolean {\r\n // Left intentionally blank\r\n return false;\r\n }\r\n\r\n fileDrop(file: File): boolean {\r\n // Left intentionally blank\r\n return false;\r\n }\r\n\r\n clickEnd(): void {\r\n // Left intentionally blank\r\n }\r\n\r\n}", "import { ContextMenuConfig, ContextMenuItemConfig } from \"./contextMenu\";\r\nimport { ContainerRenderElement as ContainerElement } from \"./elements/container\";\r\nimport { IRenderElement } from \"./elements/interfaces\";\r\nimport { TextAlign, TextElement as TextElement, VerticalAlign } from \"./elements/text\";\r\nimport { FontWeight } from \"./styles/text\";\r\nimport { Theme } from \"./theme\";\r\nimport { Text } from './types/text';\r\nimport { ScaleVector, Vector2 } from './types/vector2';\r\nimport { Display } from './elements/base';\r\n\r\nclass QuickMenuGroup {\r\n\r\n #text: TextElement;\r\n\r\n public items: Array<QuickMenuItem>;\r\n\r\n constructor(text: TextElement, items: Array<QuickMenuItem>) {\r\n this.#text = text;\r\n this.items = items;\r\n }\r\n\r\n updateRendering(terms: Array<string>): void {\r\n let shouldRender = false;\r\n for (let i = 0; i < this.items.length; i++) {\r\n const kept = this.items[i].filter(terms);\r\n this.items[i].render(kept);\r\n if (kept) {\r\n shouldRender = true;\r\n }\r\n }\r\n\r\n this.#text.setDisplay(shouldRender ? Display.Flex : Display.None);\r\n }\r\n\r\n}\r\n\r\nclass QuickMenuItem {\r\n #searchText: string;\r\n #text: TextElement;\r\n #context: ContextMenuItemConfig\r\n\r\n constructor(searchText: string, text: TextElement, context: ContextMenuItemConfig) {\r\n this.#searchText = searchText.toLowerCase();\r\n this.#text = text;\r\n this.#context = context;\r\n }\r\n\r\n filter(terms: Array<string>): boolean {\r\n if (terms.length === 0) {\r\n return true;\r\n }\r\n for (let i = 0; i < terms.length; i++) {\r\n if (terms[i] === \"\") {\r\n continue;\r\n }\r\n\r\n if (this.#searchText.indexOf(terms[i]) === -1) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n render(render: boolean): void {\r\n this.#text.setDisplay(render ? Display.Flex : Display.None);\r\n }\r\n\r\n rendering(): boolean {\r\n return this.#text.getDisplay() === Display.Flex;\r\n }\r\n\r\n highlight(highlight: boolean): void {\r\n this.#text.setBackgroundColor(highlight ? Theme.ContextMenu.HighlightColor : \"\");\r\n }\r\n\r\n select(): void {\r\n if (this.#context.callback) {\r\n this.#context.callback()\r\n }\r\n }\r\n}\r\n\r\nfunction RecurseBuildContainers(\r\n path: string,\r\n config: ContextMenuConfig,\r\n renderElements: Array<IRenderElement>,\r\n groups: Array<QuickMenuGroup>\r\n): void {\r\n\r\n let currentPath = config?.name ?? \"\";\r\n if (path !== \"\") {\r\n currentPath = path + \" / \" + currentPath;\r\n }\r\n\r\n if (config?.items && config.items.length > 0) {\r\n const titleText = new TextElement(\r\n new Text(\r\n currentPath,\r\n {\r\n color: Theme.ContextMenu.FontColor,\r\n weight: FontWeight.Bold,\r\n size: 12,\r\n }\r\n ),\r\n {\r\n Align: TextAlign.Center,\r\n VerticalAlign: VerticalAlign.Center,\r\n Padding: 16\r\n }\r\n );\r\n renderElements.push(titleText);\r\n\r\n const quickItems = new Array<QuickMenuItem>();\r\n\r\n for (let i = 0; i < config.items.length; i++) {\r\n const configItem = config.items[i];\r\n\r\n const itemText = new TextElement(\r\n new Text(\r\n configItem.name ?? \"Item\",\r\n {\r\n color: Theme.ContextMenu.FontColor,\r\n }\r\n ),\r\n {\r\n Padding: 8\r\n }\r\n );\r\n\r\n quickItems.push(new QuickMenuItem(\r\n currentPath + (configItem.name ?? \"\"),\r\n itemText,\r\n configItem\r\n ));\r\n\r\n renderElements.push(itemText);\r\n }\r\n\r\n groups.push(new QuickMenuGroup(titleText, quickItems));\r\n }\r\n\r\n if (config?.subMenus) {\r\n for (let i = 0; i < config?.subMenus.length; i++) {\r\n const configItem = config?.subMenus[i];\r\n RecurseBuildContainers(currentPath, configItem, renderElements, groups);\r\n }\r\n }\r\n}\r\n\r\nexport class QuickMenu {\r\n\r\n #menuGroups: Array<QuickMenuGroup>\r\n\r\n #container: ContainerElement\r\n\r\n #searchText: Text;\r\n\r\n #currentSelection: number;\r\n\r\n constructor(config?: ContextMenuConfig) {\r\n this.#menuGroups = [];\r\n this.#currentSelection = 0;\r\n\r\n this.#searchText = new Text(\r\n \"\",\r\n {\r\n color: Theme.ContextMenu.FontColor,\r\n }\r\n );\r\n\r\n const elements = [\r\n new TextElement(\r\n new Text(\r\n \"Search\",\r\n {\r\n color: Theme.ContextMenu.FontColor,\r\n }\r\n ),\r\n {\r\n Padding: {\r\n Bottom: 0,\r\n Left: 8,\r\n Right: 8,\r\n Top: 8\r\n },\r\n }\r\n ),\r\n\r\n // Search Box...\r\n new ContainerElement(\r\n [\r\n new TextElement(\r\n this.#searchText,\r\n undefined\r\n ),\r\n ],\r\n {\r\n Border: {\r\n Radius: 2,\r\n },\r\n BackgroundColor: \"#003847\",\r\n Padding: 8,\r\n Margin: 8,\r\n MinHeight: 46,\r\n }\r\n ),\r\n ]\r\n\r\n if (config) {\r\n RecurseBuildContainers(\"\", config, elements, this.#menuGroups);\r\n }\r\n\r\n this.#container = new ContainerElement(\r\n elements,\r\n {\r\n BackgroundColor: Theme.ContextMenu.BackgroundColor,\r\n Border: {\r\n Thickness: 1,\r\n Radius: 4\r\n }\r\n }\r\n )\r\n\r\n this.#updateHighlighting();\r\n }\r\n\r\n execute(): void {\r\n let selection = this.#currentSelection;\r\n\r\n for (let groupIndex = 0; groupIndex < this.#menuGroups.length; groupIndex++) {\r\n const group = this.#menuGroups[groupIndex];\r\n\r\n for (let itemIndex = 0; itemIndex < group.items.length; itemIndex++) {\r\n if (group.items[itemIndex].rendering()) {\r\n if (selection === 0) {\r\n group.items[itemIndex].select();\r\n return;\r\n }\r\n selection--;\r\n }\r\n }\r\n }\r\n }\r\n\r\n #updateHighlighting(): void {\r\n const searchText = this.#searchText\r\n .get()\r\n .trim()\r\n .toLowerCase();\r\n\r\n let terms = new Array<string>();\r\n if (searchText !== \"\") {\r\n var potentialTerms = searchText.split(\" \");\r\n for (let i = 0; i < potentialTerms.length; i++) {\r\n const cleaned = potentialTerms[i].trim();\r\n if (cleaned !== \"\") {\r\n terms.push(cleaned);\r\n }\r\n }\r\n }\r\n\r\n let selection = this.#currentSelection;\r\n\r\n for (let groupIndex = 0; groupIndex < this.#menuGroups.length; groupIndex++) {\r\n const group = this.#menuGroups[groupIndex];\r\n group.updateRendering(terms);\r\n\r\n for (let itemIndex = 0; itemIndex < group.items.length; itemIndex++) {\r\n if (group.items[itemIndex].rendering()) {\r\n group.items[itemIndex].highlight(selection === 0)\r\n selection--;\r\n }\r\n }\r\n }\r\n }\r\n\r\n keyboardEvent(event: KeyboardEvent): void {\r\n\r\n let intercepted = true;\r\n\r\n if (event.code === \"Backspace\") {\r\n this.#currentSelection = 0;\r\n const text = this.#searchText.get();\r\n this.#searchText.set(text.slice(0, text.length - 1));\r\n } else if (/^[a-zA-Z0-9]$/.test(event.key) || event.key === \" \") {\r\n this.#currentSelection = 0;\r\n this.#searchText.set(this.#searchText.get() + event.key);\r\n } else if (event.key === \"ArrowUp\") {\r\n this.#currentSelection = Math.max(0, this.#currentSelection - 1);\r\n } else if (event.key === \"ArrowDown\") {\r\n this.#currentSelection ++;\r\n } else {\r\n intercepted = false;\r\n }\r\n\r\n if (intercepted) {\r\n this.#updateHighlighting();\r\n event.preventDefault();\r\n }\r\n\r\n // console.log(event);\r\n }\r\n\r\n renderSize = { x: 0, y: 0 };\r\n\r\n public render(ctx: CanvasRenderingContext2D, pos: Vector2, graphScale: number, mousePosition: Vector2 | undefined): null {\r\n this.#container.calcSize(ctx, this.renderSize, { x: -1, y: -1 });\r\n // ScaleVector(this.renderSize, graphScale);\r\n\r\n // Clamp the position so it's not spilling off the canvas\r\n if (pos.y + Math.min(this.renderSize.y, 400) > ctx.canvas.clientHeight) {\r\n pos.y = ctx.canvas.clientHeight - Math.min(this.renderSize.y, 400);\r\n }\r\n\r\n if (pos.x + this.renderSize.x > ctx.canvas.clientWidth) {\r\n pos.x = ctx.canvas.clientWidth - this.renderSize.x;\r\n }\r\n\r\n if (pos.y < 0) {\r\n pos.y = 0;\r\n }\r\n\r\n if (pos.x < 0) {\r\n pos.x = 0;\r\n }\r\n\r\n this.#container.render(ctx, pos, 1, this.renderSize);\r\n return null;\r\n }\r\n}\r\n", "import { CombineContextMenus, ContextEntry, ContextMenu, ContextMenuConfig } from './contextMenu';\r\nimport { Theme } from \"./theme\";\r\nimport { MouseObserver } from \"./input\";\r\nimport { FlowNode } from \"./node\";\r\nimport { NodeCreatedCallback, NodeFactoryConfig } from \"./nodes/factory\";\r\nimport { TimeExecution } from \"./performance\";\r\nimport { CursorStyle } from \"./styles/cursor\";\r\nimport { CopyVector2, Vector2, Zero } from './types/vector2';\r\nimport { Clamp01 } from \"./utils/math\";\r\nimport { GraphSubsystem, RenderResults } from './graphSubsystem';\r\nimport { FlowNote } from \"./notes/note\";\r\nimport { NoteAddedCallback, NoteDragStartCallback, NoteDragStopCallback, NoteRemovedCallback, NoteSubsystem, NoteSubsystemConfig } from \"./notes/subsystem\";\r\nimport { ConnectionRendererConfiguration, NodeAddedCallback, NodeRemovedCallback, NodeSubsystem } from \"./nodes/subsystem\";\r\nimport { Connection } from './connection';\r\nimport { Publisher } from './nodes/publisher';\r\nimport { VectorPool } from './types/pool';\r\nimport { Camera } from './camera';\r\nimport { PassSubsystem } from './pass/subsystem';\r\nimport { QuickMenu } from './quickMenu';\r\n\r\nexport type GraphRenderer = (canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, position: Vector2, scale: number) => void;\r\n\r\nfunction BuildBackgroundRenderer(backgroundColor: string): GraphRenderer {\r\n return (canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, position: Vector2, scale: number): void => {\r\n context.fillStyle = backgroundColor;\r\n context.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n const alpha = Math.round(Clamp01(scale - 0.3) * 255)\r\n if (alpha <= 0) {\r\n return;\r\n }\r\n\r\n context.fillStyle = `rgba(41, 54, 57, ${alpha})`;\r\n const spacing = 100;\r\n const pi2 = 2 * Math.PI\r\n const dotScale = 2 * scale;\r\n for (let x = -50; x < 50; x++) {\r\n const xPos = (x * spacing * scale) + position.x;\r\n for (let y = -50; y < 50; y++) {\r\n const yPos = (y * spacing * scale) + position.y;\r\n context.beginPath();\r\n context.arc(xPos, yPos, dotScale, 0, pi2);\r\n context.fill();\r\n }\r\n }\r\n }\r\n}\r\n\r\nconst contextMenuGroup = \"graph-context-menu\";\r\n\r\nexport interface FlowNodeGraphConfiguration {\r\n backgroundRenderer?: GraphRenderer;\r\n backgroundColor?: string;\r\n idleConnection?: ConnectionRendererConfiguration\r\n contextMenu?: ContextMenuConfig\r\n nodes?: NodeFactoryConfig\r\n board?: NoteSubsystemConfig\r\n}\r\n\r\ninterface OpenContextMenu {\r\n Menu: ContextMenu\r\n Position: Vector2\r\n}\r\n\r\ninterface OpenQuickMenu {\r\n Menu: QuickMenu\r\n Position: Vector2\r\n}\r\n\r\nclass GraphView {\r\n\r\n #subsystems: Array<GraphSubsystem>;\r\n\r\n constructor(subsystems: Array<GraphSubsystem>) {\r\n this.#subsystems = subsystems;\r\n }\r\n\r\n clickStart(mousePosition: Vector2, camera: Camera, ctrlKey: boolean) {\r\n // Since the graph is rendered from 0 => n, n is the last thing \r\n // rendererd and is always shown to the user. So if their clicking on\r\n // two things technically, we need to make sure it's whatever was most \r\n // recently rendered. So we traverse n => 0. \r\n for (let i = this.#subsystems.length - 1; i >= 0; i--) {\r\n // If the user sucesfully clicked on something in this layer, don't\r\n // check any more layers.\r\n if (this.#subsystems[i].clickStart(mousePosition, camera, ctrlKey)) {\r\n return;\r\n }\r\n }\r\n }\r\n\r\n fileDrop(file: File): boolean {\r\n for (let i = this.#subsystems.length - 1; i >= 0; i--) {\r\n if (this.#subsystems[i].fileDrop(file)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n openContextMenu(ctx: CanvasRenderingContext2D, position: Vector2): ContextMenuConfig {\r\n let finalConfig: ContextMenuConfig = {};\r\n\r\n for (let i = 0; i < this.#subsystems.length; i++) {\r\n const subSystemMenu = this.#subsystems[i].openContextMenu(ctx, position);\r\n if (subSystemMenu !== null) {\r\n finalConfig = CombineContextMenus(finalConfig, subSystemMenu);\r\n }\r\n }\r\n\r\n return finalConfig;\r\n }\r\n\r\n clickEnd(): void {\r\n for (let i = 0; i < this.#subsystems.length; i++) {\r\n this.#subsystems[i].clickEnd();\r\n }\r\n }\r\n\r\n mouseDragEvent(delta: Vector2, scale: number): boolean {\r\n for (let i = 0; i < this.#subsystems.length; i++) {\r\n if (this.#subsystems[i].mouseDragEvent(delta, scale)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, camera: Camera, mousePosition: Vector2 | undefined): RenderResults {\r\n const results: RenderResults = {};\r\n for (let i = 0; i < this.#subsystems.length; i++) {\r\n TimeExecution(\"Render_Subsystem_\" + i, () => {\r\n let results = this.#subsystems[i].render(ctx, camera, mousePosition);\r\n if (results?.cursorStyle) {\r\n results.cursorStyle = results?.cursorStyle;\r\n }\r\n })\r\n }\r\n return results;\r\n }\r\n}\r\n\r\nexport class NodeFlowGraph {\r\n\r\n #ctx: CanvasRenderingContext2D;\r\n\r\n #canvas: HTMLCanvasElement;\r\n\r\n #backgroundRenderer: GraphRenderer\r\n\r\n #contextMenuConfig: ContextMenuConfig;\r\n\r\n #mousePosition: Vector2 | undefined;\r\n\r\n #camera: Camera;\r\n\r\n #openedContextMenu: OpenContextMenu | null;\r\n\r\n #openQuickMenu: OpenQuickMenu | null;\r\n\r\n #contextMenuEntryHovering: ContextEntry | null;\r\n\r\n #views: Array<GraphView>;\r\n\r\n #currentView: number;\r\n\r\n #mainNodeSubsystem: NodeSubsystem;\r\n\r\n #mainNoteSubsystem: NoteSubsystem;\r\n\r\n constructor(canvas: HTMLCanvasElement, config?: FlowNodeGraphConfiguration) {\r\n const postProcessPass = new PassSubsystem();\r\n\r\n this.#mainNodeSubsystem = new NodeSubsystem(postProcessPass, {\r\n nodes: config?.nodes,\r\n idleConnection: config?.idleConnection\r\n });\r\n\r\n this.#lastFrameCursor = CursorStyle.Default;\r\n this.#cursor = CursorStyle.Default;\r\n\r\n this.#mainNoteSubsystem = new NoteSubsystem(config?.board);\r\n\r\n this.#views = [\r\n new GraphView([\r\n this.#mainNoteSubsystem,\r\n this.#mainNodeSubsystem,\r\n postProcessPass\r\n ])\r\n ];\r\n this.#currentView = 0;\r\n\r\n this.#camera = new Camera();\r\n\r\n this.#contextMenuConfig = CombineContextMenus({\r\n items: [\r\n {\r\n name: \"Reset View\",\r\n group: contextMenuGroup,\r\n callback: this.#camera.reset.bind(this.#camera)\r\n },\r\n ],\r\n }, config?.contextMenu);\r\n\r\n this.#openedContextMenu = null;\r\n this.#openQuickMenu = null;\r\n this.#contextMenuEntryHovering = null;\r\n\r\n this.#canvas = canvas;\r\n const ctx = canvas.getContext(\"2d\")\r\n if (ctx === null) {\r\n throw new Error(\"could not create canvas context\")\r\n }\r\n this.#ctx = ctx;\r\n\r\n if (config?.backgroundRenderer !== undefined) {\r\n this.#backgroundRenderer = config?.backgroundRenderer\r\n } else {\r\n const backgroundColor = config?.backgroundColor === undefined ? Theme.Graph.BackgroundColor : config.backgroundColor;\r\n this.#backgroundRenderer = BuildBackgroundRenderer(backgroundColor);\r\n }\r\n\r\n window.requestAnimationFrame(this.#render.bind(this));\r\n\r\n this.#canvas.addEventListener('wheel', (event) => {\r\n event.preventDefault();\r\n this.zoom(Math.sign(event.deltaY));\r\n }, false);\r\n\r\n new MouseObserver(this.#canvas,\r\n this.#mouseDragEvent.bind(this),\r\n\r\n // Mouse move event\r\n (mousePosition) => {\r\n this.#mousePosition = mousePosition;\r\n },\r\n\r\n this.#clickStart.bind(this),\r\n this.#clickEnd.bind(this),\r\n this.#openContextMenu.bind(this),\r\n this.#fileDrop.bind(this)\r\n );\r\n\r\n document.addEventListener(\r\n \"keydown\",\r\n (e) => {\r\n if (document.activeElement) {\r\n if ([\"INPUT\", \"TEXTAREA\"].includes(document.activeElement.tagName)) return;\r\n }\r\n\r\n if (this.#openQuickMenu) {\r\n if (e.code === \"Escape\") {\r\n this.#openQuickMenu = null;\r\n return;\r\n }\r\n\r\n if (e.code === \"Enter\") {\r\n this.#openQuickMenu.Menu.execute();\r\n this.#openQuickMenu = null;\r\n return;\r\n }\r\n\r\n this.#openQuickMenu.Menu.keyboardEvent(e);\r\n return\r\n }\r\n\r\n const spacePressed = e.key == \" \" || e.code == \"Space\";\r\n if (!spacePressed) {\r\n return;\r\n }\r\n\r\n if (!this.#mousePosition) {\r\n return;\r\n }\r\n const contextMenuPosition = this.#sceenPositionToGraphPosition(this.#mousePosition);\r\n\r\n let items = this.#mainNodeSubsystem.nodeFactory().newNodeSubmenus(this.#mainNodeSubsystem, contextMenuPosition);\r\n this.#openQuickMenu = {\r\n Menu: new QuickMenu({\r\n subMenus: items,\r\n }),\r\n Position: contextMenuPosition\r\n }\r\n }\r\n );\r\n }\r\n\r\n #fileDrop(file: File): void {\r\n\r\n if (this.currentView().fileDrop(file)) {\r\n return;\r\n }\r\n\r\n const contents = file.name.split('.');\r\n const extension = contents[contents.length - 1];\r\n if (extension !== \"jpg\" && extension !== \"jpeg\" && extension !== \"png\") {\r\n return;\r\n }\r\n\r\n let pos = Zero();\r\n if (this.#mousePosition) {\r\n CopyVector2(pos, this.#sceenPositionToGraphPosition(this.#mousePosition));\r\n }\r\n\r\n this.#mainNodeSubsystem.addNode(new FlowNode({\r\n title: contents[0],\r\n position: pos,\r\n widgets: [{\r\n type: \"image\",\r\n config: {\r\n blob: file,\r\n }\r\n }]\r\n }));\r\n }\r\n\r\n public addNoteAddedListener(callback: NoteAddedCallback): void {\r\n this.#mainNoteSubsystem.addNoteAddedListener(callback);\r\n }\r\n\r\n public addNoteRemovedListener(callback: NoteRemovedCallback): void {\r\n this.#mainNoteSubsystem.addNoteRemovedListener(callback);\r\n }\r\n\r\n public addNoteDragStartListener(callback: NoteDragStartCallback): void {\r\n this.#mainNoteSubsystem.addNoteDragStartListener(callback);\r\n }\r\n\r\n public addNoteDragStopListener(callback: NoteDragStopCallback): void {\r\n this.#mainNoteSubsystem.addNoteDragStopListener(callback);\r\n }\r\n\r\n\r\n zoom(amount: number): void {\r\n\r\n let oldPos: Vector2 | undefined = undefined;\r\n if (this.#mousePosition) {\r\n oldPos = this.#sceenPositionToGraphPosition(this.#mousePosition);;\r\n }\r\n\r\n this.#camera.zoom += amount * this.#camera.zoom * 0.05;\r\n\r\n if (!oldPos || !this.#mousePosition) {\r\n return;\r\n }\r\n // Attempt zoom around where the current mouse is.\r\n const newPos = this.#sceenPositionToGraphPosition(this.#mousePosition);\r\n this.#camera.position.x += (newPos.x - oldPos.x) * this.#camera.zoom;\r\n this.#camera.position.y += (newPos.y - oldPos.y) * this.#camera.zoom;\r\n }\r\n\r\n #clickStart(mousePosition: Vector2, ctrlKey: boolean): void {\r\n if (this.#contextMenuEntryHovering !== null) {\r\n this.#contextMenuEntryHovering.click();\r\n this.#openedContextMenu = null;\r\n this.#contextMenuEntryHovering = null;\r\n return;\r\n }\r\n this.#openedContextMenu = null;\r\n this.#openQuickMenu = null;\r\n this.#contextMenuEntryHovering = null;\r\n\r\n this.#mousePosition = mousePosition;\r\n this.currentView().clickStart(mousePosition, this.#camera, ctrlKey);\r\n }\r\n\r\n currentView(): GraphView {\r\n return this.#views[this.#currentView];\r\n }\r\n\r\n organize(): void {\r\n this.#mainNodeSubsystem.organize(this.#ctx);\r\n }\r\n\r\n addPublisher(identifier: string, publisher: Publisher): void {\r\n this.#mainNodeSubsystem.addPublisher(identifier, publisher);\r\n }\r\n\r\n getNodes(): Array<FlowNode> {\r\n return this.#mainNodeSubsystem.getNodes();\r\n }\r\n\r\n connectedInputsNodeReferences(nodeIndex: number): Array<FlowNode> {\r\n return this.#mainNodeSubsystem.connectedInputsNodeReferencesByIndex(nodeIndex);\r\n }\r\n\r\n connectedOutputsNodeReferences(nodeIndex: number): Array<FlowNode> {\r\n return this.#mainNodeSubsystem.connectedOutputsNodeReferences(nodeIndex);\r\n }\r\n\r\n connectNodes(nodeOut: FlowNode, outPort: number, nodeIn: FlowNode, inPort: number): Connection | undefined {\r\n return this.#mainNodeSubsystem.connectNodes(nodeOut, outPort, nodeIn, inPort);\r\n }\r\n\r\n addNode(node: FlowNode): void {\r\n this.#mainNodeSubsystem.addNode(node);\r\n }\r\n\r\n removeNode(node: FlowNode): void {\r\n this.#mainNodeSubsystem.removeNode(node);\r\n }\r\n\r\n addNote(note: FlowNote): void {\r\n this.#mainNoteSubsystem.addNote(note);\r\n }\r\n\r\n removeNote(note: FlowNote): void {\r\n this.#mainNoteSubsystem.removeNote(note);\r\n }\r\n\r\n removeAllNotes(): void {\r\n this.#mainNoteSubsystem.removeAllNotes();\r\n }\r\n\r\n getNotes(): Array<FlowNote> {\r\n return this.#mainNoteSubsystem.getNotes();\r\n }\r\n\r\n public addOnNodeCreatedListener(callback: NodeCreatedCallback): void {\r\n this.#mainNodeSubsystem.addOnNodeCreatedListener(callback);\r\n }\r\n\r\n public addOnNodeAddedListener(callback: NodeAddedCallback): void {\r\n this.#mainNodeSubsystem.addOnNodeAddedListener(callback);\r\n }\r\n\r\n public addOnNodeRemovedListener(callback: NodeRemovedCallback): void {\r\n this.#mainNodeSubsystem.addOnNodeRemovedListener(callback);\r\n }\r\n\r\n #sceenPositionToGraphPosition(screenPosition: Vector2): Vector2 {\r\n const out = Zero();\r\n this.#camera.screenSpaceToGraphSpace(screenPosition, out);\r\n return out;\r\n }\r\n\r\n #openContextMenu(position: Vector2): void {\r\n let finalConfig = this.#contextMenuConfig;\r\n\r\n const contextMenuPosition = this.#sceenPositionToGraphPosition(position);\r\n\r\n finalConfig = CombineContextMenus(finalConfig, this.currentView().openContextMenu(this.#ctx, contextMenuPosition));\r\n\r\n this.#openedContextMenu = {\r\n Menu: new ContextMenu(finalConfig),\r\n Position: contextMenuPosition,\r\n };\r\n }\r\n\r\n\r\n // Somethings wrong here. Needs more testing\r\n // #fitView(): void {\r\n // if (this.#nodes.length === 0) {\r\n // return;\r\n // }\r\n\r\n // const curBox: Box = {\r\n // Position: { x: 0, y: 0 },\r\n // Size: { x: 0, y: 0 }\r\n // };\r\n // CopyBox(curBox, this.#nodes[0].calculateBounds(this.#ctx, this.#graphState.position, this.#graphState.scale));\r\n\r\n // for (let i = 1; i < this.#nodes.length; i++) {\r\n // ExpandBox(curBox, this.#nodes[i].calculateBounds(this.#ctx, this.#graphState.position, this.#graphState.scale));\r\n // }\r\n\r\n // CopyVector2(this.#graphState.position, curBox.Position);\r\n // }\r\n\r\n #clickEnd(): void {\r\n this.currentView().clickEnd();\r\n }\r\n\r\n #mouseDragEvent(delta: Vector2): void {\r\n let draggingSomething = this.currentView().mouseDragEvent(delta, this.#camera.zoom);\r\n if (!draggingSomething) {\r\n this.#camera.position.x += delta.x;\r\n this.#camera.position.y += delta.y;\r\n }\r\n }\r\n\r\n #lastFrameCursor: CursorStyle;\r\n\r\n #cursor: CursorStyle;\r\n\r\n #render(): void {\r\n if (this.#canvas.parentNode !== null) {\r\n // Stupid as any because typescript doesn't think it exists\r\n var rect = (this.#canvas.parentNode as any).getBoundingClientRect();\r\n this.#canvas.width = rect.width;\r\n this.#canvas.height = rect.height;\r\n }\r\n\r\n\r\n this.#cursor = CursorStyle.Default;\r\n\r\n TimeExecution(\"Render_Background\", this.#renderBackground.bind(this));\r\n\r\n TimeExecution(\"Render_View_\" + this.#currentView, () => {\r\n let results = this.currentView().render(this.#ctx, this.#camera, this.#mousePosition);\r\n if (results?.cursorStyle) {\r\n this.#cursor = results?.cursorStyle;\r\n }\r\n });\r\n\r\n TimeExecution(\"Render_Context\", this.#renderContextMenu.bind(this));\r\n\r\n TimeExecution(\"Render_QuickMenu\", this.#renderQuickMenu.bind(this))\r\n\r\n // Only update CSS style if things have changed\r\n // TODO: Does this actually have any measurable performance savings?\r\n if (this.#lastFrameCursor !== this.#cursor) {\r\n this.#canvas.style.cursor = this.#cursor;\r\n }\r\n this.#lastFrameCursor = this.#cursor;\r\n\r\n window.requestAnimationFrame(this.#render.bind(this));\r\n }\r\n\r\n #renderBackground(): void {\r\n this.#backgroundRenderer(this.#canvas, this.#ctx, this.#camera.position, this.#camera.zoom);\r\n }\r\n\r\n #renderContextMenu(): void {\r\n VectorPool.run(() => {\r\n if (this.#openedContextMenu !== null) {\r\n const pos = VectorPool.get();\r\n this.#camera.graphSpaceToScreenSpace(this.#openedContextMenu.Position, pos)\r\n this.#contextMenuEntryHovering = this.#openedContextMenu.Menu.render(this.#ctx, pos, this.#camera.zoom, this.#mousePosition, true);\r\n\r\n if (this.#contextMenuEntryHovering !== null) {\r\n this.#cursor = CursorStyle.Pointer;\r\n }\r\n }\r\n });\r\n }\r\n\r\n #renderQuickMenu(): void {\r\n VectorPool.run(() => {\r\n if (this.#openQuickMenu !== null) {\r\n const pos = VectorPool.get();\r\n this.#camera.graphSpaceToScreenSpace(this.#openQuickMenu.Position, pos)\r\n this.#contextMenuEntryHovering = this.#openQuickMenu.Menu.render(this.#ctx, pos, this.#camera.zoom, this.#mousePosition);\r\n\r\n if (this.#contextMenuEntryHovering !== null) {\r\n this.#cursor = CursorStyle.Pointer;\r\n }\r\n }\r\n });\r\n }\r\n}"],
5
+ "mappings": "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",
6
+ "names": ["Theme", "DefaultSize", "DefaultColor", "TextStyleFallback", "input", "fallback", "TextStyle", "#size", "#color", "#font", "#weight", "#fontStyle", "config", "Theme", "ctx", "scale", "text", "out", "measurements", "color", "size", "weight", "Pool", "#arr", "#count", "#builder", "#reset", "#runningDepth", "builder", "reset", "condition", "fn", "#running", "start", "value", "VectorPool", "v", "CopyVector2", "dst", "src", "SubVector2", "a", "b", "AddVector2", "ScaleVector", "scale", "Zero", "Distance", "xd", "yd", "normalizeMinMax", "min", "max", "temp", "BoxIntersection", "a", "b", "intersects", "VectorPool", "aMin", "aMax", "CopyVector2", "AddVector2", "bMin", "bMax", "BoxCenter", "box", "out", "InBox", "position", "List", "#arr", "#count", "index", "value", "arr", "i", "contextEntryHeight", "ContextMenuItem", "#name", "#callback", "#textStyle", "config", "TextStyle", "ContextGroup", "entries", "#calculatedHeight", "contextEntryHeight", "ContextEntry", "text", "subMenu", "item", "CombineContextMenus", "contextMenus", "finalConfig", "i", "ContextMenu", "#items", "#subMenus", "#groups", "#group", "#submenuPosition", "Zero", "List", "TextStyleFallback", "Theme", "#calculateEntries", "groupLUT", "workingGroups", "group", "sub", "groupIndex", "groupContent", "#calculatedWidth", "#getMaxWidthForText", "ctx", "scale", "tempVec", "entryIndex", "#tempBox", "#openSubMenu", "pppp", "graphScale", "mousePosition", "openRight", "scaledEntryHeight", "scaledEntryWidth", "totalScaledHeight", "position", "CopyVector2", "submenuOpenRight", "mouseIsOver", "subOpenedThisFrame", "optionsRendered", "entry", "entryMousedOver", "InBox", "startX", "y", "mouseOverSub", "MouseObserver", "#clicked", "#lastTouch", "#ele", "#lastMousePosition", "#dragCallback", "#moveCallback", "#clickStart", "#clickStop", "#contextMenu", "ele", "dragCallback", "moveCallback", "clickStart", "clickStop", "contextMenu", "fileDrop", "Zero", "#down", "#touchDown", "#up", "#move", "#moveTouch", "ev", "item", "i", "file", "#mousePosition", "evt", "event", "rect", "pos", "delta", "SubVector2", "CopyVector2", "InstantiateRenderElementSidesStyling", "config", "RenderElementBase", "#margin", "#padding", "#border", "#backgroundColor", "#minWidth", "#maxWidth", "#minHeight", "#maxHeight", "#grow", "#display", "config", "InstantiateRenderElementSidesStyling", "newColor", "ctx", "position", "graphScale", "scaledFillableSpace", "scaledSize", "offsetPosition", "#totalLeftOffset", "#totalTopOffset", "elementSize", "#horizontalOffset", "#verticalOffset", "out", "display", "maxLimits", "ContainerRenderElement", "RenderElementBase", "#elements", "#layout", "#alignment", "elements", "config", "ctx", "out", "limitations", "eleSize", "i", "position", "graphScale", "scaledFillableSpace", "#renderColumn", "currnetPos", "scaledEleSize", "ele", "ScaleVector", "TextElement", "RenderElementBase", "#text", "#align", "#verticalAlign", "#lineHeight", "text", "styling", "ctx", "position", "graphScale", "scaledFillableSpace", "scale", "Zero", "ScaleVector", "justifiedPosition", "CopyVector2", "eles", "tempSize", "i", "out", "limitations", "binarySearch", "max", "getValue", "match", "min", "guess", "compareVal", "fitString", "ctx", "str", "maxWidth", "width", "ellipsis", "ellipsisWidth", "index", "splitString", "backward", "splitStringIntoLines", "strings", "remaining", "Text", "#measured", "#size", "#style", "#value", "#maxWidth", "#lineSpacing", "#textToRender", "value", "style", "config", "Zero", "TextStyle", "event", "newValue", "ctx", "maxWidth", "results", "entries", "splitStringIntoLines", "i", "text", "char", "index", "splitString", "#measure", "measurements", "scale", "out", "CopyVector2", "ScaleVector", "color", "size", "weight", "position", "yOffset", "Clamp", "v", "min", "max", "Clamp01", "componentToHex", "c", "hex", "RgbToHex", "HexToColor", "result", "HSV2RGB", "hsv", "out", "hh", "ff", "p", "q", "t", "Clamp01", "fallbackColor", "type", "s", "value", "mod", "hsv", "color", "HSV2RGB", "RgbToHex", "Port", "#node", "#displayName", "#emptyStyle", "#filledStyle", "#connections", "#portType", "#dataType", "#dataTypePopupElement", "#onConnectionAdded", "#onConnectionRemoved", "node", "portType", "config", "containerElements", "dataTypeDisplay", "TextElement", "Text", "description", "ContainerRenderElement", "connection", "c", "index", "i", "callback", "#box", "ctx", "position", "camera", "mousePosition", "postProcess", "style", "scaledRadius", "InBox", "xPos", "yPos", "size", "StrokeStyleWithFallback", "input", "fallback", "StrokeStyle", "#size", "#color", "config", "ctx", "scale", "newColor", "newSize", "BoxStyleWithFallback", "input", "fallback", "StrokeStyleWithFallback", "BoxStyle", "#border", "#color", "#radius", "config", "StrokeStyle", "#box", "ctx", "box", "scale", "radius", "#draw", "color", "Popup", "#title", "#options", "#content", "#onClose", "#buttonCSS", "#popup", "config", "container", "title", "buttonContainer", "i", "button", "TextBoxStyleWithFallback", "input", "fallback", "BoxStyleWithFallback", "TextStyleFallback", "TextBoxStyle", "#box", "#text", "#textAlign", "#textBaseline", "config", "BoxStyle", "TextStyle", "ctx", "box", "scale", "text", "color", "width", "height", "NumberWidget", "#node", "#nodeProperty", "#value", "#idleBoxStyle", "#highlightBoxStyle", "#text", "#callback", "node", "config", "TextBoxStyle", "TextBoxStyleWithFallback", "Theme", "oldVal", "newVal", "width", "height", "newNumber", "input", "setOption", "cancelOption", "Popup", "container", "button", "ctx", "position", "scale", "mousePosition", "box", "CopyVector2", "style", "InBox", "ButtonWidget", "#text", "#idleStyle", "#hoverStyle", "#clickStyle", "#callback", "#gettingClicked", "config", "TextBoxStyle", "TextBoxStyleWithFallback", "Theme", "width", "height", "ctx", "position", "scale", "mousePosition", "box", "CopyVector2", "style", "InBox", "contrastColor", "color", "c", "HexToColor", "ColorWidget", "#node", "#nodeProperty", "#value", "#contrast", "#textBoxStyle", "#callback", "node", "config", "TextBoxStyle", "Theme", "oldVal", "newVal", "width", "height", "value", "input", "Popup", "container", "label", "button", "ctx", "position", "scale", "mousePosition", "box", "CopyVector2", "SliderWidget", "#min", "#max", "#value", "#text", "#snapIncrement", "#node", "#nodeProperty", "#change", "#release", "#textStyle", "#backgroundColor", "#borderColor", "#fillColor", "#lastMousePosition", "#clickStartMousePosition", "#clicking", "node", "config", "Theme", "TextStyle", "TextStyleFallback", "Zero", "oldVal", "newVal", "newValue", "cleanedValue", "Clamp", "width", "height", "CopyVector2", "ctx", "position", "scale", "mousePosition", "scaledWidth", "scaledHeight", "scaledBorderThickness", "fill", "Clamp01", "min", "max", "value", "SetStringPopup", "config", "input", "Popup", "container", "button", "StringWidget", "#value", "#idleStyle", "#hoverStyle", "#callback", "#node", "#nodeProperty", "node", "config", "TextBoxStyle", "TextBoxStyleWithFallback", "Theme", "oldVal", "newVal", "width", "height", "value", "SetStringPopup", "ctx", "position", "scale", "mousePosition", "box", "CopyVector2", "style", "InBox", "fitString", "ToggleStyle", "#idleStyle", "#hoverStyle", "#lightColor", "#lightBorderColor", "#lightBlur", "#box", "config", "TextBoxStyle", "TextBoxStyleWithFallback", "Theme", "ctx", "pos", "scale", "text", "mousePosition", "scaledWidth", "width", "scaledHeight", "height", "CopyVector2", "style", "InBox", "lightScale", "ToggleWidget", "#node", "#nodeProperty", "#value", "#text", "#enabledStyle", "#disabledStyle", "#callback", "node", "oldVal", "newVal", "position", "value", "ImageWidget", "#url", "#image", "#maxWidth", "#maxHeight", "config", "blob", "imageUrl", "url", "img", "event", "adjust", "heightAdjust", "ctx", "position", "scale", "mousePosition", "size", "box", "CopyVector2", "TextWidget", "#value", "#callback", "#node", "#nodeProperty", "#size", "node", "config", "Zero", "Text", "TextStyleFallback", "Theme", "oldVal", "newVal", "value", "ctx", "position", "scale", "mousePosition", "box", "CopyVector2", "WidgetFactory", "#registeredWidgets", "widgetType", "builder", "node", "config", "GlobalWidgetFactory", "ButtonWidget", "NumberWidget", "ColorWidget", "SliderWidget", "StringWidget", "ToggleWidget", "ImageWidget", "TextWidget", "DefaultConnectionRenderer", "connectionSize", "connectionColor", "mouseOverSize", "mouseOverColor", "params", "color", "lineSize", "midX", "Connection", "#inPos", "#outPos", "#inNode", "#inNodePortIndex", "#outNode", "#outNodePortIndex", "#renderer", "inNode", "inNodePortIndex", "outNode", "outNodePortIndex", "renderer", "Zero", "ctx", "graphScale", "mouseOver", "mousePosition", "inPortBox", "BoxCenter", "outPortBox", "InBox", "node", "portIndex", "replace", "port", "Camera", "Zero", "screenPosition", "out", "scale", "graphPosition", "MarkInputs", "graph", "positions", "nodeLUT", "node", "depth", "shouldSort", "inputs", "i", "nodeIndex", "MarkOutputs", "outputs", "Organize", "ctx", "nodesToSort", "nodes", "bounds", "relativePosition", "claimed", "camera", "Camera", "entries", "min", "max", "x", "val", "a", "b", "columns", "entry", "p", "position", "nodeBounds", "column", "allColumnsWidths", "c", "widthSpacing", "heightSpacing", "widthOffset", "heightOffset", "n", "pos", "TimeExecution", "name", "callback", "start", "end", "Publisher", "#name", "#description", "#version", "#registeredNodes", "config", "nodeKey", "nodeType", "#recurseBuildMenu", "graph", "name", "subMenu", "position", "items", "subMenus", "key", "nodeConfig", "slashIndex", "bracketIndex", "node", "FlowNode", "elements", "menu", "menus", "nodes", "NodeFactory", "#registeredPublishers", "#registeredCallbacks", "config", "entry", "Publisher", "callback", "identifier", "publisher", "nodeType", "publisherIdentifier", "node", "i", "graph", "position", "menus", "_", "nodeFlowGroup", "nodeFlowGroup", "BuildConnectionRenderer", "config", "DefaultConnectionRenderer", "NodeSubsystem", "#postProcessPass", "#nodes", "#connections", "#nodeHovering", "#nodesGrabbed", "#connectionSelected", "#idleConnectionRenderer", "#portHovering", "#widgetHovering", "#widgetCurrentlyClicking", "#cursor", "#nodeFactory", "#boxSelect", "#boxSelectStart_graphSpace", "#boxSelectEnd_graphSpace", "#boxSelectionNodes", "#boxSelectStyle", "#nodeRemovedCallbacks", "#registeredNodeAddedCallbacks", "postProcessPass", "List", "NodeFactory", "Zero", "BoxStyle", "Theme", "identifier", "publisher", "callback", "mousePosition", "camera", "ctrlKey", "hoveringSomething", "#selectNodeByIndex", "i", "CopyVector2", "inNode", "inNodeIndex", "outNode", "outNodeIndex", "connection", "Connection", "delta", "scale", "nodeMoved", "VectorPool", "scaledDelta", "AddVector2", "#interactingWithNode", "node", "#interactingWithConnection", "#interactingWithWidget", "index", "port", "#removeConnection", "#selectNode", "#clearCurrentlySelectedConnection", "conn", "replace", "inputPort", "nodeOut", "outPort", "nodeIn", "inPort", "outType", "inType", "existingInputConnections", "nodeIndex", "connections", "file", "#removeNodeConnections", "#removeConnectionByIndex", "#removeNodeByIndex", "clearPorts", "ctx", "Organize", "#nodesSelected", "selected", "#organizeSelected", "position", "organizeNodesSubMenu", "nodeToReview", "nodeToReviewNode", "#selectConnectedNodes", "#selectInputNodesAndDescendents", "CombineContextMenus", "inputs", "outputs", "unselectOthers", "#renderConnections", "portMousedOver", "#renderNodes", "selectedBox_Screenspace", "#boxSelectionScreenspaceBox", "state", "intersection", "nodeBounds", "BoxIntersection", "box", "SubVector2", "TimeExecution", "FormPopup", "config", "input", "setOption", "cancelOption", "Popup", "container", "i", "title", "ele", "button", "values", "MINIMUM_NODE_WIDTH", "MessageType", "MessageTypeColor", "messageType", "Theme", "NodeState", "MessageRenderer", "#text", "#alwaysShow", "config", "Text", "ctx", "scale", "position", "hovering", "FlowNode", "#position", "#title", "#subTitle", "#infoSymbol", "#infoText", "#messages", "#input", "#output", "#widgets", "#locked", "#canEditTitle", "#canEditInfo", "#canEditPorts", "#contextMenu", "#metadata", "#onSelect", "#onUnselect", "#onFiledrop", "#onDragStop", "#titleChangeCallback", "#infoChangeCallback", "#titleColor", "#selectedStyle", "#stateStyles", "#padding", "#portTextStyle", "#elementSpacing", "#selected", "#inputPortPositions", "#outputPortPositions", "#widgetPositions", "#data", "#registeredAnyPropertyChangeCallbacks", "#registeredPropertyChangeCallbacks", "List", "i", "message", "TextStyleFallback", "BoxStyle", "BoxStyleWithFallback", "TextStyle", "widget", "GlobalWidgetFactory", "callback", "name", "callbacks", "value", "oldValue", "#popupNodeTitleSelection", "SetStringPopup", "#popupNodeInfoSelection", "#popupNewButtonWidget", "ButtonWidget", "#widgetSubmenu", "NumberWidget", "ColorWidget", "FormPopup", "data", "SliderWidget", "StringWidget", "ToggleWidget", "ImageWidget", "nodeFlowGroup", "items", "submenus", "CombineContextMenus", "file", "CopyVector2", "camera", "tempMeasurement", "Zero", "doublePadding", "screenSpacePosition", "size", "subtitleSize", "port", "eleSize", "ScaleVector", "Port", "index", "delta", "intersection", "box", "InBox", "newTitle", "cleaned", "old", "newInfo", "#calculateStyle", "state", "boxStyle", "mousePosition", "postProcess", "VectorPool", "scaledPadding", "scaledElementSpacing", "nodeBounds", "nodeStyle", "borderSize", "titleSize", "titleBoxSize", "titleX", "titleY", "titleWidth", "titleHeight", "titlePosition", "subtitlePosition", "infoRadius", "centerX", "centerY", "infoPosition", "infoLineThickness", "Distance", "infoBoxWidth", "textEntries", "splitStringIntoLines", "lineHeight", "infoBoxHeight", "scaledLineHeight", "start", "entry", "startY", "leftSide", "rightSide", "widgetSize", "scaledWidgetWidth", "messageStart", "MarkdownToken", "#type", "#lexeme", "#tokenStart", "#tokenEnd", "type", "lexeme", "tokenStart", "tokenEnd", "MarkdownLexicalParser", "#body", "#index", "#tokens", "body", "#current", "#inc", "#next", "#lastToken", "#addToken", "token", "lexeme", "MarkdownToken", "#h2", "#h1", "#whiteSpace", "char", "#text", "started", "CodeBlockEntry", "#text", "#calculatedPositions", "#calculatedEntries", "#calculatedForWidth", "text", "List", "event", "#calculateLayout", "ctx", "maxWidth", "adjustedWith", "Theme", "curHeight", "lineInc", "entries", "entryIndex", "lines", "lineIndex", "position", "scale", "padding", "max", "i", "pos", "y", "entry", "UnorderedListMarkdownEntry", "#entries", "offset", "shift", "dot", "BasicMarkdownEntry", "#underline", "#background", "underline", "background", "curPosition", "Zero", "texSize", "currentLineHeight", "currentLineText", "currentLineWidths", "MarkdownSyntaxParser", "#tokens", "#index", "#originalText", "originalText", "tokens", "#current", "#inc", "#next", "#peak", "#peakInto", "amount", "#emphasis", "token", "Text", "bold", "textContent", "boldClosed", "startingClose", "validClose", "style", "#text", "contents", "starText", "i", "#h1", "text", "Theme", "BasicMarkdownEntry", "#h2", "#h3", "#starLineStart", "starEntries", "#assignStandardStyling", "entries", "UnorderedListMarkdownEntry", "textEntries", "#backtickLineStart", "start", "end", "codeBlockText", "entryText", "CodeBlockEntry", "BuildMarkdown", "data", "lexicalParser", "MarkdownLexicalParser", "MarkdownSyntaxParser", "BOUNDS_SPACING", "BOX_SIZE", "FlowNote", "#originalText", "#document", "#width", "#edittingStyle", "#data", "#position", "#handleSelected", "#edittingLayout", "#lastRenderedBox", "#hovering", "#widthChangeCallbacks", "#contentChangeCallbacks", "config", "BoxStyle", "text", "BuildMarkdown", "i", "name", "value", "delta", "position", "CopyVector2", "handle", "#tempPosition", "Zero", "newWidth", "callback", "ctx", "camera", "mousePosition", "leftPosition", "scaledWidth", "rightPosition", "left", "right", "bottom", "top", "startY", "lineSpacing", "Theme", "hovering", "input", "saveText", "Popup", "container", "button", "NoteSubsystem", "#notes", "#noteHovering", "#noteSelected", "#hoveringHandle", "#onNoteAddedCallbacks", "#onNoteRemovedCallbacks", "#onNoteDragStartCallbacks", "#onNoteDragStopCallbacks", "config", "i", "FlowNote", "note", "callback", "ctx", "position", "group", "result", "noteToReview", "mousePosition", "camera", "ctrlKey", "delta", "scale", "file", "index", "noteRemoved", "notes", "j", "InBox", "PassSubsystem", "#queue", "List", "lambda", "ctx", "camera", "mousePosition", "i", "position", "ctrlKey", "delta", "scale", "file", "QuickMenuGroup", "#text", "text", "items", "terms", "shouldRender", "kept", "QuickMenuItem", "#searchText", "#context", "searchText", "context", "i", "render", "highlight", "Theme", "RecurseBuildContainers", "path", "config", "renderElements", "groups", "currentPath", "titleText", "TextElement", "Text", "quickItems", "configItem", "itemText", "QuickMenu", "#menuGroups", "#container", "#currentSelection", "elements", "ContainerRenderElement", "#updateHighlighting", "selection", "groupIndex", "group", "itemIndex", "potentialTerms", "cleaned", "event", "intercepted", "ctx", "pos", "graphScale", "mousePosition", "BuildBackgroundRenderer", "backgroundColor", "canvas", "context", "position", "scale", "alpha", "Clamp01", "spacing", "pi2", "dotScale", "x", "xPos", "y", "yPos", "contextMenuGroup", "GraphView", "#subsystems", "subsystems", "mousePosition", "camera", "ctrlKey", "i", "file", "ctx", "finalConfig", "subSystemMenu", "CombineContextMenus", "delta", "results", "TimeExecution", "NodeFlowGraph", "#ctx", "#canvas", "#backgroundRenderer", "#contextMenuConfig", "#mousePosition", "#camera", "#openedContextMenu", "#openQuickMenu", "#contextMenuEntryHovering", "#views", "#currentView", "#mainNodeSubsystem", "#mainNoteSubsystem", "config", "postProcessPass", "PassSubsystem", "NodeSubsystem", "#lastFrameCursor", "#cursor", "NoteSubsystem", "Camera", "Theme", "#render", "event", "MouseObserver", "#mouseDragEvent", "#clickStart", "#clickEnd", "#openContextMenu", "#fileDrop", "e", "contextMenuPosition", "#sceenPositionToGraphPosition", "items", "QuickMenu", "contents", "extension", "pos", "Zero", "CopyVector2", "FlowNode", "callback", "amount", "oldPos", "newPos", "identifier", "publisher", "nodeIndex", "nodeOut", "outPort", "nodeIn", "inPort", "node", "note", "screenPosition", "out", "ContextMenu", "rect", "#renderBackground", "#renderContextMenu", "#renderQuickMenu", "VectorPool"]
7
+ }