Rename canvas size methods and labels to output area

Refactored method and variable names from 'canvas size' to 'output area size' across multiple files for clarity. Updated UI labels and related function calls to reflect this terminology change.
This commit is contained in:
Dariusz L
2025-06-26 18:06:40 +02:00
parent 8b9edddc6a
commit dd6a9dfc85
5 changed files with 113 additions and 129 deletions

View File

@@ -241,8 +241,8 @@ export class Canvas {
this.saveState();
}
updateCanvasSize(width, height, saveHistory = true) {
return this.canvasLayers.updateCanvasSize(width, height, saveHistory);
updateOutputAreaSize(width, height, saveHistory = true) {
return this.canvasLayers.updateOutputAreaSize(width, height, saveHistory);
}
render() {

View File

@@ -680,7 +680,7 @@ export class CanvasInteractions {
const rectX = this.interaction.canvasResizeRect.x;
const rectY = this.interaction.canvasResizeRect.y;
this.canvas.updateCanvasSize(newWidth, newHeight);
this.canvas.updateOutputAreaSize(newWidth, newHeight);
this.canvas.layers.forEach(layer => {
layer.x -= rectX;

View File

@@ -5,8 +5,8 @@ import {withErrorHandling, createValidationError} from "./ErrorHandler.js";
const log = createModuleLogger('CanvasLayers');
export class CanvasLayers {
constructor(canvas) {
this.canvas = canvas;
constructor(canvasLayers) {
this.canvasLayers = canvasLayers;
this.blendModes = [
{name: 'normal', label: 'Normal'},
{name: 'multiply', label: 'Multiply'},
@@ -26,9 +26,10 @@ export class CanvasLayers {
this.isAdjustingOpacity = false;
this.internalClipboard = [];
}
async copySelectedLayers() {
if (this.canvas.selectedLayers.length === 0) return;
this.internalClipboard = this.canvas.selectedLayers.map(layer => ({...layer}));
if (this.canvasLayers.selectedLayers.length === 0) return;
this.internalClipboard = this.canvasLayers.selectedLayers.map(layer => ({...layer}));
log.info(`Copied ${this.internalClipboard.length} layer(s) to internal clipboard.`);
try {
const blob = await this.getFlattenedSelectionAsBlob();
@@ -44,23 +45,23 @@ export class CanvasLayers {
pasteLayers() {
if (this.internalClipboard.length === 0) return;
this.canvas.saveState();
this.canvasLayers.saveState();
const newLayers = [];
const pasteOffset = 20;
this.internalClipboard.forEach(clipboardLayer => {
const newLayer = {
...clipboardLayer,
x: clipboardLayer.x + pasteOffset / this.canvas.viewport.zoom,
y: clipboardLayer.y + pasteOffset / this.canvas.viewport.zoom,
zIndex: this.canvas.layers.length
x: clipboardLayer.x + pasteOffset / this.canvasLayers.viewport.zoom,
y: clipboardLayer.y + pasteOffset / this.canvasLayers.viewport.zoom,
zIndex: this.canvasLayers.layers.length
};
this.canvas.layers.push(newLayer);
this.canvasLayers.layers.push(newLayer);
newLayers.push(newLayer);
});
this.canvas.updateSelection(newLayers);
this.canvas.render();
this.canvasLayers.updateSelection(newLayers);
this.canvasLayers.render();
log.info(`Pasted ${newLayers.length} layer(s).`);
}
@@ -85,8 +86,8 @@ export class CanvasLayers {
const img = new Image();
img.onload = async () => {
await this.addLayerWithImage(img, {
x: this.canvas.lastMousePosition.x - img.width / 2,
y: this.canvas.lastMousePosition.y - img.height / 2,
x: this.canvasLayers.lastMousePosition.x - img.width / 2,
y: this.canvasLayers.lastMousePosition.y - img.height / 2,
});
};
img.src = event.target.result;
@@ -114,26 +115,26 @@ export class CanvasLayers {
log.debug("Adding layer with image:", image);
const imageId = generateUUID();
await saveImage(imageId, image.src);
this.canvas.imageCache.set(imageId, image.src);
this.canvasLayers.imageCache.set(imageId, image.src);
const layer = {
image: image,
imageId: imageId,
x: (this.canvas.width - image.width) / 2,
y: (this.canvas.height - image.height) / 2,
x: (this.canvasLayers.width - image.width) / 2,
y: (this.canvasLayers.height - image.height) / 2,
width: image.width,
height: image.height,
rotation: 0,
zIndex: this.canvas.layers.length,
zIndex: this.canvasLayers.layers.length,
blendMode: 'normal',
opacity: 1,
...layerProps
};
this.canvas.layers.push(layer);
this.canvas.updateSelection([layer]);
this.canvas.render();
this.canvas.saveState();
this.canvasLayers.layers.push(layer);
this.canvasLayers.updateSelection([layer]);
this.canvasLayers.render();
this.canvasLayers.saveState();
log.info("Layer added successfully");
return layer;
@@ -144,51 +145,51 @@ export class CanvasLayers {
}
async removeLayer(index) {
if (index >= 0 && index < this.canvas.layers.length) {
const layer = this.canvas.layers[index];
if (index >= 0 && index < this.canvasLayers.layers.length) {
const layer = this.canvasLayers.layers[index];
if (layer.imageId) {
const isImageUsedElsewhere = this.canvas.layers.some((l, i) => i !== index && l.imageId === layer.imageId);
const isImageUsedElsewhere = this.canvasLayers.layers.some((l, i) => i !== index && l.imageId === layer.imageId);
if (!isImageUsedElsewhere) {
await removeImage(layer.imageId);
this.canvas.imageCache.delete(layer.imageId);
this.canvasLayers.imageCache.delete(layer.imageId);
}
}
this.canvas.layers.splice(index, 1);
this.canvas.selectedLayer = this.canvas.layers[this.canvas.layers.length - 1] || null;
this.canvas.render();
this.canvasLayers.layers.splice(index, 1);
this.canvasLayers.selectedLayer = this.canvasLayers.layers[this.canvasLayers.layers.length - 1] || null;
this.canvasLayers.render();
}
}
moveLayer(fromIndex, toIndex) {
if (fromIndex >= 0 && fromIndex < this.canvas.layers.length &&
toIndex >= 0 && toIndex < this.canvas.layers.length) {
const layer = this.canvas.layers.splice(fromIndex, 1)[0];
this.canvas.layers.splice(toIndex, 0, layer);
this.canvas.render();
if (fromIndex >= 0 && fromIndex < this.canvasLayers.layers.length &&
toIndex >= 0 && toIndex < this.canvasLayers.layers.length) {
const layer = this.canvasLayers.layers.splice(fromIndex, 1)[0];
this.canvasLayers.layers.splice(toIndex, 0, layer);
this.canvasLayers.render();
}
}
moveLayerUp() {
if (this.canvas.selectedLayers.length === 0) return;
const selectedIndicesSet = new Set(this.canvas.selectedLayers.map(layer => this.canvas.layers.indexOf(layer)));
if (this.canvasLayers.selectedLayers.length === 0) return;
const selectedIndicesSet = new Set(this.canvasLayers.selectedLayers.map(layer => this.canvasLayers.layers.indexOf(layer)));
const sortedIndices = Array.from(selectedIndicesSet).sort((a, b) => b - a);
sortedIndices.forEach(index => {
const targetIndex = index + 1;
if (targetIndex < this.canvas.layers.length && !selectedIndicesSet.has(targetIndex)) {
[this.canvas.layers[index], this.canvas.layers[targetIndex]] = [this.canvas.layers[targetIndex], this.canvas.layers[index]];
if (targetIndex < this.canvasLayers.layers.length && !selectedIndicesSet.has(targetIndex)) {
[this.canvasLayers.layers[index], this.canvasLayers.layers[targetIndex]] = [this.canvasLayers.layers[targetIndex], this.canvasLayers.layers[index]];
}
});
this.canvas.layers.forEach((layer, i) => layer.zIndex = i);
this.canvas.render();
this.canvas.saveState();
this.canvasLayers.layers.forEach((layer, i) => layer.zIndex = i);
this.canvasLayers.render();
this.canvasLayers.saveState();
}
moveLayerDown() {
if (this.canvas.selectedLayers.length === 0) return;
const selectedIndicesSet = new Set(this.canvas.selectedLayers.map(layer => this.canvas.layers.indexOf(layer)));
if (this.canvasLayers.selectedLayers.length === 0) return;
const selectedIndicesSet = new Set(this.canvasLayers.selectedLayers.map(layer => this.canvasLayers.layers.indexOf(layer)));
const sortedIndices = Array.from(selectedIndicesSet).sort((a, b) => a - b);
@@ -196,17 +197,17 @@ export class CanvasLayers {
const targetIndex = index - 1;
if (targetIndex >= 0 && !selectedIndicesSet.has(targetIndex)) {
[this.canvas.layers[index], this.canvas.layers[targetIndex]] = [this.canvas.layers[targetIndex], this.canvas.layers[index]];
[this.canvasLayers.layers[index], this.canvasLayers.layers[targetIndex]] = [this.canvasLayers.layers[targetIndex], this.canvasLayers.layers[index]];
}
});
this.canvas.layers.forEach((layer, i) => layer.zIndex = i);
this.canvas.render();
this.canvas.saveState();
this.canvasLayers.layers.forEach((layer, i) => layer.zIndex = i);
this.canvasLayers.render();
this.canvasLayers.saveState();
}
getLayerAtPosition(worldX, worldY) {
for (let i = this.canvas.layers.length - 1; i >= 0; i--) {
const layer = this.canvas.layers[i];
for (let i = this.canvasLayers.layers.length - 1; i >= 0; i--) {
const layer = this.canvasLayers.layers[i];
const centerX = layer.x + layer.width / 2;
const centerY = layer.y + layer.height / 2;
@@ -232,27 +233,10 @@ export class CanvasLayers {
return null;
}
resizeLayer(scale) {
this.canvas.selectedLayers.forEach(layer => {
layer.width *= scale;
layer.height *= scale;
});
this.canvas.render();
this.canvas.saveState();
}
rotateLayer(angle) {
this.canvas.selectedLayers.forEach(layer => {
layer.rotation += angle;
});
this.canvas.render();
this.canvas.saveState();
}
async mirrorHorizontal() {
if (this.canvas.selectedLayers.length === 0) return;
if (this.canvasLayers.selectedLayers.length === 0) return;
const promises = this.canvas.selectedLayers.map(layer => {
const promises = this.canvasLayers.selectedLayers.map(layer => {
return new Promise(resolve => {
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
@@ -273,14 +257,14 @@ export class CanvasLayers {
});
await Promise.all(promises);
this.canvas.render();
this.canvas.saveState();
this.canvasLayers.render();
this.canvasLayers.saveState();
}
async mirrorVertical() {
if (this.canvas.selectedLayers.length === 0) return;
if (this.canvasLayers.selectedLayers.length === 0) return;
const promises = this.canvas.selectedLayers.map(layer => {
const promises = this.canvasLayers.selectedLayers.map(layer => {
return new Promise(resolve => {
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
@@ -301,8 +285,8 @@ export class CanvasLayers {
});
await Promise.all(promises);
this.canvas.render();
this.canvas.saveState();
this.canvasLayers.render();
this.canvasLayers.saveState();
}
async getLayerImageData(layer) {
@@ -340,21 +324,21 @@ export class CanvasLayers {
}
updateCanvasSize(width, height, saveHistory = true) {
updateOutputAreaSize(width, height, saveHistory = true) {
if (saveHistory) {
this.canvas.saveState();
this.canvasLayers.saveState();
}
this.canvas.width = width;
this.canvas.height = height;
this.canvas.maskTool.resize(width, height);
this.canvasLayers.width = width;
this.canvasLayers.height = height;
this.canvasLayers.maskTool.resize(width, height);
this.canvas.canvas.width = width;
this.canvas.canvas.height = height;
this.canvasLayers.canvasLayers.width = width;
this.canvasLayers.canvasLayers.height = height;
this.canvas.render();
this.canvasLayers.render();
if (saveHistory) {
this.canvas.saveStateToDB();
this.canvasLayers.saveStateToDB();
}
}
@@ -367,18 +351,18 @@ export class CanvasLayers {
width: image.width,
height: image.height,
rotation: 0,
zIndex: this.canvas.layers.length
zIndex: this.canvasLayers.layers.length
};
this.canvas.layers.push(layer);
this.canvas.selectedLayer = layer;
this.canvas.render();
this.canvasLayers.layers.push(layer);
this.canvasLayers.selectedLayer = layer;
this.canvasLayers.render();
}
isRotationHandle(x, y) {
if (!this.canvas.selectedLayer) return false;
if (!this.canvasLayers.selectedLayer) return false;
const handleX = this.canvas.selectedLayer.x + this.canvas.selectedLayer.width / 2;
const handleY = this.canvas.selectedLayer.y - 20;
const handleX = this.canvasLayers.selectedLayer.x + this.canvasLayers.selectedLayer.width / 2;
const handleY = this.canvasLayers.selectedLayer.y - 20;
const handleRadius = 5;
return Math.sqrt(Math.pow(x - handleX, 2) + Math.pow(y - handleY, 2)) <= handleRadius;
@@ -404,7 +388,7 @@ export class CanvasLayers {
'sw': {x: -halfW, y: halfH},
'w': {x: -halfW, y: 0},
'nw': {x: -halfW, y: -halfH},
'rot': {x: 0, y: -halfH - 20 / this.canvas.viewport.zoom}
'rot': {x: 0, y: -halfH - 20 / this.canvasLayers.viewport.zoom}
};
const worldHandles = {};
@@ -419,11 +403,11 @@ export class CanvasLayers {
}
getHandleAtPosition(worldX, worldY) {
if (this.canvas.selectedLayers.length === 0) return null;
if (this.canvasLayers.selectedLayers.length === 0) return null;
const handleRadius = 8 / this.canvas.viewport.zoom;
for (let i = this.canvas.selectedLayers.length - 1; i >= 0; i--) {
const layer = this.canvas.selectedLayers[i];
const handleRadius = 8 / this.canvasLayers.viewport.zoom;
for (let i = this.canvasLayers.selectedLayers.length - 1; i >= 0; i--) {
const layer = this.canvasLayers.selectedLayers[i];
const handles = this.getHandles(layer);
for (const key in handles) {
@@ -439,17 +423,17 @@ export class CanvasLayers {
}
getResizeHandle(x, y) {
if (!this.canvas.selectedLayer) return null;
if (!this.canvasLayers.selectedLayer) return null;
const handleRadius = 5;
const handles = {
'nw': {x: this.canvas.selectedLayer.x, y: this.canvas.selectedLayer.y},
'ne': {x: this.canvas.selectedLayer.x + this.canvas.selectedLayer.width, y: this.canvas.selectedLayer.y},
'nw': {x: this.canvasLayers.selectedLayer.x, y: this.canvasLayers.selectedLayer.y},
'ne': {x: this.canvasLayers.selectedLayer.x + this.canvasLayers.selectedLayer.width, y: this.canvasLayers.selectedLayer.y},
'se': {
x: this.canvas.selectedLayer.x + this.canvas.selectedLayer.width,
y: this.canvas.selectedLayer.y + this.canvas.selectedLayer.height
x: this.canvasLayers.selectedLayer.x + this.canvasLayers.selectedLayer.width,
y: this.canvasLayers.selectedLayer.y + this.canvasLayers.selectedLayer.height
},
'sw': {x: this.canvas.selectedLayer.x, y: this.canvas.selectedLayer.y + this.canvas.selectedLayer.height}
'sw': {x: this.canvasLayers.selectedLayer.x, y: this.canvasLayers.selectedLayer.y + this.canvasLayers.selectedLayer.height}
};
for (const [position, point] of Object.entries(handles)) {
@@ -500,14 +484,14 @@ export class CanvasLayers {
slider.min = '0';
slider.max = '100';
slider.value = this.canvas.selectedLayer.opacity ? Math.round(this.canvas.selectedLayer.opacity * 100) : 100;
slider.value = this.canvasLayers.selectedLayer.opacity ? Math.round(this.canvasLayers.selectedLayer.opacity * 100) : 100;
slider.style.cssText = `
width: 100%;
margin: 5px 0;
display: none;
`;
if (this.canvas.selectedLayer.blendMode === mode.name) {
if (this.canvasLayers.selectedLayer.blendMode === mode.name) {
slider.style.display = 'block';
option.style.backgroundColor = '#3a3a3a';
}
@@ -523,35 +507,35 @@ export class CanvasLayers {
slider.style.display = 'block';
option.style.backgroundColor = '#3a3a3a';
if (this.canvas.selectedLayer) {
this.canvas.selectedLayer.blendMode = mode.name;
this.canvas.render();
if (this.canvasLayers.selectedLayer) {
this.canvasLayers.selectedLayer.blendMode = mode.name;
this.canvasLayers.render();
}
};
slider.addEventListener('input', () => {
if (this.canvas.selectedLayer) {
this.canvas.selectedLayer.opacity = slider.value / 100;
this.canvas.render();
if (this.canvasLayers.selectedLayer) {
this.canvasLayers.selectedLayer.opacity = slider.value / 100;
this.canvasLayers.render();
}
});
slider.addEventListener('change', async () => {
if (this.canvas.selectedLayer) {
this.canvas.selectedLayer.opacity = slider.value / 100;
this.canvas.render();
if (this.canvasLayers.selectedLayer) {
this.canvasLayers.selectedLayer.opacity = slider.value / 100;
this.canvasLayers.render();
const saveWithFallback = async (fileName) => {
try {
const uniqueFileName = generateUniqueFileName(fileName, this.canvas.node.id);
return await this.canvas.saveToServer(uniqueFileName);
const uniqueFileName = generateUniqueFileName(fileName, this.canvasLayers.node.id);
return await this.canvasLayers.saveToServer(uniqueFileName);
} catch (error) {
console.warn(`Failed to save with unique name, falling back to original: ${fileName}`, error);
return await this.canvas.saveToServer(fileName);
return await this.canvasLayers.saveToServer(fileName);
}
};
await saveWithFallback(this.canvas.widget.value);
if (this.canvas.node) {
await saveWithFallback(this.canvasLayers.widget.value);
if (this.canvasLayers.node) {
app.graph.runStep();
}
}
@@ -613,11 +597,11 @@ export class CanvasLayers {
async getFlattenedCanvasAsBlob() {
return new Promise((resolve, reject) => {
const tempCanvas = document.createElement('canvas');
tempCanvas.width = this.canvas.width;
tempCanvas.height = this.canvas.height;
tempCanvas.width = this.canvasLayers.width;
tempCanvas.height = this.canvasLayers.height;
const tempCtx = tempCanvas.getContext('2d');
const sortedLayers = [...this.canvas.layers].sort((a, b) => a.zIndex - b.zIndex);
const sortedLayers = [...this.canvasLayers.layers].sort((a, b) => a.zIndex - b.zIndex);
sortedLayers.forEach(layer => {
if (!layer.image) return;
@@ -650,13 +634,13 @@ export class CanvasLayers {
});
}
async getFlattenedSelectionAsBlob() {
if (this.canvas.selectedLayers.length === 0) {
if (this.canvasLayers.selectedLayers.length === 0) {
return null;
}
return new Promise((resolve) => {
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
this.canvas.selectedLayers.forEach(layer => {
this.canvasLayers.selectedLayers.forEach(layer => {
const centerX = layer.x + layer.width / 2;
const centerY = layer.y + layer.height / 2;
const rad = layer.rotation * Math.PI / 180;
@@ -698,7 +682,7 @@ export class CanvasLayers {
tempCtx.translate(-minX, -minY);
const sortedSelection = [...this.canvas.selectedLayers].sort((a, b) => a.zIndex - b.zIndex);
const sortedSelection = [...this.canvasLayers.selectedLayers].sort((a, b) => a.zIndex - b.zIndex);
sortedSelection.forEach(layer => {
if (!layer.image) return;

View File

@@ -55,8 +55,8 @@ export class CanvasState {
zoom: 0.8
};
this.canvas.updateCanvasSize(this.canvas.width, this.canvas.height, false);
log.debug(`Canvas resized to ${this.canvas.width}x${this.canvas.height} and viewport set.`);
this.canvas.updateOutputAreaSize(this.canvas.width, this.canvas.height, false);
log.debug(`Output Area resized to ${this.canvas.width}x${this.canvas.height} and viewport set.`);
const loadedLayers = await this._loadLayers(savedState.layers);
this.canvas.layers = loadedLayers.filter(l => l !== null);
log.info(`Loaded ${this.canvas.layers.length} layers.`);

View File

@@ -406,7 +406,7 @@ async function createCanvasWidget(node, widget, app) {
$el("div.painter-separator"),
$el("div.painter-button-group", {}, [
$el("button.painter-button", {
textContent: "Canvas Size",
textContent: "Output Area Size",
onclick: () => {
const dialog = $el("div.painter-dialog", {
style: {
@@ -479,7 +479,7 @@ async function createCanvasWidget(node, widget, app) {
document.getElementById('confirm-size').onclick = () => {
const width = parseInt(document.getElementById('canvas-width').value) || canvas.width;
const height = parseInt(document.getElementById('canvas-height').value) || canvas.height;
canvas.updateCanvasSize(width, height);
canvas.updateOutputAreaSize(width, height);
document.body.removeChild(dialog);
};