From 4d36369cd8dd228dc8686bb33195e83d4ef22b70 Mon Sep 17 00:00:00 2001 From: Chenlei Hu Date: Sat, 8 Feb 2025 19:28:38 -0500 Subject: [PATCH] Refactor widget switch statement (#491) --- src/LGraphCanvas.ts | 129 +++++--------------------------------- src/LGraphNode.ts | 42 ++----------- src/widgets/BaseWidget.ts | 4 +- src/widgets/widgetMap.ts | 23 +++++++ 4 files changed, 45 insertions(+), 153 deletions(-) create mode 100644 src/widgets/widgetMap.ts diff --git a/src/LGraphCanvas.ts b/src/LGraphCanvas.ts index a0177c584..0fdb3d0d4 100644 --- a/src/LGraphCanvas.ts +++ b/src/LGraphCanvas.ts @@ -22,7 +22,7 @@ import type { ReadOnlyPoint, ReadOnlyRect, } from "./interfaces" -import type { IWidget, TWidgetValue } from "./types/widgets" +import type { IBaseWidget, IWidget, TWidgetValue } from "./types/widgets" import { LGraphNode, type NodeId } from "./LGraphNode" import type { CanvasDragEvent, @@ -73,6 +73,8 @@ import { NumberWidget } from "./widgets/NumberWidget" import { ButtonWidget } from "./widgets/ButtonWidget" import { TextWidget } from "./widgets/TextWidget" import { SliderWidget } from "./widgets/SliderWidget" +import { BaseWidget } from "./widgets/BaseWidget" +import { WIDGET_TYPE_MAP } from "./widgets/widgetMap" interface IShowSearchOptions { node_to?: LGraphNode @@ -2556,88 +2558,29 @@ export class LGraphCanvas implements ConnectionColorContext { if (handled) return } - const width = widget.width || node.width - const oldValue = widget.value const pos = this.graph_mouse const x = pos[0] - node.pos[0] const y = pos[1] - node.pos[1] - switch (widget.type) { - case "button": - pointer.onClick = () => { - toClass(ButtonWidget, widget).onClick({ - e, - node, - canvas: this, - }) - } - break - case "slider": { - pointer.onClick = () => toClass(SliderWidget, widget).onClick({ + const WidgetClass = WIDGET_TYPE_MAP[widget.type] + if (WidgetClass) { + const widgetInstance = toClass(WidgetClass, widget) + pointer.onClick = () => widgetInstance.onClick({ e, node, canvas: this, }) - pointer.onDrag = eMove => toClass(SliderWidget, widget).onDrag({ + pointer.onDrag = eMove => widgetInstance.onDrag({ e: eMove, node, }) - break - } - case "number": { - const numberWidget = toClass(NumberWidget, widget) - pointer.onClick = () => { - numberWidget.onClick({ - e, - node, - canvas: this, - }) - } - // Click & drag from widget centre area - pointer.onDrag = (eMove) => { - numberWidget.onDrag({ - e: eMove, - node, - }) - } - break - } - case "combo": { - pointer.onClick = () => { - toClass(ComboWidget, widget).onClick({ - e, - node, - canvas: this, - }) - } - break - } - case "toggle": - pointer.onClick = () => { - toClass(BooleanWidget, widget).onClick({ - e, - node, - canvas: this, - }) - } - break - case "string": - case "text": - pointer.onClick = () => toClass(TextWidget, widget).onClick({ - e, - node, - canvas: this, - }) - break - default: - // Legacy custom widget callback + } else { if (widget.mouse) { const result = widget.mouse(e, [x, y], node) if (result != null) this.dirty_canvas = result } - break } // value changed @@ -2657,26 +2600,6 @@ export class LGraphCanvas implements ConnectionColorContext { this.node_widget = null } - - function setWidgetValue( - canvas: LGraphCanvas, - node: LGraphNode, - widget: IWidget, - value: TWidgetValue, - ) { - const v = widget.type === "number" ? Number(value) : value - widget.value = v - if ( - widget.options?.property && - node.properties[widget.options.property] !== undefined - ) { - node.setProperty(widget.options.property, v) - } - widget.callback?.(widget.value, canvas, node, pos, e) - - node.onWidgetChanged?.(widget.name, v, oldValue, widget) - node.graph._version++ - } } /** @@ -5809,13 +5732,9 @@ export class LGraphCanvas implements ConnectionColorContext { const show_text = !this.low_quality ctx.save() ctx.globalAlpha = this.editor_alpha - const background_color = LiteGraph.WIDGET_BGCOLOR - const text_color = LiteGraph.WIDGET_TEXT_COLOR - const secondary_text_color = LiteGraph.WIDGET_SECONDARY_TEXT_COLOR const margin = 15 - for (let i = 0; i < widgets.length; ++i) { - const w = widgets[i] + for (const w of widgets) { if (w.hidden || (w.advanced && !node.showAdvanced)) continue const y = w.y || posY const outline_color = w.advanced ? LiteGraph.WIDGET_ADVANCED_OUTLINE_COLOR : LiteGraph.WIDGET_OUTLINE_COLOR @@ -5833,34 +5752,14 @@ export class LGraphCanvas implements ConnectionColorContext { ctx.strokeStyle = outline_color ctx.fillStyle = "#222" ctx.textAlign = "left" - // ctx.lineWidth = 2; if (w.disabled) ctx.globalAlpha *= 0.5 const widget_width = w.width || width - switch (w.type) { - case "button": - toClass(ButtonWidget, w).drawWidget(ctx, { y, width: widget_width, show_text, margin }) - break - case "toggle": - toClass(BooleanWidget, w).drawWidget(ctx, { y, width: widget_width, show_text, margin }) - break - case "slider": - toClass(SliderWidget, w).drawWidget(ctx, { y, width: widget_width, show_text, margin }) - break - case "combo": - toClass(ComboWidget, w).drawWidget(ctx, { y, width: widget_width, show_text, margin }) - break - case "number": - toClass(NumberWidget, w).drawWidget(ctx, { y, width: widget_width, show_text, margin }) - break - case "string": - case "text": - toClass(TextWidget, w).drawWidget(ctx, { y, width: widget_width, show_text, margin }) - break - // Custom widgets - default: + const WidgetClass = WIDGET_TYPE_MAP[w.type] + if (WidgetClass) { + toClass(WidgetClass, w).drawWidget(ctx, { y, width: widget_width, show_text, margin }) + } else { w.draw?.(ctx, node, widget_width, y, H) - break } posY += (w.computeSize ? w.computeSize(widget_width)[1] : H) + 4 ctx.globalAlpha = this.editor_alpha diff --git a/src/LGraphNode.ts b/src/LGraphNode.ts index 1bda43142..ac78c38ca 100644 --- a/src/LGraphNode.ts +++ b/src/LGraphNode.ts @@ -16,7 +16,7 @@ import type { Size, } from "./interfaces" import type { LGraph } from "./LGraph" -import type { IWidget, TWidgetValue } from "./types/widgets" +import type { IWidget, TWidgetType, TWidgetValue } from "./types/widgets" import type { ISerialisedNode } from "./types/serialisation" import type { LGraphCanvas } from "./LGraphCanvas" import type { CanvasMouseEvent } from "./types/events" @@ -32,14 +32,8 @@ import { BadgePosition, LGraphBadge } from "./LGraphBadge" import { type LGraphNodeConstructor, LiteGraph } from "./litegraph" import { isInRectangle, isInRect, snapPoint } from "./measure" import { LLink } from "./LLink" -import { BooleanWidget } from "./widgets/BooleanWidget" -import { ComboWidget } from "./widgets/ComboWidget" -import { NumberWidget } from "./widgets/NumberWidget" -import { ButtonWidget } from "./widgets/ButtonWidget" import { NodeInputSlot, NodeOutputSlot } from "./NodeSlot" -import { TextWidget } from "./widgets/TextWidget" -import { SliderWidget } from "./widgets/SliderWidget" - +import { WIDGET_TYPE_MAP } from "./widgets/widgetMap" export type NodeId = number | string export interface INodePropertyInfo { @@ -1668,36 +1662,12 @@ export class LGraphNode implements Positionable, IPinnable { return widget } - addCustomWidget(custom_widget: IWidget): IWidget { + addCustomWidget(custom_widget: T): T { this.widgets ||= [] - - let widget: IWidget - switch (custom_widget.type) { - case "toggle": - widget = new BooleanWidget(custom_widget) - break - case "combo": - widget = new ComboWidget(custom_widget) - break - case "number": - widget = new NumberWidget(custom_widget) - break - case "button": - widget = new ButtonWidget(custom_widget) - break - case "text": - case "string": - widget = new TextWidget(custom_widget) - break - case "slider": - widget = new SliderWidget(custom_widget) - break - default: - widget = custom_widget - } - + const WidgetClass = WIDGET_TYPE_MAP[custom_widget.type] + const widget = WidgetClass ? new WidgetClass(custom_widget) as IWidget : custom_widget this.widgets.push(widget) - return widget + return widget as T } move(deltaX: number, deltaY: number): void { diff --git a/src/widgets/BaseWidget.ts b/src/widgets/BaseWidget.ts index 036846f57..f6c9b959a 100644 --- a/src/widgets/BaseWidget.ts +++ b/src/widgets/BaseWidget.ts @@ -2,7 +2,7 @@ import { Point } from "@/interfaces" import { LiteGraph } from "@/litegraph" import type { CanvasPointer, LGraphCanvas, LGraphNode, Size } from "@/litegraph" import type { CanvasMouseEvent, CanvasPointerEvent } from "@/types/events" -import type { IBaseWidget, IWidget, IWidgetOptions, TWidgetValue } from "@/types/widgets" +import type { IBaseWidget, IWidget, IWidgetOptions, TWidgetType, TWidgetValue } from "@/types/widgets" export abstract class BaseWidget implements IBaseWidget { linkedWidgets?: IWidget[] @@ -11,7 +11,7 @@ export abstract class BaseWidget implements IBaseWidget { label?: string clicked?: boolean name?: string - type?: "string" | "number" | "combo" | "button" | "toggle" | "slider" | "text" | "multiline" | "custom" + type?: TWidgetType value?: TWidgetValue y?: number last_y?: number diff --git a/src/widgets/widgetMap.ts b/src/widgets/widgetMap.ts new file mode 100644 index 000000000..12758d22c --- /dev/null +++ b/src/widgets/widgetMap.ts @@ -0,0 +1,23 @@ +// @ts-strict-ignore +import type { IBaseWidget } from "@/types/widgets" +import { BooleanWidget } from "./BooleanWidget" +import { ButtonWidget } from "./ButtonWidget" +import { ComboWidget } from "./ComboWidget" +import { NumberWidget } from "./NumberWidget" +import { SliderWidget } from "./SliderWidget" +import { TextWidget } from "./TextWidget" +import { BaseWidget } from "./BaseWidget" + +type WidgetConstructor = { + new (plain: IBaseWidget): BaseWidget +} + +export const WIDGET_TYPE_MAP: Record = { + button: ButtonWidget, + toggle: BooleanWidget, + slider: SliderWidget, + combo: ComboWidget, + number: NumberWidget, + string: TextWidget, + text: TextWidget, +}