Missing?
This commit is contained in:
+219
-219
@@ -1,219 +1,219 @@
|
||||
// @ts-ignore
|
||||
import { app } from "../../scripts/app.js";
|
||||
import type {
|
||||
IWidget,
|
||||
LGraphNode,
|
||||
LiteGraph as TLiteGraph,
|
||||
LGraphCanvas as TLGraphCanvas,
|
||||
Vector2,
|
||||
} from "../typings/litegraph.js";
|
||||
import { drawNodeWidget, fitString, isLowQuality } from "./utils_canvas.js";
|
||||
|
||||
declare const LiteGraph: typeof TLiteGraph;
|
||||
|
||||
/**
|
||||
* Draws a label on teft, and a value on the right, ellipsizing when out of space.
|
||||
*/
|
||||
export function drawLabelAndValue(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
label: string,
|
||||
value: string,
|
||||
width: number,
|
||||
posY: number,
|
||||
height: number,
|
||||
options?: { offsetLeft: number },
|
||||
) {
|
||||
const outerMargin = 15;
|
||||
const innerMargin = 10;
|
||||
const midY = posY + height / 2;
|
||||
ctx.save();
|
||||
ctx.textAlign = "left";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle = LiteGraph.WIDGET_SECONDARY_TEXT_COLOR;
|
||||
const labelX = outerMargin + innerMargin + (options?.offsetLeft ?? 0);
|
||||
ctx.fillText(label, labelX, midY);
|
||||
|
||||
const valueXLeft = labelX + ctx.measureText(label).width + 7;
|
||||
const valueXRight = width - (outerMargin + innerMargin);
|
||||
|
||||
ctx.fillStyle = LiteGraph.WIDGET_TEXT_COLOR;
|
||||
ctx.textAlign = "right";
|
||||
ctx.fillText(fitString(ctx, value, valueXRight - valueXLeft), valueXRight, midY);
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* A better implementation of the LiteGraph text widget, including auto ellipsis.
|
||||
*/
|
||||
export class RgthreeBetterTextWidget implements IWidget<string> {
|
||||
name: string;
|
||||
value: string;
|
||||
|
||||
constructor(name: string, value: string) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D, node: LGraphNode, width: number, y: number, height: number) {
|
||||
const widgetData = drawNodeWidget(ctx, { width, height, posY: y });
|
||||
|
||||
if (!widgetData.lowQuality) {
|
||||
drawLabelAndValue(ctx, this.name, this.value, width, y, height);
|
||||
}
|
||||
}
|
||||
|
||||
mouse(event: MouseEvent, pos: Vector2, node: LGraphNode) {
|
||||
const canvas = app.canvas as TLGraphCanvas;
|
||||
if (event.type == "pointerdown") {
|
||||
canvas.prompt("Label", this.value, (v: string) => (this.value = v), event);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the Divider Widget.
|
||||
*/
|
||||
type RgthreeDividerWidgetOptions = {
|
||||
marginTop: number;
|
||||
marginBottom: number;
|
||||
marginLeft: number;
|
||||
marginRight: number;
|
||||
color: string;
|
||||
thickness: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* A divider widget; can also be used as a spacer if fed a 0 thickness.
|
||||
*/
|
||||
export class RgthreeDividerWidget implements IWidget<null> {
|
||||
options = { serialize: false };
|
||||
value = null;
|
||||
name = "divider";
|
||||
|
||||
private readonly widgetOptions: RgthreeDividerWidgetOptions = {
|
||||
marginTop: 7,
|
||||
marginBottom: 7,
|
||||
marginLeft: 15,
|
||||
marginRight: 15,
|
||||
color: LiteGraph.WIDGET_OUTLINE_COLOR,
|
||||
thickness: 1,
|
||||
};
|
||||
|
||||
constructor(widgetOptions?: Partial<RgthreeDividerWidgetOptions>) {
|
||||
Object.assign(this.widgetOptions, widgetOptions || {});
|
||||
}
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D, node: LGraphNode, width: number, posY: number, h: number) {
|
||||
if (this.widgetOptions.thickness) {
|
||||
ctx.strokeStyle = this.widgetOptions.color;
|
||||
const x = this.widgetOptions.marginLeft;
|
||||
const y = posY + this.widgetOptions.marginTop;
|
||||
const w = width - this.widgetOptions.marginLeft - this.widgetOptions.marginRight;
|
||||
ctx.stroke(new Path2D(`M ${x} ${y} h ${w}`));
|
||||
}
|
||||
}
|
||||
|
||||
computeSize(width: number): [number, number] {
|
||||
return [
|
||||
width,
|
||||
this.widgetOptions.marginTop + this.widgetOptions.marginBottom + this.widgetOptions.thickness,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the Label Widget.
|
||||
*/
|
||||
export type RgthreeLabelWidgetOptions = {
|
||||
align?: "left" | "center" | "right";
|
||||
color?: string;
|
||||
italic?: boolean;
|
||||
size?: number;
|
||||
|
||||
/** A label to put on the right side. */
|
||||
actionLabel?: "__PLUS_ICON__" | string;
|
||||
actionCallback?: (event: PointerEvent) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple label widget, drawn with no background.
|
||||
*/
|
||||
export class RgthreeLabelWidget implements IWidget<null> {
|
||||
options = { serialize: false };
|
||||
value = null;
|
||||
name: string;
|
||||
|
||||
private readonly widgetOptions: RgthreeLabelWidgetOptions = {};
|
||||
private posY: number = 0;
|
||||
|
||||
constructor(name: string, widgetOptions?: RgthreeLabelWidgetOptions) {
|
||||
this.name = name;
|
||||
Object.assign(this.widgetOptions, widgetOptions);
|
||||
}
|
||||
|
||||
draw(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
node: LGraphNode,
|
||||
width: number,
|
||||
posY: number,
|
||||
height: number,
|
||||
) {
|
||||
this.posY = posY;
|
||||
ctx.save();
|
||||
|
||||
ctx.textAlign = this.widgetOptions.align || "left";
|
||||
ctx.fillStyle = this.widgetOptions.color || LiteGraph.WIDGET_TEXT_COLOR;
|
||||
const oldFont = ctx.font;
|
||||
if (this.widgetOptions.italic) {
|
||||
ctx.font = "italic " + ctx.font;
|
||||
}
|
||||
if (this.widgetOptions.size) {
|
||||
ctx.font = ctx.font.replace(/\d+px/, `${this.widgetOptions.size}px`);
|
||||
}
|
||||
|
||||
const midY = posY + height / 2;
|
||||
ctx.textBaseline = "middle";
|
||||
|
||||
if (this.widgetOptions.align === "center") {
|
||||
ctx.fillText(this.name, node.size[0] / 2, midY);
|
||||
} else {
|
||||
ctx.fillText(this.name, 15, midY);
|
||||
} // TODO(right);
|
||||
|
||||
ctx.font = oldFont;
|
||||
|
||||
if (this.widgetOptions.actionLabel === "__PLUS_ICON__") {
|
||||
const plus = new Path2D(
|
||||
`M${node.size[0] - 15 - 2} ${posY + 7} v4 h-4 v4 h-4 v-4 h-4 v-4 h4 v-4 h4 v4 h4 z`,
|
||||
);
|
||||
ctx.lineJoin = "round";
|
||||
ctx.lineCap = "round";
|
||||
ctx.fillStyle = "#3a3";
|
||||
ctx.strokeStyle = "#383";
|
||||
ctx.fill(plus);
|
||||
ctx.stroke(plus);
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
mouse(event: PointerEvent, nodePos: Vector2, node: LGraphNode) {
|
||||
if (
|
||||
event.type !== "pointerdown" ||
|
||||
isLowQuality() ||
|
||||
!this.widgetOptions.actionLabel ||
|
||||
!this.widgetOptions.actionCallback
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const pos: Vector2 = [nodePos[0], nodePos[1] - this.posY];
|
||||
const rightX = node.size[0] - 15;
|
||||
if (pos[0] > rightX || pos[0] < rightX - 16) {
|
||||
return false;
|
||||
}
|
||||
this.widgetOptions.actionCallback(event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// @ts-ignore
|
||||
import { app } from "../../scripts/app.js";
|
||||
import type {
|
||||
IWidget,
|
||||
LGraphNode,
|
||||
LiteGraph as TLiteGraph,
|
||||
LGraphCanvas as TLGraphCanvas,
|
||||
Vector2,
|
||||
} from "../typings/litegraph.js";
|
||||
import { drawNodeWidget, fitString, isLowQuality } from "./utils_canvas.js";
|
||||
|
||||
declare const LiteGraph: typeof TLiteGraph;
|
||||
|
||||
/**
|
||||
* Draws a label on teft, and a value on the right, ellipsizing when out of space.
|
||||
*/
|
||||
export function drawLabelAndValue(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
label: string,
|
||||
value: string,
|
||||
width: number,
|
||||
posY: number,
|
||||
height: number,
|
||||
options?: { offsetLeft: number },
|
||||
) {
|
||||
const outerMargin = 15;
|
||||
const innerMargin = 10;
|
||||
const midY = posY + height / 2;
|
||||
ctx.save();
|
||||
ctx.textAlign = "left";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle = LiteGraph.WIDGET_SECONDARY_TEXT_COLOR;
|
||||
const labelX = outerMargin + innerMargin + (options?.offsetLeft ?? 0);
|
||||
ctx.fillText(label, labelX, midY);
|
||||
|
||||
const valueXLeft = labelX + ctx.measureText(label).width + 7;
|
||||
const valueXRight = width - (outerMargin + innerMargin);
|
||||
|
||||
ctx.fillStyle = LiteGraph.WIDGET_TEXT_COLOR;
|
||||
ctx.textAlign = "right";
|
||||
ctx.fillText(fitString(ctx, value, valueXRight - valueXLeft), valueXRight, midY);
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* A better implementation of the LiteGraph text widget, including auto ellipsis.
|
||||
*/
|
||||
export class RgthreeBetterTextWidget implements IWidget<string> {
|
||||
name: string;
|
||||
value: string;
|
||||
|
||||
constructor(name: string, value: string) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D, node: LGraphNode, width: number, y: number, height: number) {
|
||||
const widgetData = drawNodeWidget(ctx, { width, height, posY: y });
|
||||
|
||||
if (!widgetData.lowQuality) {
|
||||
drawLabelAndValue(ctx, this.name, this.value, width, y, height);
|
||||
}
|
||||
}
|
||||
|
||||
mouse(event: MouseEvent, pos: Vector2, node: LGraphNode) {
|
||||
const canvas = app.canvas as TLGraphCanvas;
|
||||
if (event.type == "pointerdown") {
|
||||
canvas.prompt("Label", this.value, (v: string) => (this.value = v), event);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the Divider Widget.
|
||||
*/
|
||||
type RgthreeDividerWidgetOptions = {
|
||||
marginTop: number;
|
||||
marginBottom: number;
|
||||
marginLeft: number;
|
||||
marginRight: number;
|
||||
color: string;
|
||||
thickness: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* A divider widget; can also be used as a spacer if fed a 0 thickness.
|
||||
*/
|
||||
export class RgthreeDividerWidget implements IWidget<null> {
|
||||
options = { serialize: false };
|
||||
value = null;
|
||||
name = "divider";
|
||||
|
||||
private readonly widgetOptions: RgthreeDividerWidgetOptions = {
|
||||
marginTop: 7,
|
||||
marginBottom: 7,
|
||||
marginLeft: 15,
|
||||
marginRight: 15,
|
||||
color: LiteGraph.WIDGET_OUTLINE_COLOR,
|
||||
thickness: 1,
|
||||
};
|
||||
|
||||
constructor(widgetOptions?: Partial<RgthreeDividerWidgetOptions>) {
|
||||
Object.assign(this.widgetOptions, widgetOptions || {});
|
||||
}
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D, node: LGraphNode, width: number, posY: number, h: number) {
|
||||
if (this.widgetOptions.thickness) {
|
||||
ctx.strokeStyle = this.widgetOptions.color;
|
||||
const x = this.widgetOptions.marginLeft;
|
||||
const y = posY + this.widgetOptions.marginTop;
|
||||
const w = width - this.widgetOptions.marginLeft - this.widgetOptions.marginRight;
|
||||
ctx.stroke(new Path2D(`M ${x} ${y} h ${w}`));
|
||||
}
|
||||
}
|
||||
|
||||
computeSize(width: number): [number, number] {
|
||||
return [
|
||||
width,
|
||||
this.widgetOptions.marginTop + this.widgetOptions.marginBottom + this.widgetOptions.thickness,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the Label Widget.
|
||||
*/
|
||||
export type RgthreeLabelWidgetOptions = {
|
||||
align?: "left" | "center" | "right";
|
||||
color?: string;
|
||||
italic?: boolean;
|
||||
size?: number;
|
||||
|
||||
/** A label to put on the right side. */
|
||||
actionLabel?: "__PLUS_ICON__" | string;
|
||||
actionCallback?: (event: PointerEvent) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple label widget, drawn with no background.
|
||||
*/
|
||||
export class RgthreeLabelWidget implements IWidget<null> {
|
||||
options = { serialize: false };
|
||||
value = null;
|
||||
name: string;
|
||||
|
||||
private readonly widgetOptions: RgthreeLabelWidgetOptions = {};
|
||||
private posY: number = 0;
|
||||
|
||||
constructor(name: string, widgetOptions?: RgthreeLabelWidgetOptions) {
|
||||
this.name = name;
|
||||
Object.assign(this.widgetOptions, widgetOptions);
|
||||
}
|
||||
|
||||
draw(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
node: LGraphNode,
|
||||
width: number,
|
||||
posY: number,
|
||||
height: number,
|
||||
) {
|
||||
this.posY = posY;
|
||||
ctx.save();
|
||||
|
||||
ctx.textAlign = this.widgetOptions.align || "left";
|
||||
ctx.fillStyle = this.widgetOptions.color || LiteGraph.WIDGET_TEXT_COLOR;
|
||||
const oldFont = ctx.font;
|
||||
if (this.widgetOptions.italic) {
|
||||
ctx.font = "italic " + ctx.font;
|
||||
}
|
||||
if (this.widgetOptions.size) {
|
||||
ctx.font = ctx.font.replace(/\d+px/, `${this.widgetOptions.size}px`);
|
||||
}
|
||||
|
||||
const midY = posY + height / 2;
|
||||
ctx.textBaseline = "middle";
|
||||
|
||||
if (this.widgetOptions.align === "center") {
|
||||
ctx.fillText(this.name, node.size[0] / 2, midY);
|
||||
} else {
|
||||
ctx.fillText(this.name, 15, midY);
|
||||
} // TODO(right);
|
||||
|
||||
ctx.font = oldFont;
|
||||
|
||||
if (this.widgetOptions.actionLabel === "__PLUS_ICON__") {
|
||||
const plus = new Path2D(
|
||||
`M${node.size[0] - 15 - 2} ${posY + 7} v4 h-4 v4 h-4 v-4 h-4 v-4 h4 v-4 h4 v4 h4 z`,
|
||||
);
|
||||
ctx.lineJoin = "round";
|
||||
ctx.lineCap = "round";
|
||||
ctx.fillStyle = "#3a3";
|
||||
ctx.strokeStyle = "#383";
|
||||
ctx.fill(plus);
|
||||
ctx.stroke(plus);
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
mouse(event: PointerEvent, nodePos: Vector2, node: LGraphNode) {
|
||||
if (
|
||||
event.type !== "pointerdown" ||
|
||||
isLowQuality() ||
|
||||
!this.widgetOptions.actionLabel ||
|
||||
!this.widgetOptions.actionCallback
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const pos: Vector2 = [nodePos[0], nodePos[1] - this.posY];
|
||||
const rightX = node.size[0] - 15;
|
||||
if (pos[0] > rightX || pos[0] < rightX - 16) {
|
||||
return false;
|
||||
}
|
||||
this.widgetOptions.actionCallback(event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user