From 66f106203790a8e13808188775fa2c5bec901334 Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Tue, 17 Dec 2024 02:28:05 +0100 Subject: [PATCH 1/2] Refactor GlyphsSearch into GlyphsSearchFiled and GlyphsSearchList --- ...lyphs-search.js => glyphs-search-field.js} | 71 ++---------- .../web-components/glyphs-search-list.js | 109 ++++++++++++++++++ src/fontra/views/editor/editor.html | 2 +- src/fontra/views/editor/editor.js | 4 +- src/fontra/views/editor/panel-glyph-search.js | 8 +- 5 files changed, 123 insertions(+), 71 deletions(-) rename src/fontra/client/web-components/{glyphs-search.js => glyphs-search-field.js} (62%) create mode 100644 src/fontra/client/web-components/glyphs-search-list.js diff --git a/src/fontra/client/web-components/glyphs-search.js b/src/fontra/client/web-components/glyphs-search-field.js similarity index 62% rename from src/fontra/client/web-components/glyphs-search.js rename to src/fontra/client/web-components/glyphs-search-field.js index 1500606524..9273a7699e 100644 --- a/src/fontra/client/web-components/glyphs-search.js +++ b/src/fontra/client/web-components/glyphs-search-field.js @@ -1,20 +1,14 @@ import { themeColorCSS } from "./theme-support.js"; -import { UIList } from "./ui-list.js"; import * as html from "/core/html-utils.js"; import { UnlitElement } from "/core/html-utils.js"; import { translate } from "/core/localization.js"; -import { - getCharFromCodePoint, - guessCharFromGlyphName, - makeUPlusStringFromCodePoint, -} from "/core/utils.js"; const colors = { "search-input-foreground-color": ["black", "white"], "search-input-background-color": ["#eee", "#333"], }; -export class GlyphsSearch extends UnlitElement { +export class GlyphsSearchField extends UnlitElement { static styles = ` ${themeColorCSS(colors)} @@ -43,9 +37,10 @@ export class GlyphsSearch extends UnlitElement { } `; - constructor() { + constructor(glyphsListItemsController, controllerKey) { super(); - + this.glyphsListItemsController = glyphsListItemsController; + this.controllerKey = controllerKey; this.searchField = html.input({ type: "text", placeholder: translate("sidebar.glyphs.search"), @@ -53,50 +48,6 @@ export class GlyphsSearch extends UnlitElement { oninput: (event) => this._searchFieldChanged(event), }); - const columnDescriptions = [ - { - key: "char", - title: " ", - width: "1.8em", - cellFactory: (item, description) => { - if (item.unicodes[0]) { - return getCharFromCodePoint(item.unicodes[0]); - } - const guessedChar = guessCharFromGlyphName(item.glyphName); - return guessedChar ? html.span({ class: "guessed-char" }, [guessedChar]) : ""; - }, - }, - { key: "glyphName", title: "glyph name", width: "10em", isIdentifierKey: true }, - { - key: "unicode", - width: "fit-content", - get: (item) => item.unicodes.map(makeUPlusStringFromCodePoint).join(","), - }, - ]; - this.glyphNamesList = new UIList(); - this.glyphNamesList.appendStyle(` - .guessed-char { - color: #999; - } - `); - this.glyphNamesList.columnDescriptions = columnDescriptions; - - this.glyphNamesList.addEventListener("listSelectionChanged", () => { - const event = new CustomEvent("selectedGlyphNameChanged", { - bubbles: false, - detail: this.getSelectedGlyphName(), - }); - this.dispatchEvent(event); - }); - - this.glyphNamesList.addEventListener("rowDoubleClicked", () => { - const event = new CustomEvent("selectedGlyphNameDoubleClicked", { - bubbles: false, - detail: this.getSelectedGlyphName(), - }); - this.dispatchEvent(event); - }); - this._glyphNamesListFilterFunc = (item) => true; // pass all through this.glyphMap = {}; @@ -107,7 +58,7 @@ export class GlyphsSearch extends UnlitElement { } render() { - return [this.searchField, this.glyphNamesList]; + return this.searchField; } get glyphMap() { @@ -119,14 +70,6 @@ export class GlyphsSearch extends UnlitElement { this.updateGlyphNamesListContent(); } - getSelectedGlyphName() { - return this.glyphNamesList.items[this.glyphNamesList.selectedItemIndex]?.glyphName; - } - - getFilteredGlyphNames() { - return this.glyphNamesList.items.map((item) => item.glyphName); - } - updateGlyphNamesListContent() { const glyphMap = this.glyphMap; this.glyphsListItems = []; @@ -155,11 +98,11 @@ export class GlyphsSearch extends UnlitElement { const filteredGlyphItems = this.glyphsListItems.filter( this._glyphNamesListFilterFunc ); - this.glyphNamesList.setItems(filteredGlyphItems); + this.glyphsListItemsController.model[this.controllerKey] = filteredGlyphItems; } } -customElements.define("glyphs-search", GlyphsSearch); +customElements.define("glyphs-search-field", GlyphsSearchField); function glyphItemSortFunc(item1, item2) { const uniCmp = compare(item1.unicodes[0], item2.unicodes[0]); diff --git a/src/fontra/client/web-components/glyphs-search-list.js b/src/fontra/client/web-components/glyphs-search-list.js new file mode 100644 index 0000000000..e7b1f29301 --- /dev/null +++ b/src/fontra/client/web-components/glyphs-search-list.js @@ -0,0 +1,109 @@ +import { GlyphsSearchField } from "./glyphs-search-field.js"; +import { UIList } from "./ui-list.js"; +import * as html from "/core/html-utils.js"; +import { UnlitElement } from "/core/html-utils.js"; +import { ObservableController } from "/core/observable-object.js"; +import { + getCharFromCodePoint, + guessCharFromGlyphName, + makeUPlusStringFromCodePoint, + throttleCalls, +} from "/core/utils.js"; + +export class GlyphsSearchList extends UnlitElement { + constructor() { + super(); + this.glyphsListItemsController = new ObservableController({ + glyphsListItems: [], + }); + + this.searchField = new GlyphsSearchField( + this.glyphsListItemsController, + "glyphsListItems" + ); + this.glyphNamesList = this.getGlyphNamesList(); + + this.throttledUpdate = throttleCalls(() => this.update(), 50); + } + + getGlyphNamesList() { + const columnDescriptions = [ + { + key: "char", + title: " ", + width: "1.8em", + cellFactory: (item, description) => { + if (item.unicodes[0]) { + return getCharFromCodePoint(item.unicodes[0]); + } + const guessedChar = guessCharFromGlyphName(item.glyphName); + return guessedChar ? html.span({ class: "guessed-char" }, [guessedChar]) : ""; + }, + }, + { key: "glyphName", title: "glyph name", width: "10em", isIdentifierKey: true }, + { + key: "unicode", + width: "fit-content", + get: (item) => item.unicodes.map(makeUPlusStringFromCodePoint).join(","), + }, + ]; + const glyphNamesList = new UIList(); + glyphNamesList.appendStyle(` + .guessed-char { + color: #999; + } + `); + glyphNamesList.columnDescriptions = columnDescriptions; + + glyphNamesList.addEventListener("listSelectionChanged", () => { + const event = new CustomEvent("selectedGlyphNameChanged", { + bubbles: false, + detail: this.getSelectedGlyphName(), + }); + this.dispatchEvent(event); + }); + + glyphNamesList.addEventListener("rowDoubleClicked", () => { + const event = new CustomEvent("selectedGlyphNameDoubleClicked", { + bubbles: false, + detail: this.getSelectedGlyphName(), + }); + this.dispatchEvent(event); + }); + return glyphNamesList; + } + + focusSearchField() { + this.searchField.focus(); + } + + async update() { + this.glyphNamesList.setItems(this.glyphsListItemsController.model.glyphsListItems); + } + + async render() { + this.glyphsListItemsController.addKeyListener( + "glyphsListItems", + this.throttledUpdate + ); + return [this.searchField, this.glyphNamesList]; + } + + get glyphMap() { + return this.searchField._glyphMap; + } + + set glyphMap(glyphMap) { + this.searchField.glyphMap = glyphMap; + } + + getSelectedGlyphName() { + return this.glyphNamesList.items[this.glyphNamesList.selectedItemIndex]?.glyphName; + } + + getFilteredGlyphNames() { + return this.glyphNamesList.items.map((item) => item.glyphName); + } +} + +customElements.define("glyphs-search-list", GlyphsSearchList); diff --git a/src/fontra/views/editor/editor.html b/src/fontra/views/editor/editor.html index 60cd679c8c..9781bbc606 100644 --- a/src/fontra/views/editor/editor.html +++ b/src/fontra/views/editor/editor.html @@ -16,7 +16,7 @@ - + diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 41d9bd6125..6e82ac646b 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -3148,7 +3148,7 @@ export class EditorController { usedBy.map((glyphName) => [glyphName, this.fontController.glyphMap[glyphName]]) ); - const glyphsSearch = document.createElement("glyphs-search"); + const glyphsSearch = document.createElement("glyphs-search-list"); glyphsSearch.glyphMap = glyphMap; glyphsSearch.addEventListener("selectedGlyphNameDoubleClicked", (event) => { @@ -3223,7 +3223,7 @@ export class EditorController { titleLabel = translate("dialog.glyphs.search"), okLabel = translate("dialog.add") ) { - const glyphsSearch = document.createElement("glyphs-search"); + const glyphsSearch = document.createElement("glyphs-search-list"); glyphsSearch.glyphMap = this.fontController.glyphMap; glyphsSearch.addEventListener("selectedGlyphNameChanged", (event) => { diff --git a/src/fontra/views/editor/panel-glyph-search.js b/src/fontra/views/editor/panel-glyph-search.js index 27dd130623..d1b112d725 100644 --- a/src/fontra/views/editor/panel-glyph-search.js +++ b/src/fontra/views/editor/panel-glyph-search.js @@ -18,7 +18,7 @@ export default class GlyphSearchPanel extends Panel { constructor(editorController) { super(editorController); - this.glyphsSearch = this.contentElement.querySelector("#glyphs-search"); + this.glyphsSearch = this.contentElement.querySelector("#glyphs-search-list"); this.glyphsSearch.addEventListener("selectedGlyphNameChanged", (event) => this.glyphNameChangedCallback(event.detail) ); @@ -65,8 +65,8 @@ export default class GlyphSearchPanel extends Panel { class: "glyph-search", }, [ - html.createDomElement("glyphs-search", { - id: "glyphs-search", + html.createDomElement("glyphs-search-list", { + id: "glyphs-search-list", }), ] ); @@ -74,7 +74,7 @@ export default class GlyphSearchPanel extends Panel { async toggle(on, focus) { if (on && focus) { - const glyphsSearch = this.contentElement.querySelector("#glyphs-search"); + const glyphsSearch = this.contentElement.querySelector("#glyphs-search-list"); glyphsSearch.focusSearchField(); } } From 8eff649d2b8ecb3f5df5c0c5420ef9b18665ca8b Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Wed, 18 Dec 2024 01:15:13 +0100 Subject: [PATCH 2/2] Rename getGlyphNamesList to makeGlyphNamesList --- src/fontra/client/web-components/glyphs-search-list.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fontra/client/web-components/glyphs-search-list.js b/src/fontra/client/web-components/glyphs-search-list.js index e7b1f29301..44f0d06c95 100644 --- a/src/fontra/client/web-components/glyphs-search-list.js +++ b/src/fontra/client/web-components/glyphs-search-list.js @@ -21,12 +21,12 @@ export class GlyphsSearchList extends UnlitElement { this.glyphsListItemsController, "glyphsListItems" ); - this.glyphNamesList = this.getGlyphNamesList(); + this.glyphNamesList = this.makeGlyphNamesList(); this.throttledUpdate = throttleCalls(() => this.update(), 50); } - getGlyphNamesList() { + makeGlyphNamesList() { const columnDescriptions = [ { key: "char",