mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-27 18:24:11 +00:00
Group update - titlebar, resize, config (#270)
* Backport group header from frontend * nit - TS types & redundant code * Refactor - simplify group resize * Fix group resize can be inverted * Move group resize check to group class * Add config for group padding & default colour * nit - Remove redundant code
This commit is contained in:
@@ -260,6 +260,9 @@ export class LGraphCanvas {
|
||||
selected_nodes: Dictionary<LGraphNode> = {}
|
||||
/** All selected nodes, groups, and reroutes */
|
||||
selectedItems: Set<Positionable> = new Set()
|
||||
/** The group currently being resized. */
|
||||
resizingGroup: LGraphGroup | null = null
|
||||
/** @deprecated See {@link LGraphCanvas.selectedItems} */
|
||||
selected_group: LGraphGroup | null = null
|
||||
visible_nodes: LGraphNode[] = []
|
||||
node_dragged?: LGraphNode
|
||||
@@ -299,6 +302,7 @@ export class LGraphCanvas {
|
||||
block_click?: boolean
|
||||
last_click_position?: Point
|
||||
resizing_node?: LGraphNode
|
||||
/** @deprecated See {@link LGraphCanvas.resizingGroup} */
|
||||
selected_group_resizing?: boolean
|
||||
last_mouse_dragging: boolean
|
||||
onMouseDown: (arg0: CanvasMouseEvent) => void
|
||||
@@ -1253,7 +1257,6 @@ export class LGraphCanvas {
|
||||
this.dragging_rectangle = null
|
||||
|
||||
this.selected_nodes = {}
|
||||
/** The group currently being resized */
|
||||
this.selected_group = null
|
||||
|
||||
this.visible_nodes = []
|
||||
@@ -1428,13 +1431,14 @@ export class LGraphCanvas {
|
||||
|
||||
if (!skip_events) this.bindEvents()
|
||||
}
|
||||
//used in some events to capture them
|
||||
_doNothing(e: Event) {
|
||||
/** Captures an event and prevents default - returns false. */
|
||||
_doNothing(e: Event): boolean {
|
||||
//console.log("pointerevents: _doNothing "+e.type);
|
||||
e.preventDefault()
|
||||
return false
|
||||
}
|
||||
_doReturnTrue(e: Event) {
|
||||
/** Captures an event and prevents default - returns true. */
|
||||
_doReturnTrue(e: Event): boolean {
|
||||
e.preventDefault()
|
||||
return true
|
||||
}
|
||||
@@ -1722,7 +1726,6 @@ export class LGraphCanvas {
|
||||
let node = this.graph.getNodeOnPos(e.canvasX, e.canvasY, this.visible_nodes)
|
||||
let skip_action = false
|
||||
const now = LiteGraph.getTime()
|
||||
const is_primary = (e.isPrimary === undefined || !e.isPrimary)
|
||||
const is_double_click = (now - this.last_mouseclick < 300)
|
||||
this.mouse[0] = e.clientX
|
||||
this.mouse[1] = e.clientY
|
||||
@@ -1730,7 +1733,7 @@ export class LGraphCanvas {
|
||||
this.graph_mouse[1] = e.canvasY
|
||||
this.last_click_position = [this.mouse[0], this.mouse[1]]
|
||||
|
||||
this.pointer_is_double = this.pointer_is_down && is_primary
|
||||
this.pointer_is_double = this.pointer_is_down && e.isPrimary
|
||||
this.pointer_is_down = true
|
||||
|
||||
this.canvas.focus()
|
||||
@@ -2057,11 +2060,8 @@ export class LGraphCanvas {
|
||||
this.ctx.lineWidth = lineWidth
|
||||
}
|
||||
|
||||
|
||||
this.selected_group = this.graph.getGroupOnPos(e.canvasX, e.canvasY)
|
||||
this.selected_group_resizing = false
|
||||
|
||||
const group = this.selected_group
|
||||
const group = this.graph.getGroupOnPos(e.canvasX, e.canvasY)
|
||||
this.selected_group = group
|
||||
if (group && !this.read_only) {
|
||||
if (e.ctrlKey) {
|
||||
this.dragging_rectangle = null
|
||||
@@ -2069,7 +2069,7 @@ export class LGraphCanvas {
|
||||
|
||||
const dist = distance([e.canvasX, e.canvasY], [group.pos[0] + group.size[0], group.pos[1] + group.size[1]])
|
||||
if (dist * this.ds.scale < 10) {
|
||||
this.selected_group_resizing = true
|
||||
this.resizingGroup = group
|
||||
} else {
|
||||
const f = group.font_size || LiteGraph.DEFAULT_GROUP_FONT_SIZE
|
||||
const headerHeight = f * 1.4
|
||||
@@ -2086,7 +2086,7 @@ export class LGraphCanvas {
|
||||
this.emitEvent({
|
||||
subType: "group-double-click",
|
||||
originalEvent: e,
|
||||
group: this.selected_group,
|
||||
group,
|
||||
})
|
||||
}
|
||||
} else if (is_double_click && !this.read_only) {
|
||||
@@ -2259,19 +2259,20 @@ export class LGraphCanvas {
|
||||
|
||||
//get node over
|
||||
const node = this.graph.getNodeOnPos(e.canvasX, e.canvasY, this.visible_nodes)
|
||||
const { resizingGroup } = this
|
||||
|
||||
if (this.dragging_rectangle) {
|
||||
this.dragging_rectangle[2] = e.canvasX - this.dragging_rectangle[0]
|
||||
this.dragging_rectangle[3] = e.canvasY - this.dragging_rectangle[1]
|
||||
this.dirty_canvas = true
|
||||
}
|
||||
else if (this.selected_group_resizing && !this.read_only) {
|
||||
//moving/resizing a group
|
||||
this.selected_group.resize(
|
||||
e.canvasX - this.selected_group.pos[0],
|
||||
e.canvasY - this.selected_group.pos[1]
|
||||
else if (resizingGroup && !this.read_only) {
|
||||
// Resizing a group
|
||||
const resized = resizingGroup.resize(
|
||||
e.canvasX - resizingGroup.pos[0],
|
||||
e.canvasY - resizingGroup.pos[1]
|
||||
)
|
||||
this.dirty_bgcanvas = true
|
||||
if (resized) this.dirty_bgcanvas = true
|
||||
} else if (this.dragging_canvas) {
|
||||
this.ds.offset[0] += delta[0] / this.ds.scale
|
||||
this.ds.offset[1] += delta[1] / this.ds.scale
|
||||
@@ -2494,6 +2495,7 @@ export class LGraphCanvas {
|
||||
this.block_click &&= false
|
||||
|
||||
if (e.which == 1) {
|
||||
this.resizingGroup = null
|
||||
|
||||
if (this.node_widget) {
|
||||
this.processNodeWidgets(this.node_widget[0], this.graph_mouse, e)
|
||||
@@ -2501,12 +2503,7 @@ export class LGraphCanvas {
|
||||
|
||||
//left button
|
||||
this.node_widget = null
|
||||
|
||||
if (this.selected_group) {
|
||||
this.dirty_canvas = true
|
||||
this.selected_group = null
|
||||
}
|
||||
this.selected_group_resizing = false
|
||||
this.selected_group = null
|
||||
this.isDragging = false
|
||||
|
||||
let node = this.graph.getNodeOnPos(
|
||||
|
||||
@@ -12,12 +12,18 @@ export interface IGraphGroupFlags extends Record<string, unknown> {
|
||||
}
|
||||
|
||||
export class LGraphGroup implements Positionable {
|
||||
static minWidth = 140
|
||||
static minHeight = 80
|
||||
static resizeLength = 10
|
||||
static padding = 4
|
||||
static defaultColour = '#335'
|
||||
|
||||
id: number
|
||||
color: string
|
||||
title: string
|
||||
font?: string
|
||||
font_size: number = LiteGraph.DEFAULT_GROUP_FONT || 24
|
||||
_bounding: Float32Array = new Float32Array([10, 10, 140, 80])
|
||||
_bounding: Float32Array = new Float32Array([10, 10, LGraphGroup.minWidth, LGraphGroup.minHeight])
|
||||
_pos: Point = this._bounding.subarray(0, 2)
|
||||
_size: Size = this._bounding.subarray(2, 4)
|
||||
/** @deprecated See {@link _children} */
|
||||
@@ -54,10 +60,11 @@ export class LGraphGroup implements Positionable {
|
||||
set size(v) {
|
||||
if (!v || v.length < 2) return
|
||||
|
||||
this._size[0] = Math.max(140, v[0])
|
||||
this._size[1] = Math.max(80, v[1])
|
||||
this._size[0] = Math.max(LGraphGroup.minWidth, v[0])
|
||||
this._size[1] = Math.max(LGraphGroup.minHeight, v[1])
|
||||
}
|
||||
|
||||
|
||||
get boundingRect() {
|
||||
return this._bounding
|
||||
}
|
||||
@@ -113,26 +120,37 @@ export class LGraphGroup implements Positionable {
|
||||
* @param {CanvasRenderingContext2D} ctx
|
||||
*/
|
||||
draw(graphCanvas: LGraphCanvas, ctx: CanvasRenderingContext2D): void {
|
||||
const padding = 4
|
||||
const { padding, resizeLength, defaultColour } = LGraphGroup
|
||||
const font_size = this.font_size || LiteGraph.DEFAULT_GROUP_FONT_SIZE
|
||||
|
||||
ctx.fillStyle = this.color
|
||||
ctx.strokeStyle = this.color
|
||||
const [x, y] = this._pos
|
||||
const [width, height] = this._size
|
||||
|
||||
// Titlebar
|
||||
ctx.globalAlpha = 0.25 * graphCanvas.editor_alpha
|
||||
ctx.fillStyle = this.color || defaultColour
|
||||
ctx.strokeStyle = this.color || defaultColour
|
||||
ctx.beginPath()
|
||||
ctx.rect(x + 0.5, y + 0.5, width, font_size * 1.4)
|
||||
ctx.fill()
|
||||
|
||||
// Group background, border
|
||||
ctx.fillStyle = this.color
|
||||
ctx.strokeStyle = this.color
|
||||
ctx.beginPath()
|
||||
ctx.rect(x + 0.5, y + 0.5, width, height)
|
||||
ctx.fill()
|
||||
ctx.globalAlpha = graphCanvas.editor_alpha
|
||||
ctx.stroke()
|
||||
|
||||
// Resize marker
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x + width, y + height)
|
||||
ctx.lineTo(x + width - 10, y + height)
|
||||
ctx.lineTo(x + width, y + height - 10)
|
||||
ctx.lineTo(x + width - resizeLength, y + height)
|
||||
ctx.lineTo(x + width, y + height - resizeLength)
|
||||
ctx.fill()
|
||||
|
||||
const font_size = this.font_size || LiteGraph.DEFAULT_GROUP_FONT_SIZE
|
||||
// Title
|
||||
ctx.font = font_size + "px Arial"
|
||||
ctx.textAlign = "left"
|
||||
ctx.fillText(this.title + (this.pinned ? "📌" : ""), x + padding, y + font_size)
|
||||
@@ -148,11 +166,12 @@ export class LGraphGroup implements Positionable {
|
||||
}
|
||||
}
|
||||
|
||||
resize(width: number, height: number): void {
|
||||
if (this.pinned) return
|
||||
resize(width: number, height: number): boolean {
|
||||
if (this.pinned) return false
|
||||
|
||||
this._size[0] = width
|
||||
this._size[1] = height
|
||||
this._size[0] = Math.max(LGraphGroup.minWidth, width)
|
||||
this._size[1] = Math.max(LGraphGroup.minHeight, height)
|
||||
return true
|
||||
}
|
||||
|
||||
move(deltaX: number, deltaY: number, skipChildren: boolean = false): void {
|
||||
@@ -264,6 +283,16 @@ export class LGraphGroup implements Positionable {
|
||||
return isInsideRectangle(x, y, b[0], b[1], b[2], this.titleHeight)
|
||||
}
|
||||
|
||||
isInResize(x: number, y: number): boolean {
|
||||
const b = this._bounding
|
||||
const right = b[0] + b[2]
|
||||
const bottom = b[1] + b[3]
|
||||
|
||||
return x < right
|
||||
&& y < bottom
|
||||
&& (x - right) + (y - bottom) > -LGraphGroup.resizeLength
|
||||
}
|
||||
|
||||
isPointInside = LGraphNode.prototype.isPointInside
|
||||
setDirtyCanvas = LGraphNode.prototype.setDirtyCanvas
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user