Overhaul node computeSize - use actual text width (#962)

### Node resize overhaul

- Precisely calculates node minimum size
- Prevents input & output overlap
- Prevents (normal*) widgets from rendering text over the edge of nodes
- Performance impact was sub-millisecond for normal usage in a 500-node
graph


![image](https://github.com/user-attachments/assets/5b6a6cc7-a752-4d7e-bcdf-b4bc8df26c51)

_Minimum size for a few example node configurations_

### Widgets

- Converts hard-coded draw render values to class static properties
- Adds widget button draw function for left/right arrow widgets

_*_ Exception: `control_after_generate`, as it is not a true input /
widget. A check may be added later to handle this special case.
This commit is contained in:
filtered
2025-04-25 00:31:34 +10:00
committed by GitHub
parent 79ce3199d4
commit 080a8da8f4
10 changed files with 97 additions and 52 deletions

View File

@@ -13,6 +13,15 @@ export interface DrawWidgetOptions {
}
export abstract class BaseWidget implements IBaseWidget {
/** From node edge to widget edge */
static margin = 15
/** From widget edge to tip of arrow button */
static arrowMargin = 6
/** Arrow button width */
static arrowWidth = 10
/** Absolute minimum display width of widget values */
static minValueWidth = 42
linkedWidgets?: IWidget[]
name: string
options: IWidgetOptions<unknown>
@@ -82,6 +91,28 @@ export abstract class BaseWidget implements IBaseWidget {
*/
abstract drawWidget(ctx: CanvasRenderingContext2D, options: DrawWidgetOptions): void
drawArrowButtons(ctx: CanvasRenderingContext2D, margin: number, y: number, width: number) {
const { height } = this
const { arrowMargin, arrowWidth } = BaseWidget
const arrowTipX = margin + arrowMargin
const arrowInnerX = arrowTipX + arrowWidth
// Draw left arrow
ctx.fillStyle = this.text_color
ctx.beginPath()
ctx.moveTo(arrowInnerX, y + 5)
ctx.lineTo(arrowTipX, y + height * 0.5)
ctx.lineTo(arrowInnerX, y + height - 5)
ctx.fill()
// Draw right arrow
ctx.beginPath()
ctx.moveTo(width - arrowInnerX, y + 5)
ctx.lineTo(width - arrowTipX, y + height * 0.5)
ctx.lineTo(width - arrowInnerX, y + height - 5)
ctx.fill()
}
/**
* Handles the click event for the widget
* @param options The options for handling the click event

View File

@@ -20,7 +20,7 @@ export class BooleanWidget extends BaseWidget implements IBooleanWidget {
y,
width,
show_text = true,
margin = 15,
margin = BaseWidget.margin,
}: DrawWidgetOptions) {
const { height } = this

View File

@@ -27,7 +27,7 @@ export class ButtonWidget extends BaseWidget implements IButtonWidget {
y,
width,
show_text = true,
margin = 15,
margin = BaseWidget.margin,
}: DrawWidgetOptions) {
// Store original context attributes
const originalTextAlign = ctx.textAlign

View File

@@ -28,7 +28,7 @@ export class ComboWidget extends BaseWidget implements IComboWidget {
y,
width,
show_text = true,
margin = 15,
margin = BaseWidget.margin,
}: DrawWidgetOptions) {
// Store original context attributes
const originalTextAlign = ctx.textAlign
@@ -51,19 +51,7 @@ export class ComboWidget extends BaseWidget implements IComboWidget {
if (show_text) {
if (!this.computedDisabled) {
ctx.stroke()
// Draw left arrow
ctx.fillStyle = this.text_color
ctx.beginPath()
ctx.moveTo(margin + 16, y + 5)
ctx.lineTo(margin + 6, y + height * 0.5)
ctx.lineTo(margin + 16, y + height - 5)
ctx.fill()
// Draw right arrow
ctx.beginPath()
ctx.moveTo(width - margin - 16, y + 5)
ctx.lineTo(width - margin - 6, y + height * 0.5)
ctx.lineTo(width - margin - 16, y + height - 5)
ctx.fill()
this.drawArrowButtons(ctx, margin, y, width)
}
// Draw label

View File

@@ -49,7 +49,7 @@ export class KnobWidget extends BaseWidget implements IKnobWidget {
y,
width,
show_text = true,
margin = 15,
margin = BaseWidget.margin,
}: DrawWidgetOptions,
): void {
// Store original context attributes

View File

@@ -43,7 +43,7 @@ export class NumberWidget extends BaseWidget implements INumericWidget {
y,
width,
show_text = true,
margin = 15,
margin = BaseWidget.margin,
}: DrawWidgetOptions) {
// Store original context attributes
const originalTextAlign = ctx.textAlign
@@ -66,19 +66,7 @@ export class NumberWidget extends BaseWidget implements INumericWidget {
if (show_text) {
if (!this.computedDisabled) {
ctx.stroke()
// Draw left arrow
ctx.fillStyle = this.text_color
ctx.beginPath()
ctx.moveTo(margin + 16, y + 5)
ctx.lineTo(margin + 6, y + height * 0.5)
ctx.lineTo(margin + 16, y + height - 5)
ctx.fill()
// Draw right arrow
ctx.beginPath()
ctx.moveTo(width - margin - 16, y + 5)
ctx.lineTo(width - margin - 6, y + height * 0.5)
ctx.lineTo(width - margin - 16, y + height - 5)
ctx.fill()
this.drawArrowButtons(ctx, margin, y, width)
}
// Draw label

View File

@@ -31,7 +31,7 @@ export class SliderWidget extends BaseWidget implements ISliderWidget {
y,
width,
show_text = true,
margin = 15,
margin = BaseWidget.margin,
}: DrawWidgetOptions) {
// Store original context attributes
const originalTextAlign = ctx.textAlign

View File

@@ -26,7 +26,7 @@ export class TextWidget extends BaseWidget implements IStringWidget {
y,
width,
show_text = true,
margin = 15,
margin = BaseWidget.margin,
}: DrawWidgetOptions) {
// Store original context attributes
const originalTextAlign = ctx.textAlign