From 2baa0dc50880c0bcffa7e76280a38cd8ae16c5ea Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 10:13:15 +0100 Subject: [PATCH 01/20] Add getUsedBy() remote method --- src/fontra/core/fonthandler.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/fontra/core/fonthandler.py b/src/fontra/core/fonthandler.py index a26f3d8f6..159c24495 100644 --- a/src/fontra/core/fonthandler.py +++ b/src/fontra/core/fonthandler.py @@ -226,6 +226,12 @@ def _getClientData(self, connection, key, default=None): def _setClientData(self, connection, key, value): self.clientData[connection.clientUUID][key] = value + @remoteMethod + async def getUsedBy(self, glyphName: str) -> list[str]: + if hasattr(self.backend, "getUsedBy"): + return await self.backend.getUsedBy(glyphName) + return [] + @remoteMethod async def subscribeChanges(self, pathOrPattern, wantLiveChanges, *, connection): pattern = _ensurePattern(pathOrPattern) From b27cb5cb72728289271a632c280880e2ffd69847 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 11:48:41 +0100 Subject: [PATCH 02/20] Fux remote method signature --- src/fontra/core/fonthandler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra/core/fonthandler.py b/src/fontra/core/fonthandler.py index 159c24495..0e7fee965 100644 --- a/src/fontra/core/fonthandler.py +++ b/src/fontra/core/fonthandler.py @@ -227,7 +227,7 @@ def _setClientData(self, connection, key, value): self.clientData[connection.clientUUID][key] = value @remoteMethod - async def getUsedBy(self, glyphName: str) -> list[str]: + async def getUsedBy(self, glyphName: str, *, connection) -> list[str]: if hasattr(self.backend, "getUsedBy"): return await self.backend.getUsedBy(glyphName) return [] From e9635d05d434095650427db7c36eb2d33eefac2b Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 11:53:29 +0100 Subject: [PATCH 03/20] Rename method --- src/fontra/core/fonthandler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fontra/core/fonthandler.py b/src/fontra/core/fonthandler.py index 0e7fee965..9cf85d88b 100644 --- a/src/fontra/core/fonthandler.py +++ b/src/fontra/core/fonthandler.py @@ -227,9 +227,9 @@ def _setClientData(self, connection, key, value): self.clientData[connection.clientUUID][key] = value @remoteMethod - async def getUsedBy(self, glyphName: str, *, connection) -> list[str]: - if hasattr(self.backend, "getUsedBy"): - return await self.backend.getUsedBy(glyphName) + async def getGlyphsUsedBy(self, glyphName: str, *, connection) -> list[str]: + if hasattr(self.backend, "getGlyphsUsedBy"): + return await self.backend.getGlyphsUsedBy(glyphName) return [] @remoteMethod From 1eb5f25ae37dd1220a0f3fdff67c1aa4520c2be9 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 11:54:18 +0100 Subject: [PATCH 04/20] Add getGlyphsUsedBy() method --- src/fontra/client/core/font-controller.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/fontra/client/core/font-controller.js b/src/fontra/client/core/font-controller.js index ac8bd3a05..e4963d33b 100644 --- a/src/fontra/client/core/font-controller.js +++ b/src/fontra/client/core/font-controller.js @@ -545,6 +545,11 @@ export class FontController { } } + async getGlyphsUsedBy(glyphName) { + // Ask the backend about which glyphs use glyph `glyphName` as a component + return await this.font.getGlyphsUsedBy(glyphName); + } + _purgeGlyphCache(glyphName) { this._glyphsPromiseCache.delete(glyphName); this._purgeInstanceCache(glyphName); From c87291aaf3b5476213f5804c4153ad50687ae40c Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 11:55:45 +0100 Subject: [PATCH 05/20] Remove unused methods --- src/fontra/core/fonthandler.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/fontra/core/fonthandler.py b/src/fontra/core/fonthandler.py index 9cf85d88b..187cfa1bd 100644 --- a/src/fontra/core/fonthandler.py +++ b/src/fontra/core/fonthandler.py @@ -408,16 +408,6 @@ async def scheduleDataWrite(self, writeKey, writeFunc, connection): self._processWritesEvent.set() # write: go! self._writingInProgressEvent.clear() - def iterGlyphMadeOf(self, glyphName): - for dependantGlyphName in self.glyphMadeOf.get(glyphName, ()): - yield dependantGlyphName - yield from self.iterGlyphMadeOf(dependantGlyphName) - - def iterGlyphUsedBy(self, glyphName): - for dependantGlyphName in self.glyphUsedBy.get(glyphName, ()): - yield dependantGlyphName - yield from self.iterGlyphUsedBy(dependantGlyphName) - def updateGlyphDependencies(self, glyphName, glyph): # Zap previous used-by data for this glyph, if any for componentName in self.glyphMadeOf.get(glyphName, ()): From 272ea571073dfbd2e6778a972fdb97850d83e885 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 11:56:26 +0100 Subject: [PATCH 06/20] Add Find used by context menu --- src/fontra/views/editor/editor.js | 71 ++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 480ad39a5..f05ba076b 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -792,6 +792,12 @@ export class EditorController { }, }); } + + this.glyphSelectedContextMenuItems.push({ + title: "Find glyphs used by this glyph", + enabled: () => true, + callback: () => this.doFindGlyphsUsedBy(), + }); } initShortCuts() { @@ -1447,7 +1453,7 @@ export class EditorController { const dialog = await dialogSetup("Add Component", null, [ { title: "Cancel", isCancelButton: true }, - { title: "Add", isDefaultButton: true, result: "ok", disabled: true }, + { title: "Add", isDefaultButton: true, resultValue: "ok", disabled: true }, ]); dialog.setContent(glyphsSearch); @@ -1553,6 +1559,69 @@ export class EditorController { this.sceneSettings.selectedSourceIndex = newSourceIndex; } + async doFindGlyphsUsedBy() { + const glyphName = this.sceneSettings.selectedGlyphName; + + const usedBy = await loaderSpinner(this.fontController.getGlyphsUsedBy(glyphName)); + if (!usedBy.length) { + await dialog(`Glyph '${glyphName}' is not used as a component anywhere.`, null, [ + { title: "Okay", resultValue: "ok" }, + ]); + return; + } else { + usedBy.sort(); + + const glyphMap = Object.fromEntries( + usedBy.map((glyphName) => [glyphName, this.fontController.glyphMap[glyphName]]) + ); + + const glyphsSearch = document.createElement("glyphs-search"); + glyphsSearch.glyphMap = glyphMap; + + // glyphsSearch.addEventListener("selectedGlyphNameChanged", (event) => { + // dialog.defaultButton.classList.toggle( + // "disabled", + // !glyphsSearch.getSelectedGlyphName() + // ); + // }); + + // glyphsSearch.addEventListener("selectedGlyphNameDoubleClicked", (event) => { + // dialog.defaultButton.click(); + // }); + + const dialog = await dialogSetup( + `Glyphs that use glyph '${glyphName}' as a component`, + null, + [ + { title: "Cancel", isCancelButton: true }, + { title: "Copy names", resultValue: "copy" }, + { + title: "Add to text", + isDefaultButton: true, + resultValue: "ok", + // disabled: true, + }, + ] + ); + + dialog.setContent(glyphsSearch); + + setTimeout(() => glyphsSearch.focusSearchField(), 0); // next event loop iteration + + switch (await dialog.run()) { + case "copy": + const glyphNamesString = usedBy + .map((glyphName) => "/" + glyphName) + .join("\n"); + const clipboardObject = { + "text/plain": glyphNamesString, + }; + await writeToClipboard(clipboardObject); + break; + } + } + } + keyUpHandler(event) { if (event.code === "Space") { this.spaceKeyUpHandler(); From 4919b27c25248153b825fdef20745a284e04e182 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 12:06:50 +0100 Subject: [PATCH 07/20] Rename iterGlyphXXX() methods, and add doc comments --- src/fontra/client/core/font-controller.js | 16 +++++++++------- src/fontra/views/editor/scene-model.js | 5 ++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/fontra/client/core/font-controller.js b/src/fontra/client/core/font-controller.js index e4963d33b..9848126c2 100644 --- a/src/fontra/client/core/font-controller.js +++ b/src/fontra/client/core/font-controller.js @@ -129,7 +129,7 @@ export class FontController { await this.getGlyph(glyphName); - for (const subGlyphName of this.iterGlyphMadeOf(glyphName)) { + for (const subGlyphName of this.iterGlyphsMadeOfRecursively(glyphName)) { todo.add(subGlyphName); } }; @@ -276,7 +276,7 @@ export class FontController { } async glyphChanged(glyphName, senderInfo) { - const glyphNames = [glyphName, ...this.iterGlyphUsedBy(glyphName)]; + const glyphNames = [glyphName, ...this.iterGlyphsUsedByRecursively(glyphName)]; for (const glyphName of glyphNames) { this._purgeInstanceCache(glyphName); } @@ -507,7 +507,8 @@ export class FontController { return cachedPattern; } - *iterGlyphMadeOf(glyphName, seenGlyphNames = null) { + *iterGlyphsMadeOfRecursively(glyphName, seenGlyphNames = null) { + // Yield the names of all glyphs that are used as a component in `glyphName`, recursively. if (!seenGlyphNames) { seenGlyphNames = new Set(); } else if (seenGlyphNames.has(glyphName)) { @@ -517,7 +518,7 @@ export class FontController { seenGlyphNames.add(glyphName); for (const dependantGlyphName of this.glyphMadeOf[glyphName] || []) { yield dependantGlyphName; - for (const deeperGlyphName of this.iterGlyphMadeOf( + for (const deeperGlyphName of this.iterGlyphsMadeOfRecursively( dependantGlyphName, seenGlyphNames )) { @@ -526,7 +527,8 @@ export class FontController { } } - *iterGlyphUsedBy(glyphName, seenGlyphNames = null) { + *iterGlyphsUsedByRecursively(glyphName, seenGlyphNames = null) { + // Yield the names of all *loaded* glyphs that use `glyphName` as a component, recursively. if (!seenGlyphNames) { seenGlyphNames = new Set(); } else if (seenGlyphNames.has(glyphName)) { @@ -536,7 +538,7 @@ export class FontController { seenGlyphNames.add(glyphName); for (const dependantGlyphName of this.glyphUsedBy[glyphName] || []) { yield dependantGlyphName; - for (const deeperGlyphName of this.iterGlyphUsedBy( + for (const deeperGlyphName of this.iterGlyphsUsedByRecursively( dependantGlyphName, seenGlyphNames )) { @@ -546,7 +548,7 @@ export class FontController { } async getGlyphsUsedBy(glyphName) { - // Ask the backend about which glyphs use glyph `glyphName` as a component + // Ask the backend about which glyphs use glyph `glyphName` as a component, non-recursively. return await this.font.getGlyphsUsedBy(glyphName); } diff --git a/src/fontra/views/editor/scene-model.js b/src/fontra/views/editor/scene-model.js index 4679f942f..ee49a3fbd 100644 --- a/src/fontra/views/editor/scene-model.js +++ b/src/fontra/views/editor/scene-model.js @@ -742,7 +742,10 @@ function getUsedGlyphNames(fontController, positionedLines) { for (const line of positionedLines) { for (const glyph of line.glyphs) { usedGlyphNames.add(glyph.glyph.name); - updateSet(usedGlyphNames, fontController.iterGlyphMadeOf(glyph.glyph.name)); + updateSet( + usedGlyphNames, + fontController.iterGlyphsMadeOfRecursively(glyph.glyph.name) + ); } } return usedGlyphNames; From b68e9a88d53fea06dd44300a05e3cc0d38694e37 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 12:09:23 +0100 Subject: [PATCH 08/20] Fix context menu title --- src/fontra/views/editor/editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index f05ba076b..5285c9bb8 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -794,7 +794,7 @@ export class EditorController { } this.glyphSelectedContextMenuItems.push({ - title: "Find glyphs used by this glyph", + title: "Find glyphs that use this glyph", enabled: () => true, callback: () => this.doFindGlyphsUsedBy(), }); From 7f7c02f07b5745feeef8af1cf249a2b3ccc9d274 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 12:21:13 +0100 Subject: [PATCH 09/20] Group glyph names in sets of 16 per line --- src/fontra/views/editor/editor.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 5285c9bb8..496e9487b 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -1610,9 +1610,11 @@ export class EditorController { switch (await dialog.run()) { case "copy": - const glyphNamesString = usedBy - .map((glyphName) => "/" + glyphName) + const glyphNamesString = chunks(usedBy, 16) + .map((chunked) => chunked.map((glyphName) => "/" + glyphName).join("")) .join("\n"); + // .map((glyphName) => "/" + glyphName) + // .join("\n"); const clipboardObject = { "text/plain": glyphNamesString, }; @@ -2064,3 +2066,11 @@ async function runDialogWholeGlyphPaste() { return result === "ok" ? controller.model.behavior : null; } + +function chunks(array, n) { + const chunked = []; + for (const i of range(0, array.length, n)) { + chunked.push(array.slice(i, i + n)); + } + return chunked; +} From 94c309fd2f3bf3c991a8b7744a62ab77d6edef67 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 12:25:41 +0100 Subject: [PATCH 10/20] Improve dialog text --- src/fontra/views/editor/editor.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 496e9487b..8c0570a52 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -1564,9 +1564,11 @@ export class EditorController { const usedBy = await loaderSpinner(this.fontController.getGlyphsUsedBy(glyphName)); if (!usedBy.length) { - await dialog(`Glyph '${glyphName}' is not used as a component anywhere.`, null, [ - { title: "Okay", resultValue: "ok" }, - ]); + await dialog( + `Glyph '${glyphName}' is not used as a component by any glyph.`, + null, + [{ title: "Okay", resultValue: "ok" }] + ); return; } else { usedBy.sort(); From d2ae7b64476f691eb3544ef3a53666d2b910cab3 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 15:09:47 +0100 Subject: [PATCH 11/20] Add backend info method, so we can gracefully enable/disable features --- src/fontra/client/core/font-controller.js | 1 + src/fontra/core/fonthandler.py | 7 +++++++ src/fontra/views/editor/editor.js | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/fontra/client/core/font-controller.js b/src/fontra/client/core/font-controller.js index 9848126c2..bc3fa9771 100644 --- a/src/fontra/client/core/font-controller.js +++ b/src/fontra/client/core/font-controller.js @@ -44,6 +44,7 @@ export class FontController { this._rootObject["unitsPerEm"] = await this.font.getUnitsPerEm(); this._rootObject["customData"] = await this.font.getCustomData(); this._rootClassDef = (await getClassSchema())["Font"]; + this.backendInfo = await await this.font.getBackEndInfo(); this._resolveInitialized(); } diff --git a/src/fontra/core/fonthandler.py b/src/fontra/core/fonthandler.py index 187cfa1bd..a3a6e71a3 100644 --- a/src/fontra/core/fonthandler.py +++ b/src/fontra/core/fonthandler.py @@ -147,6 +147,13 @@ async def useConnection(self, connection) -> AsyncGenerator[None, None]: if not self.connections and self.allConnectionsClosedCallback is not None: await self.allConnectionsClosedCallback() + @remoteMethod + async def getBackEndInfo(self, *, connection=None) -> dict: + features = {} + for key, methodName in [("glyphs-used-by", "getGlyphsUsedBy")]: + features[key] = hasattr(self.backend, methodName) + return dict(name=self.backend.__class__.__name__, features=features) + @remoteMethod async def getGlyph( self, glyphName: str, *, connection=None diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 8c0570a52..b2b95afb5 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -795,7 +795,7 @@ export class EditorController { this.glyphSelectedContextMenuItems.push({ title: "Find glyphs that use this glyph", - enabled: () => true, + enabled: () => this.fontController.backendInfo.features["glyphs-used-by"], callback: () => this.doFindGlyphsUsedBy(), }); } From bd3cdbd8811e06291b3feb14fc69773cf50dd067 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 15:30:14 +0100 Subject: [PATCH 12/20] factor out setting up glyph info; add glyphs from used-by dialog --- src/fontra/views/editor/editor.js | 41 +++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index b2b95afb5..c9675d135 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -619,11 +619,7 @@ export class EditorController { if (!glyphName) { return; } - const codePoint = this.fontController.codePointForGlyph(glyphName); - const glyphInfo = { glyphName: glyphName }; - if (codePoint !== undefined) { - glyphInfo["character"] = getCharFromUnicode(codePoint); - } + const glyphInfo = glyphInfoFromGlyphName(glyphName, this.fontController); let selectedGlyphState = this.sceneSettings.selectedGlyph; const glyphLines = [...this.sceneSettings.glyphLines]; if (selectedGlyphState) { @@ -678,12 +674,7 @@ export class EditorController { if (location) { localLocations[glyphName] = location; } - const glyphInfo = { glyphName: glyphName }; - const codePoint = this.fontController.codePointForGlyph(glyphName); - if (codePoint !== undefined) { - glyphInfo["character"] = getCharFromUnicode(codePoint); - } - glyphInfos.push(glyphInfo); + glyphInfos.push(glyphInfoFromGlyphName(glyphName, this.fontController)); } this.sceneController.updateLocalLocations(localLocations); const selectedGlyphInfo = this.sceneSettings.selectedGlyph; @@ -1600,7 +1591,7 @@ export class EditorController { { title: "Add to text", isDefaultButton: true, - resultValue: "ok", + resultValue: "add", // disabled: true, }, ] @@ -1611,7 +1602,7 @@ export class EditorController { setTimeout(() => glyphsSearch.focusSearchField(), 0); // next event loop iteration switch (await dialog.run()) { - case "copy": + case "copy": { const glyphNamesString = chunks(usedBy, 16) .map((chunked) => chunked.map((glyphName) => "/" + glyphName).join("")) .join("\n"); @@ -1622,6 +1613,21 @@ export class EditorController { }; await writeToClipboard(clipboardObject); break; + } + case "add": { + const glyphInfos = usedBy.map((glyphName) => + glyphInfoFromGlyphName(glyphName, this.fontController) + ); + const selectedGlyphInfo = this.sceneSettings.selectedGlyph; + const glyphLines = [...this.sceneSettings.glyphLines]; + glyphLines[selectedGlyphInfo.lineIndex].splice( + selectedGlyphInfo.glyphIndex + 1, + 0, + ...glyphInfos + ); + this.sceneSettings.glyphLines = glyphLines; + break; + } } } } @@ -2076,3 +2082,12 @@ function chunks(array, n) { } return chunked; } + +function glyphInfoFromGlyphName(glyphName, fontController) { + const glyphInfo = { glyphName: glyphName }; + const codePoint = fontController.codePointForGlyph(glyphName); + if (codePoint !== undefined) { + glyphInfo["character"] = getCharFromUnicode(codePoint); + } + return glyphInfo; +} From 9b46c12a7d0df608aa5ce36712f2c3a8c264daf0 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 15:33:06 +0100 Subject: [PATCH 13/20] Take selection into account --- src/fontra/views/editor/editor.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index c9675d135..ee1773053 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -1571,16 +1571,9 @@ export class EditorController { const glyphsSearch = document.createElement("glyphs-search"); glyphsSearch.glyphMap = glyphMap; - // glyphsSearch.addEventListener("selectedGlyphNameChanged", (event) => { - // dialog.defaultButton.classList.toggle( - // "disabled", - // !glyphsSearch.getSelectedGlyphName() - // ); - // }); - - // glyphsSearch.addEventListener("selectedGlyphNameDoubleClicked", (event) => { - // dialog.defaultButton.click(); - // }); + glyphsSearch.addEventListener("selectedGlyphNameDoubleClicked", (event) => { + dialog.defaultButton.click(); + }); const dialog = await dialogSetup( `Glyphs that use glyph '${glyphName}' as a component`, @@ -1615,7 +1608,10 @@ export class EditorController { break; } case "add": { - const glyphInfos = usedBy.map((glyphName) => + const glyphName = glyphsSearch.getSelectedGlyphName(); + const glyphNames = glyphName ? [glyphName] : usedBy; + + const glyphInfos = glyphNames.map((glyphName) => glyphInfoFromGlyphName(glyphName, this.fontController) ); const selectedGlyphInfo = this.sceneSettings.selectedGlyph; From be5b81581b17b6508bc1cabdd998a896d8b30a28 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 15:50:39 +0100 Subject: [PATCH 14/20] Make context menu title dynamic --- src/fontra/views/editor/editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index ee1773053..8ce11e977 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -785,7 +785,7 @@ export class EditorController { } this.glyphSelectedContextMenuItems.push({ - title: "Find glyphs that use this glyph", + title: () => `Find glyphs that use '${this.sceneSettings.selectedGlyphName}'`, enabled: () => this.fontController.backendInfo.features["glyphs-used-by"], callback: () => this.doFindGlyphsUsedBy(), }); From acdb4052a65a7abc7b37780b779b763edce47df9 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 15:54:03 +0100 Subject: [PATCH 15/20] redundant else: dedent --- src/fontra/views/editor/editor.js | 111 +++++++++++++++--------------- 1 file changed, 55 insertions(+), 56 deletions(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 8ce11e977..2e9b5575a 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -1561,69 +1561,68 @@ export class EditorController { [{ title: "Okay", resultValue: "ok" }] ); return; - } else { - usedBy.sort(); + } + usedBy.sort(); - const glyphMap = Object.fromEntries( - usedBy.map((glyphName) => [glyphName, this.fontController.glyphMap[glyphName]]) - ); + const glyphMap = Object.fromEntries( + usedBy.map((glyphName) => [glyphName, this.fontController.glyphMap[glyphName]]) + ); - const glyphsSearch = document.createElement("glyphs-search"); - glyphsSearch.glyphMap = glyphMap; + const glyphsSearch = document.createElement("glyphs-search"); + glyphsSearch.glyphMap = glyphMap; - glyphsSearch.addEventListener("selectedGlyphNameDoubleClicked", (event) => { - dialog.defaultButton.click(); - }); + glyphsSearch.addEventListener("selectedGlyphNameDoubleClicked", (event) => { + theDialog.defaultButton.click(); + }); - const dialog = await dialogSetup( - `Glyphs that use glyph '${glyphName}' as a component`, - null, - [ - { title: "Cancel", isCancelButton: true }, - { title: "Copy names", resultValue: "copy" }, - { - title: "Add to text", - isDefaultButton: true, - resultValue: "add", - // disabled: true, - }, - ] - ); + const theDialog = await dialogSetup( + `Glyphs that use glyph '${glyphName}' as a component`, + null, + [ + { title: "Cancel", isCancelButton: true }, + { title: "Copy names", resultValue: "copy" }, + { + title: "Add to text", + isDefaultButton: true, + resultValue: "add", + // disabled: true, + }, + ] + ); - dialog.setContent(glyphsSearch); + theDialog.setContent(glyphsSearch); - setTimeout(() => glyphsSearch.focusSearchField(), 0); // next event loop iteration + setTimeout(() => glyphsSearch.focusSearchField(), 0); // next event loop iteration - switch (await dialog.run()) { - case "copy": { - const glyphNamesString = chunks(usedBy, 16) - .map((chunked) => chunked.map((glyphName) => "/" + glyphName).join("")) - .join("\n"); - // .map((glyphName) => "/" + glyphName) - // .join("\n"); - const clipboardObject = { - "text/plain": glyphNamesString, - }; - await writeToClipboard(clipboardObject); - break; - } - case "add": { - const glyphName = glyphsSearch.getSelectedGlyphName(); - const glyphNames = glyphName ? [glyphName] : usedBy; - - const glyphInfos = glyphNames.map((glyphName) => - glyphInfoFromGlyphName(glyphName, this.fontController) - ); - const selectedGlyphInfo = this.sceneSettings.selectedGlyph; - const glyphLines = [...this.sceneSettings.glyphLines]; - glyphLines[selectedGlyphInfo.lineIndex].splice( - selectedGlyphInfo.glyphIndex + 1, - 0, - ...glyphInfos - ); - this.sceneSettings.glyphLines = glyphLines; - break; - } + switch (await theDialog.run()) { + case "copy": { + const glyphNamesString = chunks(usedBy, 16) + .map((chunked) => chunked.map((glyphName) => "/" + glyphName).join("")) + .join("\n"); + // .map((glyphName) => "/" + glyphName) + // .join("\n"); + const clipboardObject = { + "text/plain": glyphNamesString, + }; + await writeToClipboard(clipboardObject); + break; + } + case "add": { + const glyphName = glyphsSearch.getSelectedGlyphName(); + const glyphNames = glyphName ? [glyphName] : usedBy; + + const glyphInfos = glyphNames.map((glyphName) => + glyphInfoFromGlyphName(glyphName, this.fontController) + ); + const selectedGlyphInfo = this.sceneSettings.selectedGlyph; + const glyphLines = [...this.sceneSettings.glyphLines]; + glyphLines[selectedGlyphInfo.lineIndex].splice( + selectedGlyphInfo.glyphIndex + 1, + 0, + ...glyphInfos + ); + this.sceneSettings.glyphLines = glyphLines; + break; } } } From fac9ca6c706e9187f4e00d833aaebd4146f27d0f Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 15:54:14 +0100 Subject: [PATCH 16/20] Delete leftover --- src/fontra/views/editor/editor.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 2e9b5575a..e748f2af8 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -1599,8 +1599,6 @@ export class EditorController { const glyphNamesString = chunks(usedBy, 16) .map((chunked) => chunked.map((glyphName) => "/" + glyphName).join("")) .join("\n"); - // .map((glyphName) => "/" + glyphName) - // .join("\n"); const clipboardObject = { "text/plain": glyphNamesString, }; From 86ac8acabe085f1603cc8014454a2f4516979025 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 15:54:40 +0100 Subject: [PATCH 17/20] whitespace --- src/fontra/views/editor/editor.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index e748f2af8..eee38fb83 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -1554,6 +1554,7 @@ export class EditorController { const glyphName = this.sceneSettings.selectedGlyphName; const usedBy = await loaderSpinner(this.fontController.getGlyphsUsedBy(glyphName)); + if (!usedBy.length) { await dialog( `Glyph '${glyphName}' is not used as a component by any glyph.`, @@ -1562,6 +1563,7 @@ export class EditorController { ); return; } + usedBy.sort(); const glyphMap = Object.fromEntries( From a6bb56136da30212aa7717959854e56e930df92f Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 20:44:50 +0100 Subject: [PATCH 18/20] Fix double await --- src/fontra/client/core/font-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra/client/core/font-controller.js b/src/fontra/client/core/font-controller.js index bc3fa9771..8190d363c 100644 --- a/src/fontra/client/core/font-controller.js +++ b/src/fontra/client/core/font-controller.js @@ -44,7 +44,7 @@ export class FontController { this._rootObject["unitsPerEm"] = await this.font.getUnitsPerEm(); this._rootObject["customData"] = await this.font.getCustomData(); this._rootClassDef = (await getClassSchema())["Font"]; - this.backendInfo = await await this.font.getBackEndInfo(); + this.backendInfo = await this.font.getBackEndInfo(); this._resolveInitialized(); } From 1e22e16a4dda4b0dc26e5170185daa359e31b3c5 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 20:55:41 +0100 Subject: [PATCH 19/20] Don't insert unlimited glyphs: truncate (for now) to 100 --- src/fontra/views/editor/editor.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index eee38fb83..7b289368c 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -1609,7 +1609,13 @@ export class EditorController { } case "add": { const glyphName = glyphsSearch.getSelectedGlyphName(); - const glyphNames = glyphName ? [glyphName] : usedBy; + const MAX_NUM_GLYPHS = 100; + const truncate = !glyphName && usedBy.length > MAX_NUM_GLYPHS; + const glyphNames = glyphName + ? [glyphName] + : truncate + ? usedBy.slice(0, MAX_NUM_GLYPHS) + : usedBy; const glyphInfos = glyphNames.map((glyphName) => glyphInfoFromGlyphName(glyphName, this.fontController) @@ -1622,6 +1628,13 @@ export class EditorController { ...glyphInfos ); this.sceneSettings.glyphLines = glyphLines; + if (truncate) { + await dialog( + `The number of added glyphs was truncated to ${MAX_NUM_GLYPHS}`, + null, + [{ title: "Okay", resultValue: "ok" }] + ); + } break; } } From 31d66c8cf5c412cb3cb9fd554aa4b486a145cba7 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 18 Dec 2023 21:02:14 +0100 Subject: [PATCH 20/20] Remove dead code --- src/fontra/views/editor/editor.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 7b289368c..536b8622e 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -1587,7 +1587,6 @@ export class EditorController { title: "Add to text", isDefaultButton: true, resultValue: "add", - // disabled: true, }, ] );