Changed to switch button mask on/off

This commit is contained in:
Dariusz L
2025-07-28 19:02:29 +02:00
parent 257bada28d
commit 6b04e3891b
4 changed files with 182 additions and 83 deletions

View File

@@ -393,37 +393,66 @@ async function createCanvasWidget(node, widget, app) {
]), ]),
$el("div.painter-separator"), $el("div.painter-separator"),
$el("div.painter-button-group", { id: "mask-controls" }, [ $el("div.painter-button-group", { id: "mask-controls" }, [
$el("button.painter-button.primary", { $el("label.clipboard-switch.mask-switch", {
id: `toggle-mask-btn-${node.id}`, id: `toggle-mask-switch-${node.id}`,
textContent: "M", // Fallback text until icon loads style: { minWidth: "56px", maxWidth: "56px", width: "56px", paddingLeft: "0", paddingRight: "0" }
title: "Toggle mask overlay visibility", }, [
style: { $el("input", {
display: 'flex', type: "checkbox",
alignItems: 'center', checked: canvas.maskTool.isOverlayVisible,
justifyContent: 'center', onchange: (e) => {
minWidth: '32px', const checked = e.target.checked;
maxWidth: '32px', canvas.maskTool.isOverlayVisible = checked;
padding: '4px', canvas.render();
fontSize: '12px', }
fontWeight: 'bold' }),
}, $el("span.switch-track"),
onclick: (e) => { $el("span.switch-labels", { style: { fontSize: "11px" } }, [
const button = e.currentTarget; $el("span.text-clipspace", { style: { paddingRight: "22px" } }, ["On"]),
canvas.maskTool.toggleOverlayVisibility(); $el("span.text-system", { style: { paddingLeft: "20px" } }, ["Off"])
canvas.render(); ]),
const iconContainer = button.querySelector('.mask-icon-container'); $el("span.switch-knob", {}, [
if (iconContainer) { (() => {
if (canvas.maskTool.isOverlayVisible) { // Ikona maski (SVG lub obrazek)
button.classList.add('primary'); const iconContainer = document.createElement('span');
iconContainer.style.opacity = '1'; iconContainer.className = 'switch-icon';
iconContainer.style.display = 'flex';
iconContainer.style.alignItems = 'center';
iconContainer.style.justifyContent = 'center';
iconContainer.style.width = '16px';
iconContainer.style.height = '16px';
// Pobierz ikonę maski z iconLoader
const icon = iconLoader.getIcon(LAYERFORGE_TOOLS.MASK);
if (icon instanceof HTMLImageElement) {
const img = icon.cloneNode();
img.style.width = "16px";
img.style.height = "16px";
// Ustaw filtr w zależności od stanu checkboxa
setTimeout(() => {
const input = document.getElementById(`toggle-mask-switch-${node.id}`)?.querySelector('input[type="checkbox"]');
const updateIconFilter = () => {
if (input && img) {
img.style.filter = input.checked
? "brightness(0) invert(1)"
: "grayscale(1) brightness(0.7) opacity(0.6)";
}
};
if (input) {
input.addEventListener('change', updateIconFilter);
updateIconFilter();
}
}, 0);
iconContainer.appendChild(img);
} }
else { else {
button.classList.remove('primary'); iconContainer.textContent = "M";
iconContainer.style.opacity = '0.5'; iconContainer.style.fontSize = "12px";
iconContainer.style.color = "#fff";
} }
} return iconContainer;
} })()
}), ])
]),
$el("button.painter-button", { $el("button.painter-button", {
textContent: "Edit Mask", textContent: "Edit Mask",
title: "Open the current canvas view in the mask editor", title: "Open the current canvas view in the mask editor",

View File

@@ -2,16 +2,17 @@
background-color: #444; background-color: #444;
border: 1px solid #555; border: 1px solid #555;
border-radius: 5px; border-radius: 5px;
color: #e0e0e0; color: #fff;
padding: 6px 14px; padding: 6px 14px;
font-size: 12px; font-size: 12px;
font-weight: 500; font-weight: 550;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
min-width: 80px; min-width: 80px;
text-align: center; text-align: center;
margin: 2px; margin: 2px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1); box-shadow: 0 1px 2px rgba(0,0,0,0.1);
text-shadow: 0 1px 2px rgb(0,0,0);
} }
.painter-button:hover { .painter-button:hover {
@@ -42,7 +43,7 @@
background-color: #3a76d6; background-color: #3a76d6;
border-color: #2a6ac4; border-color: #2a6ac4;
color: #fff; color: #fff;
text-shadow: none; text-shadow: 0 1px 2px rgb(0,0,0);
} }
.painter-button.primary:hover { .painter-button.primary:hover {
@@ -54,6 +55,7 @@
background-color: #4a7c59; background-color: #4a7c59;
border-color: #3a6c49; border-color: #3a6c49;
color: #fff; color: #fff;
text-shadow: 0 1px 2px rgb(0,0,0);
} }
.painter-button.success:hover { .painter-button.success:hover {
@@ -65,6 +67,7 @@
background-color: #c54747; background-color: #c54747;
border-color: #a53737; border-color: #a53737;
color: #fff; color: #fff;
text-shadow: 0 1px 2px rgb(0,0,0);
} }
.painter-button.danger:hover { .painter-button.danger:hover {
@@ -180,11 +183,11 @@
width: 90px; width: 90px;
height: 30px; height: 30px;
box-sizing: border-box; box-sizing: border-box;
background-color: #444; background: linear-gradient(to right, #5a5a5a 30%, #3a76d6);
border-radius: 5px; border-radius: 5px;
border: 1px solid #555; border: 1px solid #555;
cursor: pointer; cursor: pointer;
transition: background-color 0.3s ease-in-out; transition: background 0.3s ease-in-out, border-color 0.3s ease-in-out;
user-select: none; user-select: none;
padding: 0; padding: 0;
font-family: inherit; font-family: inherit;
@@ -192,11 +195,21 @@
box-shadow: 0 1px 2px rgba(0,0,0,0.1); box-shadow: 0 1px 2px rgba(0,0,0,0.1);
} }
.clipboard-switch:hover { .clipboard-switch:hover {
background-color: #555; background: linear-gradient(to right, #6a6a6a 30%, #4a86e4);
border-color: #666; border-color: #666;
box-shadow: 0 2px 4px rgba(0,0,0,0.15);
transform: translateY(-1px);
}
/* Mask switch: szaro-czarny gradient tylko dla maski */
.clipboard-switch.mask-switch {
background: linear-gradient(to right, #5a5a5a 30%, #e53935);
}
.clipboard-switch.mask-switch:hover {
background: linear-gradient(to right, #6a6a6a 30%, #ff5252);
} }
.clipboard-switch:active { .clipboard-switch:active {
background-color: #3a3a3a; background: linear-gradient(135deg, #3a76d6, #3a3a3a);
} }
.clipboard-switch input[type="checkbox"] { .clipboard-switch input[type="checkbox"] {
@@ -223,6 +236,14 @@
z-index: 2; z-index: 2;
} }
.clipboard-switch:hover .switch-knob {
background-color: #6a6a6a;
}
.clipboard-switch:hover .switch-knob {
background-color: #6a6a6a;
}
.clipboard-switch .switch-labels { .clipboard-switch .switch-labels {
position: absolute; position: absolute;
top: 0; top: 0;
@@ -232,11 +253,12 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-weight: 500; font-weight: 550;
color: #e0e0e0; color: #ffffff;
pointer-events: none; pointer-events: none;
z-index: 1; z-index: 1;
transition: opacity 0.3s ease-in-out; transition: opacity 0.3s ease-in-out;
text-shadow: 0 1px 2px rgb(0, 0, 0);
} }
.clipboard-switch .switch-labels .text-clipspace, .clipboard-switch .switch-labels .text-clipspace,
.clipboard-switch .switch-labels .text-system { .clipboard-switch .switch-labels .text-system {
@@ -261,20 +283,19 @@
/* Checked state */ /* Checked state */
.clipboard-switch:has(input:checked) { .clipboard-switch:has(input:checked) {
background-color: #3a76d6; background: linear-gradient(to right, #3a76d6, #5a5a5a 70%);
border-color: #2a6ac4; border-color: #2a6ac4;
} }
.clipboard-switch:has(input:checked):hover { .clipboard-switch:has(input:checked):hover {
background-color: #4a86e4; background: linear-gradient(to right, #4a86e4, #6a6a6a 70%);
border-color: #3a76d6; border-color: #3a76d6;
} }
.clipboard-switch input:checked ~ .switch-knob { .clipboard-switch input:checked ~ .switch-knob {
left: calc(100% - 26px); left: calc(100% - 26px);
background-color: #fff;
} }
.clipboard-switch input:checked ~ .switch-knob .switch-icon img { .clipboard-switch input:checked ~ .switch-knob .switch-icon img {
filter: invert(35%) sepia(100%) saturate(1500%) hue-rotate(200deg) brightness(90%) contrast(100%); filter: none;
} }
.clipboard-switch input:checked ~ .switch-labels .text-clipspace { .clipboard-switch input:checked ~ .switch-labels .text-clipspace {
opacity: 1; opacity: 1;

View File

@@ -435,37 +435,65 @@ async function createCanvasWidget(node: ComfyNode, widget: any, app: ComfyApp):
]), ]),
$el("div.painter-separator"), $el("div.painter-separator"),
$el("div.painter-button-group", {id: "mask-controls"}, [ $el("div.painter-button-group", {id: "mask-controls"}, [
$el("button.painter-button.primary", { $el("label.clipboard-switch.mask-switch", {
id: `toggle-mask-btn-${node.id}`, id: `toggle-mask-switch-${node.id}`,
textContent: "M", // Fallback text until icon loads style: { minWidth: "56px", maxWidth: "56px", width: "56px", paddingLeft: "0", paddingRight: "0" }
title: "Toggle mask overlay visibility", }, [
style: { $el("input", {
display: 'flex', type: "checkbox",
alignItems: 'center', checked: canvas.maskTool.isOverlayVisible,
justifyContent: 'center', onchange: (e: Event) => {
minWidth: '32px', const checked = (e.target as HTMLInputElement).checked;
maxWidth: '32px', canvas.maskTool.isOverlayVisible = checked;
padding: '4px', canvas.render();
fontSize: '12px', }
fontWeight: 'bold' }),
}, $el("span.switch-track"),
onclick: (e: MouseEvent) => { $el("span.switch-labels", { style: { fontSize: "11px" } }, [
const button = e.currentTarget as HTMLButtonElement; $el("span.text-clipspace", { style: { paddingRight: "22px" } }, ["On"]),
canvas.maskTool.toggleOverlayVisibility(); $el("span.text-system", { style: { paddingLeft: "20px" } }, ["Off"])
canvas.render(); ]),
$el("span.switch-knob", {}, [
const iconContainer = button.querySelector('.mask-icon-container') as HTMLElement; (() => {
if (iconContainer) { // Ikona maski (SVG lub obrazek)
if (canvas.maskTool.isOverlayVisible) { const iconContainer = document.createElement('span') as HTMLElement;
button.classList.add('primary'); iconContainer.className = 'switch-icon';
iconContainer.style.opacity = '1'; iconContainer.style.display = 'flex';
} else { iconContainer.style.alignItems = 'center';
button.classList.remove('primary'); iconContainer.style.justifyContent = 'center';
iconContainer.style.opacity = '0.5'; iconContainer.style.width = '16px';
} iconContainer.style.height = '16px';
// Pobierz ikonę maski z iconLoader
const icon = iconLoader.getIcon(LAYERFORGE_TOOLS.MASK);
if (icon instanceof HTMLImageElement) {
const img = icon.cloneNode() as HTMLImageElement;
img.style.width = "16px";
img.style.height = "16px";
// Ustaw filtr w zależności od stanu checkboxa
setTimeout(() => {
const input = document.getElementById(`toggle-mask-switch-${node.id}`)?.querySelector('input[type="checkbox"]') as HTMLInputElement;
const updateIconFilter = () => {
if (input && img) {
img.style.filter = input.checked
? "brightness(0) invert(1)"
: "grayscale(1) brightness(0.7) opacity(0.6)";
} }
};
if (input) {
input.addEventListener('change', updateIconFilter);
updateIconFilter();
} }
}), }, 0);
iconContainer.appendChild(img);
} else {
iconContainer.textContent = "M";
iconContainer.style.fontSize = "12px";
iconContainer.style.color = "#fff";
}
return iconContainer;
})()
])
]),
$el("button.painter-button", { $el("button.painter-button", {
textContent: "Edit Mask", textContent: "Edit Mask",
title: "Open the current canvas view in the mask editor", title: "Open the current canvas view in the mask editor",

View File

@@ -2,16 +2,17 @@
background-color: #444; background-color: #444;
border: 1px solid #555; border: 1px solid #555;
border-radius: 5px; border-radius: 5px;
color: #e0e0e0; color: #fff;
padding: 6px 14px; padding: 6px 14px;
font-size: 12px; font-size: 12px;
font-weight: 500; font-weight: 550;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
min-width: 80px; min-width: 80px;
text-align: center; text-align: center;
margin: 2px; margin: 2px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1); box-shadow: 0 1px 2px rgba(0,0,0,0.1);
text-shadow: 0 1px 2px rgb(0,0,0);
} }
.painter-button:hover { .painter-button:hover {
@@ -42,7 +43,7 @@
background-color: #3a76d6; background-color: #3a76d6;
border-color: #2a6ac4; border-color: #2a6ac4;
color: #fff; color: #fff;
text-shadow: none; text-shadow: 0 1px 2px rgb(0,0,0);
} }
.painter-button.primary:hover { .painter-button.primary:hover {
@@ -54,6 +55,7 @@
background-color: #4a7c59; background-color: #4a7c59;
border-color: #3a6c49; border-color: #3a6c49;
color: #fff; color: #fff;
text-shadow: 0 1px 2px rgb(0,0,0);
} }
.painter-button.success:hover { .painter-button.success:hover {
@@ -65,6 +67,7 @@
background-color: #c54747; background-color: #c54747;
border-color: #a53737; border-color: #a53737;
color: #fff; color: #fff;
text-shadow: 0 1px 2px rgb(0,0,0);
} }
.painter-button.danger:hover { .painter-button.danger:hover {
@@ -180,11 +183,11 @@
width: 90px; width: 90px;
height: 30px; height: 30px;
box-sizing: border-box; box-sizing: border-box;
background-color: #444; background: linear-gradient(to right, #5a5a5a 30%, #3a76d6);
border-radius: 5px; border-radius: 5px;
border: 1px solid #555; border: 1px solid #555;
cursor: pointer; cursor: pointer;
transition: background-color 0.3s ease-in-out; transition: background 0.3s ease-in-out, border-color 0.3s ease-in-out;
user-select: none; user-select: none;
padding: 0; padding: 0;
font-family: inherit; font-family: inherit;
@@ -192,11 +195,21 @@
box-shadow: 0 1px 2px rgba(0,0,0,0.1); box-shadow: 0 1px 2px rgba(0,0,0,0.1);
} }
.clipboard-switch:hover { .clipboard-switch:hover {
background-color: #555; background: linear-gradient(to right, #6a6a6a 30%, #4a86e4);
border-color: #666; border-color: #666;
box-shadow: 0 2px 4px rgba(0,0,0,0.15);
transform: translateY(-1px);
}
/* Mask switch: szaro-czarny gradient tylko dla maski */
.clipboard-switch.mask-switch {
background: linear-gradient(to right, #5a5a5a 30%, #e53935);
}
.clipboard-switch.mask-switch:hover {
background: linear-gradient(to right, #6a6a6a 30%, #ff5252);
} }
.clipboard-switch:active { .clipboard-switch:active {
background-color: #3a3a3a; background: linear-gradient(135deg, #3a76d6, #3a3a3a);
} }
.clipboard-switch input[type="checkbox"] { .clipboard-switch input[type="checkbox"] {
@@ -223,6 +236,14 @@
z-index: 2; z-index: 2;
} }
.clipboard-switch:hover .switch-knob {
background-color: #6a6a6a;
}
.clipboard-switch:hover .switch-knob {
background-color: #6a6a6a;
}
.clipboard-switch .switch-labels { .clipboard-switch .switch-labels {
position: absolute; position: absolute;
top: 0; top: 0;
@@ -232,11 +253,12 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-weight: 500; font-weight: 550;
color: #e0e0e0; color: #ffffff;
pointer-events: none; pointer-events: none;
z-index: 1; z-index: 1;
transition: opacity 0.3s ease-in-out; transition: opacity 0.3s ease-in-out;
text-shadow: 0 1px 2px rgb(0, 0, 0);
} }
.clipboard-switch .switch-labels .text-clipspace, .clipboard-switch .switch-labels .text-clipspace,
.clipboard-switch .switch-labels .text-system { .clipboard-switch .switch-labels .text-system {
@@ -261,20 +283,19 @@
/* Checked state */ /* Checked state */
.clipboard-switch:has(input:checked) { .clipboard-switch:has(input:checked) {
background-color: #3a76d6; background: linear-gradient(to right, #3a76d6, #5a5a5a 70%);
border-color: #2a6ac4; border-color: #2a6ac4;
} }
.clipboard-switch:has(input:checked):hover { .clipboard-switch:has(input:checked):hover {
background-color: #4a86e4; background: linear-gradient(to right, #4a86e4, #6a6a6a 70%);
border-color: #3a76d6; border-color: #3a76d6;
} }
.clipboard-switch input:checked ~ .switch-knob { .clipboard-switch input:checked ~ .switch-knob {
left: calc(100% - 26px); left: calc(100% - 26px);
background-color: #fff;
} }
.clipboard-switch input:checked ~ .switch-knob .switch-icon img { .clipboard-switch input:checked ~ .switch-knob .switch-icon img {
filter: invert(35%) sepia(100%) saturate(1500%) hue-rotate(200deg) brightness(90%) contrast(100%); filter: none;
} }
.clipboard-switch input:checked ~ .switch-labels .text-clipspace { .clipboard-switch input:checked ~ .switch-labels .text-clipspace {
opacity: 1; opacity: 1;