Files
ComfyUI_frontend/src/components/graph/TitleEditor.vue
Chenlei Hu 4a230f720e Edit group name on group creation (With Ctrl + g) (#715)
* Editor store

* Merge editors

* nit

* Edit on group creation

* nit
2024-09-02 20:20:40 -04:00

167 lines
4.5 KiB
Vue

<template>
<div
v-if="showInput"
class="group-title-editor node-title-editor"
:style="inputStyle"
>
<EditableText
:isEditing="showInput"
:modelValue="editedTitle"
@edit="onEdit"
/>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, CSSProperties, watch } from 'vue'
import { app } from '@/scripts/app'
import { LGraphGroup, LGraphNode, LiteGraph } from '@comfyorg/litegraph'
import EditableText from '@/components/common/EditableText.vue'
import { ComfyExtension } from '@/types/comfy'
import { useSettingStore } from '@/stores/settingStore'
import type { LiteGraphCanvasEvent } from '@comfyorg/litegraph'
import { useTitleEditorStore } from '@/stores/graphStore'
const settingStore = useSettingStore()
const showInput = ref(false)
const editedTitle = ref('')
const inputStyle = ref<CSSProperties>({
position: 'fixed',
left: '0px',
top: '0px',
width: '200px',
height: '20px',
fontSize: '12px'
})
const titleEditorStore = useTitleEditorStore()
const onEdit = (newValue: string) => {
if (titleEditorStore.titleEditorTarget && newValue.trim() !== '') {
titleEditorStore.titleEditorTarget.title = newValue.trim()
app.graph.setDirtyCanvas(true, true)
}
showInput.value = false
titleEditorStore.titleEditorTarget = null
}
watch(
() => titleEditorStore.titleEditorTarget,
(target) => {
if (target === null) {
return
}
editedTitle.value = target.title
showInput.value = true
if (target instanceof LGraphGroup) {
const group = target
const [x, y] = group.pos
const [w, h] = group.size
const [left, top] = app.canvasPosToClientPos([x, y])
inputStyle.value.left = `${left}px`
inputStyle.value.top = `${top}px`
const width = w * app.canvas.ds.scale
const height = group.titleHeight * app.canvas.ds.scale
inputStyle.value.width = `${width}px`
inputStyle.value.height = `${height}px`
const fontSize = group.font_size * app.canvas.ds.scale
inputStyle.value.fontSize = `${fontSize}px`
} else if (target instanceof LGraphNode) {
const node = target
const isCollapsed = node.flags?.collapsed
const [x, y, nodeWidth, nodeHeight] = node.getBounding()
const canvasWidth =
// @ts-expect-error Remove after collapsed_width is exposed in LiteGraph
isCollapsed && node._collapsed_width ? node._collapsed_width : nodeWidth
const canvasHeight = LiteGraph.NODE_TITLE_HEIGHT
const [left, top] = app.canvasPosToClientPos([x, y])
inputStyle.value.left = `${left}px`
inputStyle.value.top = `${top}px`
const width = canvasWidth * app.canvas.ds.scale
const height = canvasHeight * app.canvas.ds.scale
inputStyle.value.width = `${width}px`
inputStyle.value.height = `${height}px`
const fontSize = 12 * app.canvas.ds.scale
inputStyle.value.fontSize = `${fontSize}px`
}
}
)
const canvasEventHandler = (event: LiteGraphCanvasEvent) => {
if (!settingStore.get('Comfy.Group.DoubleClickTitleToEdit')) {
return
}
if (event.detail.subType === 'group-double-click') {
const group: LGraphGroup = event.detail.group
const [x, y] = group.pos
const e = event.detail.originalEvent
// @ts-expect-error LiteGraphCanvasEvent is not typed
const relativeY = e.canvasY - y
// Only allow editing if the click is on the title bar
if (relativeY > group.titleHeight) {
return
}
titleEditorStore.titleEditorTarget = group
}
}
const extension: ComfyExtension = {
name: 'Comfy.NodeTitleEditor',
nodeCreated(node: LGraphNode) {
// Store the original callback
const originalCallback = node.onNodeTitleDblClick
node.onNodeTitleDblClick = function (e: MouseEvent, ...args: any[]) {
if (!settingStore.get('Comfy.Node.DoubleClickTitleToEdit')) {
return
}
titleEditorStore.titleEditorTarget = this
// Call the original callback if it exists
if (typeof originalCallback === 'function') {
originalCallback.call(this, e, ...args)
}
}
}
}
onMounted(() => {
document.addEventListener('litegraph:canvas', canvasEventHandler)
app.registerExtension(extension)
})
onUnmounted(() => {
document.removeEventListener('litegraph:canvas', canvasEventHandler)
})
</script>
<style scoped>
.group-title-editor.node-title-editor {
z-index: 9999;
padding: 0.25rem;
}
:deep(.editable-text) {
width: 100%;
height: 100%;
}
:deep(.editable-text input) {
width: 100%;
height: 100%;
/* Override the default font size */
font-size: inherit;
}
</style>