Skip to content

Commit

Permalink
Zoom and Pan: move helpers into its namespace to avoid littering glob…
Browse files Browse the repository at this point in the history
…al scope
  • Loading branch information
akx committed Jun 5, 2023
1 parent 9781f31 commit 8fd20bd
Showing 1 changed file with 95 additions and 97 deletions.
192 changes: 95 additions & 97 deletions extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js
Original file line number Diff line number Diff line change
@@ -1,121 +1,119 @@
// Helper functions
// Get active tab
function getActiveTab(elements, all = false) {
const tabs = elements.img2imgTabs.querySelectorAll("button");
onUiLoaded(async() => {
// Helper functions
// Get active tab
function getActiveTab(elements, all = false) {
const tabs = elements.img2imgTabs.querySelectorAll("button");

if (all) return tabs;
if (all) return tabs;

for (let tab of tabs) {
if (tab.classList.contains("selected")) {
return tab;
for (let tab of tabs) {
if (tab.classList.contains("selected")) {
return tab;
}
}
}
}

// Get tab ID
function getTabId(elements, elementIDs) {
const activeTab = getActiveTab(elements);
const tabIdLookup = {
"Sketch": elementIDs.sketch,
"Inpaint sketch": elementIDs.inpaintSketch,
"Inpaint": elementIDs.inpaint
};
return tabIdLookup[activeTab.innerText];
}

// Wait until opts loaded
async function waitForOpts() {
return new Promise(resolve => {
const checkInterval = setInterval(() => {
if (window.opts && Object.keys(window.opts).length !== 0) {
clearInterval(checkInterval);
resolve(window.opts);
}
}, 100);
});
}

// Check is hotkey valid
function isSingleLetter(value) {
return (
typeof value === "string" && value.length === 1 && /[a-z]/i.test(value)
);
}
// Get tab ID
function getTabId(elements, elementIDs) {
const activeTab = getActiveTab(elements);
const tabIdLookup = {
"Sketch": elementIDs.sketch,
"Inpaint sketch": elementIDs.inpaintSketch,
"Inpaint": elementIDs.inpaint
};
return tabIdLookup[activeTab.innerText];
}

// Create hotkeyConfig from opts
function createHotkeyConfig(defaultHotkeysConfig, hotkeysConfigOpts) {
const result = {};
const usedKeys = new Set();
// Wait until opts loaded
async function waitForOpts() {
return new Promise(resolve => {
const checkInterval = setInterval(() => {
if (window.opts && Object.keys(window.opts).length !== 0) {
clearInterval(checkInterval);
resolve(window.opts);
}
}, 100);
});
}

for (const key in defaultHotkeysConfig) {
if (typeof hotkeysConfigOpts[key] === "boolean") {
result[key] = hotkeysConfigOpts[key];
continue;
}
if (
hotkeysConfigOpts[key] &&
isSingleLetter(hotkeysConfigOpts[key]) &&
!usedKeys.has(hotkeysConfigOpts[key].toUpperCase())
) {
// If the property passed the test and has not yet been used, add 'Key' before it and save it
result[key] = "Key" + hotkeysConfigOpts[key].toUpperCase();
usedKeys.add(hotkeysConfigOpts[key].toUpperCase());
} else {
// If the property does not pass the test or has already been used, we keep the default value
console.error(
`Hotkey: ${hotkeysConfigOpts[key]} for ${key} is repeated and conflicts with another hotkey or is not 1 letter. The default hotkey is used: ${defaultHotkeysConfig[key][3]}`
);
result[key] = defaultHotkeysConfig[key];
}
// Check is hotkey valid
function isSingleLetter(value) {
return (
typeof value === "string" && value.length === 1 && /[a-z]/i.test(value)
);
}

return result;
}
// Create hotkeyConfig from opts
function createHotkeyConfig(defaultHotkeysConfig, hotkeysConfigOpts) {
const result = {};
const usedKeys = new Set();

/**
* The restoreImgRedMask function displays a red mask around an image to indicate the aspect ratio.
* If the image display property is set to 'none', the mask breaks. To fix this, the function
* temporarily sets the display property to 'block' and then hides the mask again after 300 milliseconds
* to avoid breaking the canvas. Additionally, the function adjusts the mask to work correctly on
* very long images.
*/
for (const key in defaultHotkeysConfig) {
if (typeof hotkeysConfigOpts[key] === "boolean") {
result[key] = hotkeysConfigOpts[key];
continue;
}
if (
hotkeysConfigOpts[key] &&
isSingleLetter(hotkeysConfigOpts[key]) &&
!usedKeys.has(hotkeysConfigOpts[key].toUpperCase())
) {
// If the property passed the test and has not yet been used, add 'Key' before it and save it
result[key] = "Key" + hotkeysConfigOpts[key].toUpperCase();
usedKeys.add(hotkeysConfigOpts[key].toUpperCase());
} else {
// If the property does not pass the test or has already been used, we keep the default value
console.error(
`Hotkey: ${hotkeysConfigOpts[key]} for ${key} is repeated and conflicts with another hotkey or is not 1 letter. The default hotkey is used: ${defaultHotkeysConfig[key][3]}`
);
result[key] = defaultHotkeysConfig[key];
}
}

function restoreImgRedMask(elements, elementIDs) {
const mainTabId = getTabId(elements, elementIDs);
return result;
}

if (!mainTabId) return;
/**
* The restoreImgRedMask function displays a red mask around an image to indicate the aspect ratio.
* If the image display property is set to 'none', the mask breaks. To fix this, the function
* temporarily sets the display property to 'block' and then hides the mask again after 300 milliseconds
* to avoid breaking the canvas. Additionally, the function adjusts the mask to work correctly on
* very long images.
*/
function restoreImgRedMask(elements, elementIDs) {
const mainTabId = getTabId(elements, elementIDs);

const mainTab = gradioApp().querySelector(mainTabId);
const img = mainTab.querySelector("img");
const imageARPreview = gradioApp().querySelector("#imageARPreview");
if (!mainTabId) return;

if (!img || !imageARPreview) return;
const mainTab = gradioApp().querySelector(mainTabId);
const img = mainTab.querySelector("img");
const imageARPreview = gradioApp().querySelector("#imageARPreview");

imageARPreview.style.transform = "";
if (parseFloat(mainTab.style.width) > 865) {
const transformString = mainTab.style.transform;
const scaleMatch = transformString.match(/scale\(([-+]?[0-9]*\.?[0-9]+)\)/);
let zoom = 1; // default zoom
if (!img || !imageARPreview) return;

if (scaleMatch && scaleMatch[1]) {
zoom = Number(scaleMatch[1]);
}
imageARPreview.style.transform = "";
if (parseFloat(mainTab.style.width) > 865) {
const transformString = mainTab.style.transform;
const scaleMatch = transformString.match(/scale\(([-+]?[0-9]*\.?[0-9]+)\)/);
let zoom = 1; // default zoom

imageARPreview.style.transformOrigin = "0 0";
imageARPreview.style.transform = `scale(${zoom})`;
}
if (scaleMatch && scaleMatch[1]) {
zoom = Number(scaleMatch[1]);
}

if (img.style.display !== "none") return;
imageARPreview.style.transformOrigin = "0 0";
imageARPreview.style.transform = `scale(${zoom})`;
}

img.style.display = "block";
if (img.style.display !== "none") return;

setTimeout(() => {
img.style.display = "none";
}, 400);
}
img.style.display = "block";

setTimeout(() => {
img.style.display = "none";
}, 400);
}

// Main
onUiLoaded(async() => {
const hotkeysConfigOpts = await waitForOpts();

// Default config
Expand Down

0 comments on commit 8fd20bd

Please sign in to comment.