diff --git a/src/lib/litegraph/src/LGraphCanvas.ts b/src/lib/litegraph/src/LGraphCanvas.ts
index dd2a78bb9..85187cdb3 100644
--- a/src/lib/litegraph/src/LGraphCanvas.ts
+++ b/src/lib/litegraph/src/LGraphCanvas.ts
@@ -2801,7 +2801,7 @@ export class LGraphCanvas
// Widget
const widget = node.getWidgetOnPos(x, y)
if (widget) {
- this.#processWidgetClick(e, node, widget)
+ this.processWidgetClick(e, node, widget)
this.node_widget = [node, widget]
} else {
// Node background
@@ -2981,13 +2981,12 @@ export class LGraphCanvas
this.dirty_canvas = true
}
- #processWidgetClick(
+ processWidgetClick(
e: CanvasPointerEvent,
node: LGraphNode,
- widget: IBaseWidget
+ widget: IBaseWidget,
+ pointer = this.pointer
) {
- const { pointer } = this
-
// Custom widget - CanvasPointer
if (typeof widget.onPointerDown === 'function') {
const handled = widget.onPointerDown(pointer, node, this)
diff --git a/src/lib/litegraph/src/types/widgets.ts b/src/lib/litegraph/src/types/widgets.ts
index 02111acef..2d2ceb103 100644
--- a/src/lib/litegraph/src/types/widgets.ts
+++ b/src/lib/litegraph/src/types/widgets.ts
@@ -363,6 +363,14 @@ export interface IBaseWidget<
lowQuality?: boolean
): void
+ /**
+ * Compatibility method for widgets implementing the draw
+ * method when displayed in non-canvas renderers.
+ * Set by the current renderer implementation.
+ * When called, performs a draw operation.
+ */
+ triggerDraw?: () => void
+
/**
* Compute the size of the widget. Overrides {@link IBaseWidget.computeSize}.
* @param width The width of the widget.
diff --git a/src/renderer/extensions/vueNodes/components/NodeWidgets.vue b/src/renderer/extensions/vueNodes/components/NodeWidgets.vue
index 312c9300b..c36a232c7 100644
--- a/src/renderer/extensions/vueNodes/components/NodeWidgets.vue
+++ b/src/renderer/extensions/vueNodes/components/NodeWidgets.vue
@@ -24,7 +24,7 @@
+import { useResizeObserver } from '@vueuse/core'
+import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
+
+import { useChainCallback } from '@/composables/functional/useChainCallback'
+import { CanvasPointer } from '@/lib/litegraph/src/CanvasPointer'
+import type { LGraphCanvas } from '@/lib/litegraph/src/LGraphCanvas'
+import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
+import type { CanvasPointerEvent } from '@/lib/litegraph/src/types/events'
+import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
+import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
+import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
+import type { SimplifiedWidget } from '@/types/simplifiedWidget'
+
+const props = defineProps<{
+ widget: SimplifiedWidget
+ readonly?: boolean
+}>()
+
+const canvasEl = ref()
+
+const canvas: LGraphCanvas = useCanvasStore().canvas as LGraphCanvas
+let node: LGraphNode | undefined
+let widgetInstance: IBaseWidget | undefined
+let pointer: CanvasPointer | undefined
+const scaleFactor = 2
+
+onMounted(() => {
+ node =
+ canvas?.graph?.getNodeById(
+ canvasEl.value.parentElement.attributes['node-id'].value
+ ) ?? undefined
+ if (!node) return
+ widgetInstance = node.widgets?.find((w) => w.name === props.widget.name)
+ if (!widgetInstance) return
+ canvasEl.value.width *= scaleFactor
+ if (!widgetInstance.triggerDraw)
+ widgetInstance.callback = useChainCallback(
+ widgetInstance.callback,
+ function (this: IBaseWidget) {
+ this?.triggerDraw?.()
+ }
+ )
+ widgetInstance.triggerDraw = draw
+ useResizeObserver(canvasEl.value.parentElement, draw)
+ watch(() => useColorPaletteStore().activePaletteId, draw)
+ pointer = new CanvasPointer(canvasEl.value)
+})
+onBeforeUnmount(() => {
+ if (widgetInstance) widgetInstance.triggerDraw = () => {}
+})
+
+function draw() {
+ if (!widgetInstance || !node) return
+ const width = canvasEl.value.parentElement.clientWidth
+ const height = widgetInstance.computeSize
+ ? widgetInstance.computeSize(width)[1]
+ : 20
+ widgetInstance.y = 0
+ canvasEl.value.height = (height + 2) * scaleFactor
+ canvasEl.value.width = width * scaleFactor
+ const ctx = canvasEl.value?.getContext('2d')
+ if (!ctx) return
+ ctx.scale(scaleFactor, scaleFactor)
+ widgetInstance.draw?.(ctx, node, width, 1, height)
+}
+function translateEvent(e: PointerEvent): asserts e is CanvasPointerEvent {
+ if (!node) return
+ canvas.adjustMouseEvent(e)
+ canvas.graph_mouse[0] = e.offsetX + node.pos[0]
+ canvas.graph_mouse[1] = e.offsetY + node.pos[1]
+}
+//See LGraphCanvas.processWidgetClick
+function handleDown(e: PointerEvent) {
+ if (!node || !widgetInstance || !pointer) return
+ translateEvent(e)
+ pointer.down(e)
+ if (widgetInstance.mouse)
+ pointer.onDrag = (e) =>
+ widgetInstance!.mouse?.(e, [e.offsetX, e.offsetY], node!)
+ //NOTE: a mouseUp event is already registed under pointer.finally
+ canvas.processWidgetClick(e, node, widgetInstance, pointer)
+}
+function handleUp(e: PointerEvent) {
+ if (!pointer) return
+ translateEvent(e)
+ e.click_time = e.timeStamp - (pointer?.eDown?.timeStamp ?? 0)
+ pointer.up(e)
+}
+function handleMove(e: PointerEvent) {
+ if (!pointer) return
+ translateEvent(e)
+ pointer.move(e)
+}
+
+
+
+
+
+
diff --git a/src/renderer/extensions/vueNodes/widgets/registry/widgetRegistry.ts b/src/renderer/extensions/vueNodes/widgets/registry/widgetRegistry.ts
index 6cab2dbdd..7c48b1f1e 100644
--- a/src/renderer/extensions/vueNodes/widgets/registry/widgetRegistry.ts
+++ b/src/renderer/extensions/vueNodes/widgets/registry/widgetRegistry.ts
@@ -14,6 +14,7 @@ import WidgetGalleria from '../components/WidgetGalleria.vue'
import WidgetImageCompare from '../components/WidgetImageCompare.vue'
import WidgetInputNumber from '../components/WidgetInputNumber.vue'
import WidgetInputText from '../components/WidgetInputText.vue'
+import WidgetLegacy from '../components/WidgetLegacy.vue'
import WidgetMarkdown from '../components/WidgetMarkdown.vue'
import WidgetMultiSelect from '../components/WidgetMultiSelect.vue'
import WidgetRecordAudio from '../components/WidgetRecordAudio.vue'
@@ -114,6 +115,7 @@ const coreWidgetDefinitions: Array<[string, WidgetDefinition]> = [
'markdown',
{ component: WidgetMarkdown, aliases: ['MARKDOWN'], essential: false }
],
+ ['legacy', { component: WidgetLegacy, aliases: [], essential: true }],
[
'audiorecord',
{
@@ -161,19 +163,11 @@ export const getComponent = (type: string, name: string): Component | null => {
return widgets.get(canonicalType)?.component || null
}
-const isSupported = (type: string): boolean => {
- const canonicalType = getCanonicalType(type)
- return widgets.has(canonicalType)
-}
-
export const isEssential = (type: string): boolean => {
const canonicalType = getCanonicalType(type)
return widgets.get(canonicalType)?.essential || false
}
export const shouldRenderAsVue = (widget: Partial): boolean => {
- if (widget.options?.canvasOnly) return false
- if (widget.isDOMWidget) return true
- if (!widget.type) return false
- return isSupported(widget.type)
+ return !widget.options?.canvasOnly && !!widget.type
}
diff --git a/tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useWidgetRenderer.test.ts b/tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useWidgetRenderer.test.ts
index 773ed8364..7c1d2dd5d 100644
--- a/tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useWidgetRenderer.test.ts
+++ b/tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useWidgetRenderer.test.ts
@@ -123,10 +123,6 @@ describe('widgetRegistry', () => {
expect(shouldRenderAsVue({ type: 'combo' })).toBe(true)
})
- it('should return false for unknown types', () => {
- expect(shouldRenderAsVue({ type: 'unknown_type' })).toBe(false)
- })
-
it('should respect options while checking type', () => {
const widget = { type: 'text', options: { someOption: 'value' } }
expect(shouldRenderAsVue(widget)).toBe(true)