diff --git a/src/fontra/client/lang/en.json b/src/fontra/client/lang/en.json index ec5182dd3..6fd16e93c 100644 --- a/src/fontra/client/lang/en.json +++ b/src/fontra/client/lang/en.json @@ -115,7 +115,7 @@ "sidebar.referencefont.customcharacter": "Custom character", "sidebar.referencefont.info": "Drop one or more .ttf, .otf, .woff or .woff2 files in the field below", "sidebar.referencefont.language": "Language", - "sidebar.related-glyphs": "Related Glyphs", + "sidebar.related-glyphs": "Related Glyphs & Characters", "sidebar.selection-info": "Selection Info", "sidebar.selection-info.advance-width": "Advance width", "sidebar.selection-info.component": "Component #%0", diff --git a/src/fontra/client/lang/zh-CN.json b/src/fontra/client/lang/zh-CN.json index 0cf432935..07f4a01b1 100644 --- a/src/fontra/client/lang/zh-CN.json +++ b/src/fontra/client/lang/zh-CN.json @@ -115,7 +115,7 @@ "sidebar.referencefont.customcharacter": "自定义字符", "sidebar.referencefont.info": "将一个或多个.ttf、.otf、.woff或.woff2字体文件拖放到下面的方框内", "sidebar.referencefont.language": "语言", - "sidebar.related-glyphs": "Related Glyphs", + "sidebar.related-glyphs": "Related Glyphs & Characters", "sidebar.selection-info": "选区信息", "sidebar.selection-info.advance-width": "步进宽度", "sidebar.selection-info.component": "组件 #%0", diff --git a/src/fontra/client/web-components/glyph-cell.js b/src/fontra/client/web-components/glyph-cell.js index 58ce81018..e97870043 100644 --- a/src/fontra/client/web-components/glyph-cell.js +++ b/src/fontra/client/web-components/glyph-cell.js @@ -58,6 +58,7 @@ export class GlyphCell extends UnlitElement { text-overflow: ellipsis; text-wrap: nowrap; text-align: center; + word-break: keep-all; } .glyph-status-color { diff --git a/src/fontra/views/editor/panel-related-glyphs.js b/src/fontra/views/editor/panel-related-glyphs.js index 96871de24..8b31f74e7 100644 --- a/src/fontra/views/editor/panel-related-glyphs.js +++ b/src/fontra/views/editor/panel-related-glyphs.js @@ -26,6 +26,11 @@ export default class RelatedGlyphPanel extends Panel { padding: 1em 1em 0 1em; text-wrap: wrap; } + + .no-related-glyphs { + color: #AAA; + padding-top: 1em; + } `; constructor(editorController) { @@ -69,35 +74,30 @@ export default class RelatedGlyphPanel extends Panel { open: true, content: html.div({ class: "related-glyphs-accordion-item" }, []), getRelatedGlyphsFunc: getRelatedGlyphsByExtension, - noGlyphsString: "No alternate glyphs were found", }, { label: "Components used by this glyph", open: true, content: html.div({ class: "related-glyphs-accordion-item" }, []), getRelatedGlyphsFunc: getComponentGlyphs, - noGlyphsString: "No component glyphs were found", }, { label: "Glyphs using this glyph as a component", open: true, content: html.div({ class: "related-glyphs-accordion-item" }, []), getRelatedGlyphsFunc: getUsedByGlyphs, - noGlyphsString: "No glyphs were found that use this glyph", }, { label: "Character decomposition", open: true, content: html.div({ class: "related-glyphs-accordion-item" }, []), getRelatedGlyphsFunc: getUnicodeDecomposed, - noGlyphsString: "No decomposition information was found", }, { label: "Characters that decompose with this character", open: true, content: html.div({ class: "related-glyphs-accordion-item" }, []), getRelatedGlyphsFunc: getUnicodeUsedBy, - noGlyphsString: "No characters were found that use this character", }, ]; @@ -133,11 +133,26 @@ export default class RelatedGlyphPanel extends Panel { character && character != glyphName ? `“${character}”, ${glyphName}` : glyphName; this.relatedGlyphsHeaderElement.innerHTML = glyphName - ? `Related glyphs for ${displayGlyphString}` - : `Related glyphs (no glyph selected)`; + ? `Related glyphs & characters for ${displayGlyphString}` + : `Related glyphs & characters`; + + const results = []; for (const item of this.accordion.items) { - this._updateAccordionItem(item, glyphName, codePoint); // No await + this._updateAccordionItem(item, glyphName, codePoint).then((hasResult) => { + results.push(hasResult); + if (results.length === this.accordion.items.length) { + if (!results.some((hasResult) => hasResult)) { + this.relatedGlyphsHeaderElement.appendChild( + html.div({ class: "no-related-glyphs" }, [ + glyphName + ? "(No related glyphs or characters were found)" + : "(No glyph selected)", + ]) + ); + } + } + }); } this.accordion.hidden = !glyphName; @@ -145,7 +160,10 @@ export default class RelatedGlyphPanel extends Panel { async _updateAccordionItem(item, glyphName, codePoint) { const element = item.content; + const parent = findParentWithClass(element, "ui-accordion-item"); + element.innerHTML = ""; + let hideAccordionItem = true; if (glyphName) { element.appendChild(html.span({ class: "placeholder-label" }, ["(loading)"])); const relatedGlyphs = await item.getRelatedGlyphsFunc( @@ -153,8 +171,9 @@ export default class RelatedGlyphPanel extends Panel { glyphName, codePoint ); - element.innerHTML = ""; + if (relatedGlyphs?.length) { + const documentFragment = document.createDocumentFragment(); for (const { glyphName, codePoints } of relatedGlyphs) { const glyphCell = new GlyphCell( this.fontController, @@ -168,14 +187,24 @@ export default class RelatedGlyphPanel extends Panel { this.handleContextMenu(event, glyphCell, item) ); - element.appendChild(glyphCell); + documentFragment.appendChild(glyphCell); } + element.innerHTML = ""; + element.appendChild(documentFragment); + + // At least in Chrome, we need to reset the scroll position, but it doesn't + // work if we do it right away, only after the next event iteration. + setTimeout(() => { + element.scrollTop = 0; + }, 0); + + hideAccordionItem = false; } else { - element.appendChild( - html.span({ class: "placeholder-label" }, [item.noGlyphsString]) - ); + element.innerHTML = ""; } } + parent.hidden = hideAccordionItem; + return !hideAccordionItem; } handleDoubleClick(event, glyphCell) { @@ -309,4 +338,12 @@ function addCharInfo(fontController, glyphNames) { }); } +function findParentWithClass(element, parentClass) { + let parent = element; + do { + parent = parent.parentElement; + } while (parent && !parent.classList.contains(parentClass)); + return parent; +} + customElements.define("panel-related-glyph", RelatedGlyphPanel);