File size: 4,835 Bytes
3a4bb96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

// 通用多按钮组件定义
const MultiButtonWidget = (app, inputName, options, buttons) => {
    const widget = {
        name: inputName,
        type: "multi_button",
        y: 0,
        value: null,
        options: options || {},
        clicked_button: null,
        click_time: 0
    };

    // 使用 ComfyUI 原生样式常量
    const margin = 15;
    const button_height = LiteGraph.NODE_WIDGET_HEIGHT || 20;
    const label_width = options.labelWidth !== undefined ? options.labelWidth : 80;
    const button_spacing = options.buttonSpacing || 4;
    const button_count = buttons.length;
    
    // 原生 ComfyUI 按钮颜色
    const BUTTON_BGCOLOR = "#222";
    const BUTTON_OUTLINE_COLOR = "#666";
    const BUTTON_TEXT_COLOR = "#DDD";
    const BUTTON_CLICKED_COLOR = "#AAA";

    widget.draw = function(ctx, node, width, Y, height) {
        if (app.canvas.ds.scale < 0.50) return;
        
        ctx.save();
        ctx.lineWidth = 1;
        
        // 绘制标签(仅当有标签时)
        if (label_width > 0 && inputName) {
            ctx.fillStyle = LiteGraph.WIDGET_SECONDARY_TEXT_COLOR;
            ctx.textAlign = "left";
            ctx.fillText(inputName, margin, Y + height * 0.7);
        }

        // 计算按钮区域
        const label_space = label_width > 0 ? label_width : 0;
        const left_margin = label_width > 0 ? margin : 10; // 没有标签时使用小边距避免超出节点
        const right_margin = label_width > 0 ? margin : 10; // 右边也保持小边距
        const available_width = width - label_space - left_margin - right_margin;
        const total_spacing = button_spacing * (button_count - 1);
        const button_width = (available_width - total_spacing) / button_count;
        const start_x = label_space + left_margin;
        
        // 检查点击高亮是否需要清除
        const now = Date.now();
        if (widget.click_time && now - widget.click_time > 150) {
            widget.clicked_button = null;
            widget.click_time = 0;
        }
        
        // 循环绘制所有按钮
        for (let i = 0; i < button_count; i++) {
            const button = buttons[i];
            const button_x = start_x + i * (button_width + button_spacing);
            
            // 确定按钮颜色(点击高亮或默认)
            const is_clicked = (widget.clicked_button === i);
            const button_color = is_clicked ? BUTTON_CLICKED_COLOR : 
                                (button.color || BUTTON_BGCOLOR);
            
            // 绘制按钮背景
            ctx.fillStyle = button_color;
            ctx.fillRect(button_x, Y, button_width, button_height);
            
            // 绘制按钮边框
            ctx.strokeStyle = BUTTON_OUTLINE_COLOR;
            ctx.strokeRect(button_x, Y, button_width, button_height);
            
            // 绘制按钮文字
            ctx.fillStyle = BUTTON_TEXT_COLOR;
            ctx.textAlign = "center";
            ctx.fillText(button.text, button_x + button_width / 2, Y + button_height * 0.7);
        }
        
        ctx.restore();
    };

    widget.onPointerDown = function(pointer, node) {
        const e = pointer.eDown;
        const label_space = label_width > 0 ? label_width : 0;
        const left_margin = label_width > 0 ? margin : 10;
        const right_margin = label_width > 0 ? margin : 10;
        const x = e.canvasX - node.pos[0] - label_space - left_margin;
        const available_width = node.size[0] - label_space - left_margin - right_margin;
        const total_spacing = button_spacing * (button_count - 1);
        const button_width = (available_width - total_spacing) / button_count;
        
        pointer.onClick = () => {
            // 计算点击了哪个按钮
            for (let i = 0; i < button_count; i++) {
                const button_start = i * (button_width + button_spacing);
                const button_end = button_start + button_width;
                
                if (x >= button_start && x <= button_end) {
                    // 点击了第 i 个按钮
                    widget.clicked_button = i;
                    widget.click_time = Date.now();
                    
                    // 执行回调函数
                    if (buttons[i] && buttons[i].callback) {
                        buttons[i].callback();
                    }
                    
                    // 触发重绘以显示点击效果
                    app.graph.setDirtyCanvas(true);
                    break;
                }
            }
        };
    };

    widget.computeSize = function() {
        return [0, button_height];
    };

    widget.serializeValue = async () => {
        return null;
    };

    return widget;
};

// 导出组件
export { MultiButtonWidget };