mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 02:32:18 +00:00
Implement clickable badges (#8401)
Adds an `onClick` handler to LGraphBadge ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8401-Implement-clickable-badges-2f76d73d365081b3b23fc1eaa3bc65b8) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import type { ReadOnlyRect } from '@/lib/litegraph/src/interfaces'
|
||||||
import { LGraphIcon } from './LGraphIcon'
|
import { LGraphIcon } from './LGraphIcon'
|
||||||
import type { LGraphIconOptions } from './LGraphIcon'
|
import type { LGraphIconOptions } from './LGraphIcon'
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ export interface LGraphBadgeOptions {
|
|||||||
height?: number
|
height?: number
|
||||||
cornerRadius?: number
|
cornerRadius?: number
|
||||||
iconOptions?: LGraphIconOptions
|
iconOptions?: LGraphIconOptions
|
||||||
|
onClick?: (e: MouseEvent) => void
|
||||||
xOffset?: number
|
xOffset?: number
|
||||||
yOffset?: number
|
yOffset?: number
|
||||||
}
|
}
|
||||||
@@ -28,9 +30,15 @@ export class LGraphBadge {
|
|||||||
height: number
|
height: number
|
||||||
cornerRadius: number
|
cornerRadius: number
|
||||||
icon?: LGraphIcon
|
icon?: LGraphIcon
|
||||||
|
onClick?: (e: MouseEvent) => void
|
||||||
xOffset: number
|
xOffset: number
|
||||||
yOffset: number
|
yOffset: number
|
||||||
|
|
||||||
|
readonly _boundingRect: [number, number, number, number] = [0, 0, 0, 0]
|
||||||
|
get boundingRect(): ReadOnlyRect {
|
||||||
|
return this._boundingRect
|
||||||
|
}
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
text,
|
text,
|
||||||
fgColor = 'white',
|
fgColor = 'white',
|
||||||
@@ -40,6 +48,7 @@ export class LGraphBadge {
|
|||||||
height = 20,
|
height = 20,
|
||||||
cornerRadius = 5,
|
cornerRadius = 5,
|
||||||
iconOptions,
|
iconOptions,
|
||||||
|
onClick,
|
||||||
xOffset = 0,
|
xOffset = 0,
|
||||||
yOffset = 0
|
yOffset = 0
|
||||||
}: LGraphBadgeOptions) {
|
}: LGraphBadgeOptions) {
|
||||||
@@ -53,6 +62,7 @@ export class LGraphBadge {
|
|||||||
if (iconOptions) {
|
if (iconOptions) {
|
||||||
this.icon = new LGraphIcon(iconOptions)
|
this.icon = new LGraphIcon(iconOptions)
|
||||||
}
|
}
|
||||||
|
this.onClick = onClick
|
||||||
this.xOffset = xOffset
|
this.xOffset = xOffset
|
||||||
this.yOffset = yOffset
|
this.yOffset = yOffset
|
||||||
}
|
}
|
||||||
@@ -91,6 +101,8 @@ export class LGraphBadge {
|
|||||||
const badgeWidth = this.getWidth(ctx)
|
const badgeWidth = this.getWidth(ctx)
|
||||||
const badgeX = 0
|
const badgeX = 0
|
||||||
|
|
||||||
|
this._boundingRect.splice(0, 4, x, y, badgeWidth, this.height)
|
||||||
|
|
||||||
// Draw badge background
|
// Draw badge background
|
||||||
ctx.fillStyle = this.bgColor
|
ctx.fillStyle = this.bgColor
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { toString } from 'es-toolkit/compat'
|
import { toString } from 'es-toolkit/compat'
|
||||||
|
import { toValue } from 'vue'
|
||||||
|
|
||||||
import { PREFIX, SEPARATOR } from '@/constants/groupNodeConstants'
|
import { PREFIX, SEPARATOR } from '@/constants/groupNodeConstants'
|
||||||
import { LitegraphLinkAdapter } from '@/renderer/core/canvas/litegraph/litegraphLinkAdapter'
|
import { LitegraphLinkAdapter } from '@/renderer/core/canvas/litegraph/litegraphLinkAdapter'
|
||||||
@@ -2801,6 +2802,12 @@ export class LGraphCanvas implements CustomEventDispatcher<LGraphCanvasEventMap>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const badge of node.badges.map(toValue).filter((b) => b.onClick)) {
|
||||||
|
if (isInRect(pos[0], pos[1], badge.boundingRect)) {
|
||||||
|
pointer.onClick = badge.onClick
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Mousedown callback - can block drag
|
// Mousedown callback - can block drag
|
||||||
if (node.onMouseDown?.(e, pos, this)) {
|
if (node.onMouseDown?.(e, pos, this)) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
containsCentre,
|
containsCentre,
|
||||||
containsRect,
|
containsRect,
|
||||||
createBounds,
|
createBounds,
|
||||||
|
isInRect,
|
||||||
isInRectangle,
|
isInRectangle,
|
||||||
isPointInRect,
|
isPointInRect,
|
||||||
snapPoint
|
snapPoint
|
||||||
@@ -370,6 +371,8 @@ export class LGraphGroup implements Positionable, IPinnable, IColorable {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
isPointInside = LGraphNode.prototype.isPointInside
|
isPointInside(x: number, y: number): boolean {
|
||||||
|
return isInRect(x, y, this.boundingRect)
|
||||||
|
}
|
||||||
setDirtyCanvas = LGraphNode.prototype.setDirtyCanvas
|
setDirtyCanvas = LGraphNode.prototype.setDirtyCanvas
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { toValue } from 'vue'
|
||||||
|
|
||||||
import { LGraphNodeProperties } from '@/lib/litegraph/src/LGraphNodeProperties'
|
import { LGraphNodeProperties } from '@/lib/litegraph/src/LGraphNodeProperties'
|
||||||
import {
|
import {
|
||||||
calculateInputSlotPosFromSlot,
|
calculateInputSlotPosFromSlot,
|
||||||
@@ -2084,7 +2086,13 @@ export class LGraphNode
|
|||||||
* checks if a point is inside the shape of a node
|
* checks if a point is inside the shape of a node
|
||||||
*/
|
*/
|
||||||
isPointInside(x: number, y: number): boolean {
|
isPointInside(x: number, y: number): boolean {
|
||||||
return isInRect(x, y, this.boundingRect)
|
if (isInRect(x, y, this.boundingRect)) return true
|
||||||
|
|
||||||
|
for (const badge of this.badges.map(toValue).filter((b) => b.onClick)) {
|
||||||
|
if (isInRect(x - this.pos[0], y - this.pos[1], badge.boundingRect))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ LGraph {
|
|||||||
"font_size": 14,
|
"font_size": 14,
|
||||||
"graph": [Circular],
|
"graph": [Circular],
|
||||||
"id": 123,
|
"id": 123,
|
||||||
"isPointInside": [Function],
|
|
||||||
"selected": undefined,
|
"selected": undefined,
|
||||||
"setDirtyCanvas": [Function],
|
"setDirtyCanvas": [Function],
|
||||||
"title": "A group to test with",
|
"title": "A group to test with",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
color: fgColor,
|
color: fgColor,
|
||||||
backgroundColor: bgColor
|
backgroundColor: bgColor
|
||||||
}"
|
}"
|
||||||
|
@click="(e) => onClick?.(e)"
|
||||||
>
|
>
|
||||||
{{ text }}
|
{{ text }}
|
||||||
<i v-if="cssIcon" :class="cn(cssIcon)" />
|
<i v-if="cssIcon" :class="cn(cssIcon)" />
|
||||||
@@ -20,6 +21,7 @@ export interface NodeBadgeProps {
|
|||||||
fgColor?: LGraphBadge['fgColor']
|
fgColor?: LGraphBadge['fgColor']
|
||||||
bgColor?: LGraphBadge['bgColor']
|
bgColor?: LGraphBadge['bgColor']
|
||||||
cssIcon?: string
|
cssIcon?: string
|
||||||
|
onClick?: (e: MouseEvent) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
Reference in New Issue
Block a user