mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 03:01:54 +00:00
Implement TextWidget (#484)
This commit is contained in:
@@ -71,6 +71,7 @@ import { NodeInputSlot, NodeOutputSlot, type ConnectionColorContext } from "./No
|
|||||||
import { ComboWidget } from "./widgets/ComboWidget"
|
import { ComboWidget } from "./widgets/ComboWidget"
|
||||||
import { NumberWidget } from "./widgets/NumberWidget"
|
import { NumberWidget } from "./widgets/NumberWidget"
|
||||||
import { ButtonWidget } from "./widgets/ButtonWidget"
|
import { ButtonWidget } from "./widgets/ButtonWidget"
|
||||||
|
import { TextWidget } from "./widgets/TextWidget"
|
||||||
|
|
||||||
interface IShowSearchOptions {
|
interface IShowSearchOptions {
|
||||||
node_to?: LGraphNode
|
node_to?: LGraphNode
|
||||||
@@ -2625,13 +2626,11 @@ export class LGraphCanvas implements ConnectionColorContext {
|
|||||||
break
|
break
|
||||||
case "string":
|
case "string":
|
||||||
case "text":
|
case "text":
|
||||||
pointer.onClick = () => this.prompt(
|
pointer.onClick = () => toClass(TextWidget, widget).onClick({
|
||||||
"Value",
|
|
||||||
widget.value,
|
|
||||||
(v: any) => setWidgetValue(this, node, widget, v),
|
|
||||||
e,
|
e,
|
||||||
widget.options ? widget.options.multiline : false,
|
node,
|
||||||
)
|
canvas: this,
|
||||||
|
})
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
// Legacy custom widget callback
|
// Legacy custom widget callback
|
||||||
@@ -5898,36 +5897,7 @@ export class LGraphCanvas implements ConnectionColorContext {
|
|||||||
break
|
break
|
||||||
case "string":
|
case "string":
|
||||||
case "text":
|
case "text":
|
||||||
ctx.textAlign = "left"
|
toClass(TextWidget, w).drawWidget(ctx, { y, width: widget_width, show_text, margin })
|
||||||
ctx.strokeStyle = outline_color
|
|
||||||
ctx.fillStyle = background_color
|
|
||||||
ctx.beginPath()
|
|
||||||
|
|
||||||
if (show_text)
|
|
||||||
ctx.roundRect(margin, y, widget_width - margin * 2, H, [H * 0.5])
|
|
||||||
else
|
|
||||||
ctx.rect(margin, y, widget_width - margin * 2, H)
|
|
||||||
ctx.fill()
|
|
||||||
if (show_text) {
|
|
||||||
if (!w.disabled) ctx.stroke()
|
|
||||||
ctx.save()
|
|
||||||
ctx.beginPath()
|
|
||||||
ctx.rect(margin, y, widget_width - margin * 2, H)
|
|
||||||
ctx.clip()
|
|
||||||
|
|
||||||
// ctx.stroke();
|
|
||||||
ctx.fillStyle = secondary_text_color
|
|
||||||
const label = w.label || w.name
|
|
||||||
if (label != null) ctx.fillText(label, margin * 2, y + H * 0.7)
|
|
||||||
ctx.fillStyle = text_color
|
|
||||||
ctx.textAlign = "right"
|
|
||||||
ctx.fillText(
|
|
||||||
String(w.value).substr(0, 30),
|
|
||||||
widget_width - margin * 2,
|
|
||||||
y + H * 0.7,
|
|
||||||
) // 30 chars max
|
|
||||||
ctx.restore()
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
// Custom widgets
|
// Custom widgets
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import { ComboWidget } from "./widgets/ComboWidget"
|
|||||||
import { NumberWidget } from "./widgets/NumberWidget"
|
import { NumberWidget } from "./widgets/NumberWidget"
|
||||||
import { ButtonWidget } from "./widgets/ButtonWidget"
|
import { ButtonWidget } from "./widgets/ButtonWidget"
|
||||||
import { NodeInputSlot, NodeOutputSlot } from "./NodeSlot"
|
import { NodeInputSlot, NodeOutputSlot } from "./NodeSlot"
|
||||||
|
import { TextWidget } from "./widgets/TextWidget"
|
||||||
|
|
||||||
export type NodeId = number | string
|
export type NodeId = number | string
|
||||||
|
|
||||||
@@ -1683,6 +1684,10 @@ export class LGraphNode implements Positionable, IPinnable {
|
|||||||
case "button":
|
case "button":
|
||||||
widget = new ButtonWidget(custom_widget)
|
widget = new ButtonWidget(custom_widget)
|
||||||
break
|
break
|
||||||
|
case "text":
|
||||||
|
case "string":
|
||||||
|
widget = new TextWidget(custom_widget)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
widget = custom_widget
|
widget = custom_widget
|
||||||
}
|
}
|
||||||
|
|||||||
101
src/widgets/TextWidget.ts
Normal file
101
src/widgets/TextWidget.ts
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import type { IStringWidget, IWidgetOptions } from "@/types/widgets"
|
||||||
|
import { BaseWidget } from "./BaseWidget"
|
||||||
|
import type { LGraphNode } from "@/LGraphNode"
|
||||||
|
import type { CanvasMouseEvent } from "@/types/events"
|
||||||
|
import type { LGraphCanvas } from "@/LGraphCanvas"
|
||||||
|
|
||||||
|
export class TextWidget extends BaseWidget implements IStringWidget {
|
||||||
|
// IStringWidget properties
|
||||||
|
declare type: "text" | "string"
|
||||||
|
declare value: string
|
||||||
|
declare options: IWidgetOptions<string>
|
||||||
|
|
||||||
|
constructor(widget: IStringWidget) {
|
||||||
|
super(widget)
|
||||||
|
this.type = widget.type as "text" | "string"
|
||||||
|
this.value = widget.value?.toString() ?? ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the widget
|
||||||
|
* @param ctx - The canvas context
|
||||||
|
* @param options - The options for drawing the widget
|
||||||
|
*/
|
||||||
|
override drawWidget(ctx: CanvasRenderingContext2D, options: {
|
||||||
|
y: number
|
||||||
|
width: number
|
||||||
|
show_text?: boolean
|
||||||
|
margin?: number
|
||||||
|
}) {
|
||||||
|
// Store original context attributes
|
||||||
|
const originalTextAlign = ctx.textAlign
|
||||||
|
const originalStrokeStyle = ctx.strokeStyle
|
||||||
|
const originalFillStyle = ctx.fillStyle
|
||||||
|
|
||||||
|
const { y, width, show_text = true, margin = 15 } = options
|
||||||
|
const widget_width = width
|
||||||
|
const H = this.height
|
||||||
|
|
||||||
|
ctx.textAlign = "left"
|
||||||
|
ctx.strokeStyle = this.outline_color
|
||||||
|
ctx.fillStyle = this.background_color
|
||||||
|
ctx.beginPath()
|
||||||
|
|
||||||
|
if (show_text)
|
||||||
|
ctx.roundRect(margin, y, widget_width - margin * 2, H, [H * 0.5])
|
||||||
|
else
|
||||||
|
ctx.rect(margin, y, widget_width - margin * 2, H)
|
||||||
|
ctx.fill()
|
||||||
|
|
||||||
|
if (show_text) {
|
||||||
|
if (!this.disabled) ctx.stroke()
|
||||||
|
ctx.save()
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.rect(margin, y, widget_width - margin * 2, H)
|
||||||
|
ctx.clip()
|
||||||
|
|
||||||
|
// Draw label
|
||||||
|
ctx.fillStyle = this.secondary_text_color
|
||||||
|
const label = this.label || this.name
|
||||||
|
if (label != null) {
|
||||||
|
ctx.fillText(label, margin * 2, y + H * 0.7)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw value
|
||||||
|
ctx.fillStyle = this.text_color
|
||||||
|
ctx.textAlign = "right"
|
||||||
|
ctx.fillText(
|
||||||
|
String(this.value).substr(0, 30), // 30 chars max
|
||||||
|
widget_width - margin * 2,
|
||||||
|
y + H * 0.7,
|
||||||
|
)
|
||||||
|
ctx.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore original context attributes
|
||||||
|
ctx.textAlign = originalTextAlign
|
||||||
|
ctx.strokeStyle = originalStrokeStyle
|
||||||
|
ctx.fillStyle = originalFillStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
override onClick(options: {
|
||||||
|
e: CanvasMouseEvent
|
||||||
|
node: LGraphNode
|
||||||
|
canvas: LGraphCanvas
|
||||||
|
}) {
|
||||||
|
const { e, node, canvas } = options
|
||||||
|
|
||||||
|
// Show prompt dialog for text input
|
||||||
|
canvas.prompt(
|
||||||
|
"Value",
|
||||||
|
this.value,
|
||||||
|
(v: string) => {
|
||||||
|
if (v !== null) {
|
||||||
|
this.setValue(v, { e, node, canvas })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
e,
|
||||||
|
this.options?.multiline ?? false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user