Prettified Code!

This commit is contained in:
zero01101 2024-08-31 15:40:35 +00:00 committed by GitHub Action
parent 54ad744d61
commit 32f38d9b1d
4 changed files with 264 additions and 206 deletions

View file

@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html lang="en-US"> <html lang="en-US">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />

View file

@ -23,11 +23,15 @@ const commands = makeReadOnly(
_types: {}, _types: {},
/** @type {Observer<{n: int, cancel: function}>} */ /** @type {Observer<{n: int, cancel: function}>} */
get onundo() { return this._onundo; }, get onundo() {
return this._onundo;
},
_onundo: new Observer(), _onundo: new Observer(),
/** @type {Observer<{n: int, cancel: function}>} */ /** @type {Observer<{n: int, cancel: function}>} */
get onredo() { return this._onredo; }, get onredo() {
return this._onredo;
},
_onredo: new Observer(), _onredo: new Observer(),
/** /**
@ -38,8 +42,10 @@ const commands = makeReadOnly(
async undo(n = 1) { async undo(n = 1) {
var cancelled = false; var cancelled = false;
await this._onundo.emit({ await this._onundo.emit({
n:n, n: n,
cancel: ()=>{cancelled=true;}, cancel: () => {
cancelled = true;
},
}); });
if (cancelled) return; if (cancelled) return;
for (var i = 0; i < n && this.current > -1; i++) { for (var i = 0; i < n && this.current > -1; i++) {
@ -61,8 +67,10 @@ const commands = makeReadOnly(
async redo(n = 1) { async redo(n = 1) {
let cancelled = false; let cancelled = false;
await this._onredo.emit({ await this._onredo.emit({
n:n, n: n,
cancel: ()=>{cancelled=true;}, cancel: () => {
cancelled = true;
},
}); });
if (cancelled) return; if (cancelled) return;
for (var i = 0; i < n && this.current + 1 < this._history.length; i++) { for (var i = 0; i < n && this.current + 1 < this._history.length; i++) {

View file

@ -45,7 +45,10 @@ const selectTransformTool = () =>
keyboard.onShortcut({key: "Enter"}, state.entercb); keyboard.onShortcut({key: "Enter"}, state.entercb);
keyboard.onShortcut({shift: true, key: "Enter"}, state.sentercb); keyboard.onShortcut({shift: true, key: "Enter"}, state.sentercb);
keyboard.onShortcut({ctrl: true, key: "Enter"}, state.ctentercb); keyboard.onShortcut({ctrl: true, key: "Enter"}, state.ctentercb);
keyboard.onShortcut({ctrl: true, shift: true, key: "Enter"}, state.sctentercb); keyboard.onShortcut(
{ctrl: true, shift: true, key: "Enter"},
state.sctentercb
);
keyboard.onShortcut({key: "Delete"}, state.delcb); keyboard.onShortcut({key: "Delete"}, state.delcb);
keyboard.onShortcut({shift: true, key: "Delete"}, state.sdelcb); keyboard.onShortcut({shift: true, key: "Delete"}, state.sdelcb);
@ -82,13 +85,13 @@ const selectTransformTool = () =>
keyboard.deleteShortcut(state.ctrlvcb, "KeyV"); keyboard.deleteShortcut(state.ctrlvcb, "KeyV");
keyboard.deleteShortcut(state.ctrlxcb, "KeyX"); keyboard.deleteShortcut(state.ctrlxcb, "KeyX");
keyboard.deleteShortcut(state.togglemirror, "Equal"); keyboard.deleteShortcut(state.togglemirror, "Equal");
keyboard.deleteShortcut(state.entercb,"Enter"); keyboard.deleteShortcut(state.entercb, "Enter");
keyboard.deleteShortcut(state.sentercb,"Enter"); keyboard.deleteShortcut(state.sentercb, "Enter");
keyboard.deleteShortcut(state.ctentercb,"Enter"); keyboard.deleteShortcut(state.ctentercb, "Enter");
keyboard.deleteShortcut(state.sctentercb,"Enter"); keyboard.deleteShortcut(state.sctentercb, "Enter");
keyboard.deleteShortcut(state.delcb,"Delete"); keyboard.deleteShortcut(state.delcb, "Delete");
keyboard.deleteShortcut(state.sdelcb,"Delete"); keyboard.deleteShortcut(state.sdelcb, "Delete");
keyboard.deleteShortcut(state.escapecb,"Escape"); keyboard.deleteShortcut(state.escapecb, "Escape");
uil.onactive.clear(state.uilayeractivecb); uil.onactive.clear(state.uilayeractivecb);
@ -214,17 +217,18 @@ const selectTransformTool = () =>
}; };
// Undo/Redo Handling, reset state before Undo/Redo // Undo/Redo Handling, reset state before Undo/Redo
state.undocb= (undo)=>{ state.undocb = (undo) => {
if (state.selected){ if (state.selected) {
// Cancel so undo shortcut effectively undoes the current transform, unless requesting multiple steps // Cancel so undo shortcut effectively undoes the current transform, unless requesting multiple steps
if (state.selectionTransformed() && undo.n<=1) if (state.selectionTransformed() && undo.n <= 1) undo.cancel();
undo.cancel();
state.reset(false); state.reset(false);
} }
} };
state.redocb= (redo)=>{ state.redocb = (redo) => {
if (state.selected){ state.reset(false); } if (state.selected) {
} state.reset(false);
}
};
// Mirroring // Mirroring
state.togglemirror = () => { state.togglemirror = () => {
@ -305,18 +309,20 @@ const selectTransformTool = () =>
}; };
// Check if selection has been transformed in any way. // Check if selection has been transformed in any way.
state.selectionTransformed = ()=>{ state.selectionTransformed = () => {
return state.selected && return (
!( state.selected &&
state.selected.rotation === 0 && !(
state.selected.scale.x === 1 && state.selected.rotation === 0 &&
state.selected.scale.y === 1 && state.selected.scale.x === 1 &&
state.selected.position.x === state.original.sx && state.selected.scale.y === 1 &&
state.selected.position.y === state.original.sy && state.selected.position.x === state.original.sx &&
!state.mirrorSelection && state.selected.position.y === state.original.sy &&
state.original.layer === uil.layer !state.mirrorSelection &&
state.original.layer === uil.layer
)
); );
} };
// Handles left mouse double clicks - Select All Ctrl-A // Handles left mouse double clicks - Select All Ctrl-A
// Holding shift key - Ctrl-Shift-A // Holding shift key - Ctrl-Shift-A
@ -325,13 +331,15 @@ const selectTransformTool = () =>
if (state.selected || evn.evn.ctrlKey) return; if (state.selected || evn.evn.ctrlKey) return;
let shift = evn.evn.shiftKey; let shift = evn.evn.shiftKey;
// Wait so clickcb doesn't immediately deselect. // Wait so clickcb doesn't immediately deselect.
state.dclickcb_timeout = state.dclickcb_timeout ?? window.setTimeout(async ()=>{ state.dclickcb_timeout =
state.dclickcb_timeout = null; state.dclickcb_timeout ??
if (!state.selected && !selection.exists) { window.setTimeout(async () => {
if (shift) state.ctrlsacb(evn); state.dclickcb_timeout = null;
else state.ctrlacb(evn); if (!state.selected && !selection.exists) {
} if (shift) state.ctrlsacb(evn);
},300); else state.ctrlacb(evn);
}
}, 300);
}; };
// Handles right mouse double clicks - Select topmost layer with content under pointer // Handles right mouse double clicks - Select topmost layer with content under pointer
@ -340,25 +348,32 @@ const selectTransformTool = () =>
if (state.selected) return; if (state.selected) return;
// If shift key is held, and current layer is has visible pixels under pointer // If shift key is held, and current layer is has visible pixels under pointer
// select topmost visible layer beneath the active layer // select topmost visible layer beneath the active layer
let shift = evn.evn.shiftKey let shift =
&& !uil.active.hidden evn.evn.shiftKey &&
&& !isCanvasBlank(evn.x,evn.y,2,2,uil.active.canvas); !uil.active.hidden &&
!isCanvasBlank(evn.x, evn.y, 2, 2, uil.active.canvas);
let layer = shift ? uil.active : null; let layer = shift ? uil.active : null;
for (let l of uil.layers.toReversed()) { for (let l of uil.layers.toReversed()) {
if (shift) { if (shift) {
if (layer==l) shift = false; if (layer == l) shift = false;
} } else if (
else if (!l.hidden && !isCanvasBlank(evn.x,evn.y,2,2,l.canvas)){ !l.hidden &&
!isCanvasBlank(evn.x, evn.y, 2, 2, l.canvas)
) {
layer = l; layer = l;
break; break;
} }
} }
if (layer) { if (layer) {
uil.active=layer; uil.active = layer;
state.dclickcb_timeout = state.dclickcb_timeout ?? window.setTimeout(async ()=>{ state.dclickcb_timeout =
state.dclickcb_timeout = null; state.dclickcb_timeout ??
if (!state.selected && !selection.exists) { state.ctrlacb(evn); } window.setTimeout(async () => {
},300); state.dclickcb_timeout = null;
if (!state.selected && !selection.exists) {
state.ctrlacb(evn);
}
}, 300);
} }
}; };
@ -536,50 +551,57 @@ const selectTransformTool = () =>
state.reset(); state.reset();
}; };
state.keydowncb = (evn) => { }; state.keydowncb = (evn) => {};
// Keyboard callbacks // Keyboard callbacks
state.keyclickcb = (evn) => { }; state.keyclickcb = (evn) => {};
// Register Delete Shortcut // Register Delete Shortcut
state.delcb = (evn) => { state.applyTransform(true,false,false,false); }; state.delcb = (evn) => {
state.applyTransform(true, false, false, false);
};
// Register Escape Shortcut // Register Escape Shortcut
state.escapecb = (evn) => { state.reset(false); }; state.escapecb = (evn) => {
state.reset(false);
};
// Register Shift-Delete Shortcut - Delete Outside Selection and Apply // Register Shift-Delete Shortcut - Delete Outside Selection and Apply
state.sdelcb = (evn) => { state.applyTransform(false,true,false,false); }; state.sdelcb = (evn) => {
state.applyTransform(false, true, false, false);
};
// Register Enter Shortcut - Apply Transform (Delegates to clickcb) // Register Enter Shortcut - Apply Transform (Delegates to clickcb)
state.entercb = (evn) => { state.clickcb(evn); }; state.entercb = (evn) => {
state.clickcb(evn);
};
// Register Ctrl-Enter Shortcut - Copy Selection to new layer, restore original // Register Ctrl-Enter Shortcut - Copy Selection to new layer, restore original
state.ctentercb = (evn) => { state.applyTransform(false,false,true,true); }; state.ctentercb = (evn) => {
state.applyTransform(false, false, true, true);
};
// Register Shift-Enter Shortcut - Move Selection to new layer // Register Shift-Enter Shortcut - Move Selection to new layer
state.sentercb = (evn) => { state.applyTransform(false,false,true,false); }; state.sentercb = (evn) => {
state.applyTransform(false, false, true, false);
};
// Register Ctrl-Shift-Enter Shortcut - Copy Visible Selection to new layer // Register Ctrl-Shift-Enter Shortcut - Copy Visible Selection to new layer
state.sctentercb = async (evn) => { state.sctentercb = async (evn) => {
var selectBB = var selectBB =
state.selected.bb != undefined state.selected.bb != undefined ? state.selected.bb : state.backupBB;
? state.selected.bb
: state.backupBB;
const canvas = uil.getVisible(selectBB, { const canvas = uil.getVisible(selectBB, {
categories: ["image", "user", "select-display"], categories: ["image", "user", "select-display"],
}); });
await commands.runCommand("addLayer", "Added Layer"); await commands.runCommand("addLayer", "Added Layer");
await commands.runCommand("drawImage", "Transform Tool Apply", await commands.runCommand("drawImage", "Transform Tool Apply", {
{ image: canvas,
image: canvas, ...selectBB,
...selectBB, });
}
);
state.reset(false); state.reset(false);
}; };
// Register Ctrl-A Shortcut // Register Ctrl-A Shortcut
state.ctrlacb = () => { state.ctrlacb = () => {
state.reset(false); // Reset to preserve selected content state.reset(false); // Reset to preserve selected content
@ -717,25 +739,38 @@ const selectTransformTool = () =>
// newLayer defaults to null, overriding the forced variants if explicitly set to false // newLayer defaults to null, overriding the forced variants if explicitly set to false
// Only checks if Selection exists and content has been selected // Only checks if Selection exists and content has been selected
// Does not check if content has been transformed, eg for deletion/applying to new layer // Does not check if content has been transformed, eg for deletion/applying to new layer
state.applyTransform = async (eraseSelected = false, clearLayer = false, newLayer = null, keepOriginal = false) => { state.applyTransform = async (
const isBlank = !state.selected || eraseSelected = false,
isCanvasBlank( 0, 0, state.selected.canvas.width, state.selected.canvas.height, state.selected.canvas); clearLayer = false,
newLayer = null,
// Just reset state if nothing is selected, unless Clearing layer keepOriginal = false
if (!state.selected || !clearLayer && isBlank ){ ) => {
state.reset(false); const isBlank =
return; !state.selected ||
} isCanvasBlank(
0,
// Put original image back 0,
state.original.layer.ctx.drawImage( state.selected.canvas.width,
state.selected.canvas, state.selected.canvas.height,
state.original.x, state.selected.canvas
state.original.y
); );
// Erase Entire Layer // Just reset state if nothing is selected, unless Clearing layer
if (clearLayer) await commands.runCommand( if (!state.selected || (!clearLayer && isBlank)) {
state.reset(false);
return;
}
// Put original image back
state.original.layer.ctx.drawImage(
state.selected.canvas,
state.original.x,
state.original.y
);
// Erase Entire Layer
if (clearLayer)
await commands.runCommand(
"eraseImage", "eraseImage",
"Transform Tool Erase", "Transform Tool Erase",
{ {
@ -748,8 +783,9 @@ const selectTransformTool = () =>
}, },
} }
); );
// Erase Original Selection Area // Erase Original Selection Area
else if (eraseSelected || !keepOriginal) await commands.runCommand( else if (eraseSelected || !keepOriginal)
await commands.runCommand(
"eraseImage", "eraseImage",
"Transform Tool Erase", "Transform Tool Erase",
{ {
@ -766,57 +802,56 @@ const selectTransformTool = () =>
} }
); );
// Selection erased or was blank, no need to draw anything // Selection erased or was blank, no need to draw anything
if (eraseSelected || isBlank){ if (eraseSelected || isBlank) {
state.reset(true);
return;
}
// Draw Image
const {canvas, bb} = cropCanvas(state.originalDisplayLayer.canvas, {
border: 10,
});
if ( (newLayer ?? state.toNewLayer) && !clearLayer)
await commands.runCommand("addLayer", "Added Layer");
let commandLog = "";
const addline = (v, newline = true) => {
commandLog += v;
if (newline) commandLog += "\n";
};
addline(
`Draw selected area to x: ${bb.x}, y: ${bb.y}, width: ${bb.w}, height: ${bb.h} to layer ${state.original.layer.id}`
);
addline(
` - translation: (x: ${state.selected.position.x}, y: ${state.selected.position.y})`
);
addline(
` - rotation : ${
Math.round(1000 * ((180 * state.selected.rotation) / Math.PI)) /
1000
} degrees`,
false
);
await commands.runCommand(
"drawImage",
"Transform Tool Apply",
{
image: canvas,
...bb,
},
{
extra: {
log: commandLog,
},
}
);
state.reset(true); state.reset(true);
} return;
}
// Draw Image
const {canvas, bb} = cropCanvas(state.originalDisplayLayer.canvas, {
border: 10,
});
if ((newLayer ?? state.toNewLayer) && !clearLayer)
await commands.runCommand("addLayer", "Added Layer");
let commandLog = "";
const addline = (v, newline = true) => {
commandLog += v;
if (newline) commandLog += "\n";
};
addline(
`Draw selected area to x: ${bb.x}, y: ${bb.y}, width: ${bb.w}, height: ${bb.h} to layer ${state.original.layer.id}`
);
addline(
` - translation: (x: ${state.selected.position.x}, y: ${state.selected.position.y})`
);
addline(
` - rotation : ${
Math.round(1000 * ((180 * state.selected.rotation) / Math.PI)) /
1000
} degrees`,
false
);
await commands.runCommand(
"drawImage",
"Transform Tool Apply",
{
image: canvas,
...bb,
},
{
extra: {
log: commandLog,
},
}
);
state.reset(true);
};
}, },
populateContextMenu: (menu, state) => { populateContextMenu: (menu, state) => {
if (!state.ctxmenu) { if (!state.ctxmenu) {
@ -942,17 +977,20 @@ const selectTransformTool = () =>
const copyNewLayerButton = document.createElement("button"); const copyNewLayerButton = document.createElement("button");
copyNewLayerButton.classList.add("button", "tool"); copyNewLayerButton.classList.add("button", "tool");
copyNewLayerButton.textContent = "Layer"; copyNewLayerButton.textContent = "Layer";
copyNewLayerButton.title = "Copies selection to a new Layer (Ctrl+Enter)"; copyNewLayerButton.title =
copyNewLayerButton.onclick = () => { state.applyTransform(false,false,true,true); }; "Copies selection to a new Layer (Ctrl+Enter)";
copyNewLayerButton.onclick = () => {
state.applyTransform(false, false, true, true);
};
// Dummy button for saving active selection // Dummy button for saving active selection
const ActiveSelectionButton = document.createElement("button"); const ActiveSelectionButton = document.createElement("button");
ActiveSelectionButton.classList.add("button", "tool"); ActiveSelectionButton.classList.add("button", "tool");
ActiveSelectionButton.textContent = "📄"; ActiveSelectionButton.textContent = "📄";
ActiveSelectionButton.title = "Commands Applied to the Current Selection"; ActiveSelectionButton.title =
"Commands Applied to the Current Selection";
ActiveSelectionButton.disabled = true; ActiveSelectionButton.disabled = true;
actionArray.appendChild(saveSelectionButton); actionArray.appendChild(saveSelectionButton);
actionArray.appendChild(createResourceButton); actionArray.appendChild(createResourceButton);
actionArray.appendChild(copyNewLayerButton); actionArray.appendChild(copyNewLayerButton);
@ -966,7 +1004,8 @@ const selectTransformTool = () =>
const saveVisibleSelectionButton = document.createElement("button"); const saveVisibleSelectionButton = document.createElement("button");
saveVisibleSelectionButton.classList.add("button", "tool"); saveVisibleSelectionButton.classList.add("button", "tool");
saveVisibleSelectionButton.innerHTML = "Save&nbsp;Vis."; // nbsp as a quick hack for unwanted text wrapping saveVisibleSelectionButton.innerHTML = "Save&nbsp;Vis."; // nbsp as a quick hack for unwanted text wrapping
saveVisibleSelectionButton.title = "Saves Visible Selection And Download"; saveVisibleSelectionButton.title =
"Saves Visible Selection And Download";
saveVisibleSelectionButton.onclick = () => { saveVisibleSelectionButton.onclick = () => {
console.debug(state.selected); console.debug(state.selected);
console.debug(state.selected.bb); console.debug(state.selected.bb);
@ -1009,14 +1048,18 @@ const selectTransformTool = () =>
const copyVisNewLayerButton = document.createElement("button"); const copyVisNewLayerButton = document.createElement("button");
copyVisNewLayerButton.classList.add("button", "tool"); copyVisNewLayerButton.classList.add("button", "tool");
copyVisNewLayerButton.textContent = "Layer"; copyVisNewLayerButton.textContent = "Layer";
copyVisNewLayerButton.title = "Copies Visible Selection to a new Layer (Ctrl+Shift+Enter)"; copyVisNewLayerButton.title =
copyVisNewLayerButton.onclick = (e) => { state.sctentercb(e); }; "Copies Visible Selection to a new Layer (Ctrl+Shift+Enter)";
copyVisNewLayerButton.onclick = (e) => {
state.sctentercb(e);
};
// Dummy button for saving visible Selection // Dummy button for saving visible Selection
const VisibleSelectionButton = document.createElement("button"); const VisibleSelectionButton = document.createElement("button");
VisibleSelectionButton.classList.add("button", "tool"); VisibleSelectionButton.classList.add("button", "tool");
VisibleSelectionButton.textContent = "👁"; VisibleSelectionButton.textContent = "👁";
VisibleSelectionButton.title = "Commands Applied to All Visible Content In the Selected Area"; VisibleSelectionButton.title =
"Commands Applied to All Visible Content In the Selected Area";
VisibleSelectionButton.disabled = true; VisibleSelectionButton.disabled = true;
visibleActionArray.appendChild(saveVisibleSelectionButton); visibleActionArray.appendChild(saveVisibleSelectionButton);
@ -1031,22 +1074,30 @@ const selectTransformTool = () =>
const applyClearButton = document.createElement("button"); const applyClearButton = document.createElement("button");
applyClearButton.classList.add("button", "tool"); applyClearButton.classList.add("button", "tool");
applyClearButton.textContent = "Isolate"; applyClearButton.textContent = "Isolate";
applyClearButton.title = "Erases everything in the current layer outside the selection (Shift+Delete)"; applyClearButton.title =
applyClearButton.onclick = () => { state.applyTransform(false,true,false,false); }; "Erases everything in the current layer outside the selection (Shift+Delete)";
applyClearButton.onclick = () => {
state.applyTransform(false, true, false, false);
};
// Erase Button // Erase Button
const eraseSelectionButton = document.createElement("button"); const eraseSelectionButton = document.createElement("button");
eraseSelectionButton.classList.add("button", "tool"); eraseSelectionButton.classList.add("button", "tool");
eraseSelectionButton.textContent = "Erase"; eraseSelectionButton.textContent = "Erase";
eraseSelectionButton.title = "Erases current selection (Delete)"; eraseSelectionButton.title = "Erases current selection (Delete)";
eraseSelectionButton.onclick = () => { state.applyTransform(true,false,false,false); }; eraseSelectionButton.onclick = () => {
state.applyTransform(true, false, false, false);
};
// Apply To New Layer button // Apply To New Layer button
const applyNewLayerButton = document.createElement("button"); const applyNewLayerButton = document.createElement("button");
applyNewLayerButton.classList.add("button", "tool"); applyNewLayerButton.classList.add("button", "tool");
applyNewLayerButton.textContent = "Extract"; applyNewLayerButton.textContent = "Extract";
applyNewLayerButton.title = "Moves Selection to a New Layer (Shift+Enter)"; applyNewLayerButton.title =
applyNewLayerButton.onclick = () => { state.applyTransform(false,false,true,false); }; "Moves Selection to a New Layer (Shift+Enter)";
applyNewLayerButton.onclick = () => {
state.applyTransform(false, false, true, false);
};
actionArrayRow3.appendChild(applyClearButton); actionArrayRow3.appendChild(applyClearButton);
actionArrayRow3.appendChild(eraseSelectionButton); actionArrayRow3.appendChild(eraseSelectionButton);

View file

@ -72,4 +72,3 @@
</script> </script>
</body> </body>
</html> </html>