From 07f54c92b299055175c439800c1d82907cfd3a42 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Thu, 26 Oct 2023 19:10:05 +0300 Subject: [PATCH 01/38] Initial implementation of menu-bar --- src/fontra/client/web-components/menu-bar.js | 88 ++++++++++++++++++ .../client/web-components/menu-panel.js | 2 +- src/fontra/views/plugins/plugins.html | 91 +++++++++++++++++++ 3 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 src/fontra/client/web-components/menu-bar.js diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js new file mode 100644 index 0000000000..25302db14c --- /dev/null +++ b/src/fontra/client/web-components/menu-bar.js @@ -0,0 +1,88 @@ +import * as html from "../core/html-utils.js"; +import { SimpleElement } from "../core/html-utils.js"; +import { MenuPanel } from "./menu-panel.js"; + +export class MenuBar extends SimpleElement { + static styles = ` + .menu-bar { + padding: 0.5rem 1rem; + align-items: center; + position: absolute; + } + + .menu-item { + padding: 0.5rem 1rem; + display: inline-block; + cursor: default; + user-select: none; + } + + .menu-item.current { + background: #e1e1e1; + border-radius: 5px; + } + `; + constructor(items = []) { + super(); + this._items = items; + this.contentElement = this.shadowRoot.appendChild(html.div()); + this.contentElement.classList.add("menu-bar"); + this.render(); + window.addEventListener("mousedown", this.clearCurrentSelection.bind(this)); + window.addEventListener("blur", this.clearCurrentSelection.bind(this)); + } + get items() { + return this._items; + } + set items(items) { + this._items = items; + this.render(); + } + clearCurrentSelection() { + const currentSelection = this.contentElement.querySelector(".current"); + if (!currentSelection) { + return false; + } + currentSelection.classList.remove("current"); + const menuPanel = this.contentElement.querySelector("menu-panel"); + if (menuPanel) { + this.contentElement.removeChild(menuPanel); + } + return true; + } + + showMenu(items, menuItemElement) { + menuItemElement.classList.add("current"); + const clientRect = menuItemElement.getBoundingClientRect(); + const menuPanel = new MenuPanel(items, { + x: clientRect.x, + y: clientRect.y + clientRect.height, + }); + this.contentElement.appendChild(menuPanel); + } + + render() { + const fragment = document.createDocumentFragment(); + for (const item of this.items) { + const menuItem = html.div( + { + onmouseover: () => { + if (this.clearCurrentSelection()) { + this.showMenu(item.items, menuItem); + } + }, + onclick: () => { + this.clearCurrentSelection(); + this.showMenu(item.items, menuItem); + }, + class: "menu-item", + }, + [item.title] + ); + fragment.appendChild(menuItem); + } + this.contentElement.appendChild(fragment); + } +} + +customElements.define("menu-bar", MenuBar); diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index b105e72623..30d2d02f57 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -13,7 +13,7 @@ export function showMenu(menuItems, position, positionContainer, container) { container.appendChild(menu); } -class MenuPanel extends SimpleElement { +export class MenuPanel extends SimpleElement { static openMenuPanels = []; static closeAllMenus(event) { diff --git a/src/fontra/views/plugins/plugins.html b/src/fontra/views/plugins/plugins.html index 803def016b..97d493ac3e 100644 --- a/src/fontra/views/plugins/plugins.html +++ b/src/fontra/views/plugins/plugins.html @@ -6,15 +6,106 @@ + Fontra Plugins +
+
From 7b715349c860a1791728555ff11931e3ab4b4ad6 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Thu, 26 Oct 2023 19:11:12 +0300 Subject: [PATCH 02/38] Delete commented out import line --- src/fontra/views/plugins/plugins.html | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fontra/views/plugins/plugins.html b/src/fontra/views/plugins/plugins.html index 97d493ac3e..ffbf30b3c8 100644 --- a/src/fontra/views/plugins/plugins.html +++ b/src/fontra/views/plugins/plugins.html @@ -6,7 +6,6 @@ - Fontra Plugins From 10887e17a211ffb5cc5018b039328954a525c52e Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Thu, 26 Oct 2023 19:51:54 +0300 Subject: [PATCH 03/38] Delete .items getter&setters --- src/fontra/client/web-components/menu-bar.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index 25302db14c..892008935f 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -22,22 +22,17 @@ export class MenuBar extends SimpleElement { border-radius: 5px; } `; + constructor(items = []) { super(); - this._items = items; + this.items = items; this.contentElement = this.shadowRoot.appendChild(html.div()); this.contentElement.classList.add("menu-bar"); this.render(); window.addEventListener("mousedown", this.clearCurrentSelection.bind(this)); window.addEventListener("blur", this.clearCurrentSelection.bind(this)); } - get items() { - return this._items; - } - set items(items) { - this._items = items; - this.render(); - } + clearCurrentSelection() { const currentSelection = this.contentElement.querySelector(".current"); if (!currentSelection) { From 754a222f730ed982348dc24623b7b7ec9bd410c2 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Tue, 7 Nov 2023 23:26:06 +0300 Subject: [PATCH 04/38] Make font size 1rem, Highlight the top bar menu items when hover --- src/fontra/client/web-components/menu-bar.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index 892008935f..71abf1e141 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -8,6 +8,7 @@ export class MenuBar extends SimpleElement { padding: 0.5rem 1rem; align-items: center; position: absolute; + font-size: 1rem; } .menu-item { @@ -17,6 +18,7 @@ export class MenuBar extends SimpleElement { user-select: none; } + .menu-item:hover, .menu-item.current { background: #e1e1e1; border-radius: 5px; From 5cab52901d7e72d2574481f729ac1f03f4cfa3da Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 24 Jan 2024 13:04:33 +0300 Subject: [PATCH 05/38] Menu items should be available when getItems called --- src/fontra/client/web-components/menu-bar.js | 4 +- src/fontra/views/plugins/plugins.html | 144 ++++++++++--------- 2 files changed, 79 insertions(+), 69 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index 71abf1e141..61cc38c4da 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -65,12 +65,12 @@ export class MenuBar extends SimpleElement { { onmouseover: () => { if (this.clearCurrentSelection()) { - this.showMenu(item.items, menuItem); + this.showMenu(item.getItems(), menuItem); } }, onclick: () => { this.clearCurrentSelection(); - this.showMenu(item.items, menuItem); + this.showMenu(item.getItems(), menuItem); }, class: "menu-item", }, diff --git a/src/fontra/views/plugins/plugins.html b/src/fontra/views/plugins/plugins.html index ffbf30b3c8..32d66ed0d3 100644 --- a/src/fontra/views/plugins/plugins.html +++ b/src/fontra/views/plugins/plugins.html @@ -21,86 +21,96 @@ const menuBar = new MenuBar([ { title: "File", - items: [ - { - title: "File", - enabled: () => true, - callback: () => { - console.log(1); + getItems() { + return [ + { + title: "File", + enabled: () => true, + callback: () => { + console.log(1); + }, + shortCut: undefined, }, - shortCut: undefined, - }, - ], + ]; + }, }, { title: "Edit", - items: [ - { - title: "Undo", - enabled: () => true, - callback: () => {}, - }, - { - title: "Redo", - enabled: () => true, - callback: () => {}, - }, - { - title: "Cut", - enabled: () => true, - callback: () => {}, - }, - { - title: "Copy", - enabled: () => true, - callback: () => {}, - }, - { - title: "Paste", - enabled: () => true, - callback: () => {}, - }, - { - title: "Select all", - enabled: () => true, - callback: () => {}, - }, - ], + getItems() { + return [ + { + title: "Undo", + enabled: () => true, + callback: () => {}, + }, + { + title: "Redo", + enabled: () => true, + callback: () => {}, + }, + { + title: "Cut", + enabled: () => true, + callback: () => {}, + }, + { + title: "Copy", + enabled: () => true, + callback: () => {}, + }, + { + title: "Paste", + enabled: () => true, + callback: () => {}, + }, + { + title: "Select all", + enabled: () => true, + callback: () => {}, + }, + ]; + }, }, { title: "View", - items: [ - { - title: "Reset zoom", - enabled: () => true, - callback: () => {}, - }, - ], + getItems() { + return [ + { + title: "Reset zoom", + enabled: () => true, + callback: () => {}, + }, + ]; + }, }, { title: "Go to", - items: [ - { - title: "Switch to plugins", - enabled: () => true, - callback: () => {}, - }, - { - title: "Font overview", - enabled: () => true, - callback: () => {}, - }, - ], + getItems() { + return [ + { + title: "Switch to plugins", + enabled: () => true, + callback: () => {}, + }, + { + title: "Font overview", + enabled: () => true, + callback: () => {}, + }, + ]; + }, }, { title: "Help", - items: [ - { - title: "Documentation", - enabled: () => true, - callback: () => {}, - }, - ], + getItems() { + return [ + { + title: "Documentation", + enabled: () => true, + callback: () => {}, + }, + ]; + }, }, ]); document.getElementById("menu-bar").appendChild(menuBar); From 28ccfc8c11059a11753c13f83a103122934b3aeb Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Tue, 2 Jan 2024 17:21:39 +0300 Subject: [PATCH 06/38] Initial implementation of sub-menu --- .../client/web-components/menu-panel.js | 72 ++++++++++++++++--- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 30d2d02f57..08941ab8b3 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -66,11 +66,16 @@ export class MenuPanel extends SimpleElement { .context-menu-item { display: grid; grid-template-columns: 1em auto; + align-items: center; gap: 0em; padding: 0.1em 0.8em 0.1em 0.5em; /* top, right, bottom, left */ color: #8080a0; } + .with-submenu { + grid-template-columns: 1em auto auto; + } + .context-menu-item.enabled { color: inherit; } @@ -86,11 +91,16 @@ export class MenuPanel extends SimpleElement { gap: 0.5em; justify-content: space-between; } + + .submenu-icon { + font-size: 0.8em; + } `; - constructor(menuItems, position, positionContainer) { + constructor(menuItems, position, positionContainer, visible = true) { super(); this.style = "display: none;"; + this.visible = visible; this.position = position; this.positionContainer = positionContainer; this.menuElement = html.div({ class: "menu-container", tabindex: 0 }); @@ -99,13 +109,42 @@ export class MenuPanel extends SimpleElement { this.menuElement.oncontextmenu = (event) => event.preventDefault(); for (const item of menuItems) { + const hasSubMenu = item.items && item.items.length > 0; let itemElement; if (item === MenuItemDivider || item.title === "-") { itemElement = html.hr({ class: "menu-item-divider" }); } else { + const classNames = ["context-menu-item"]; + if (typeof item.enabled === "function" && item.enabled()) { + classNames.push("enabled"); + } + if (hasSubMenu) { + classNames.push("with-submenu"); + } + const itemElementContent = [ + html.div({ class: "check-mark" }, [item.checked ? "✓" : ""]), + html.div({ class: "item-content" }, [ + typeof item.title === "function" ? item.title() : item.title, + html.span({}, [buildShortCutString(item.shortCut)]), + ]), + ]; + if (hasSubMenu) { + itemElementContent.push(html.div({ class: "submenu-icon" }, ["►"])); + itemElementContent.push( + new MenuPanel( + item.items, + { + x: 0, + y: 0, + }, + undefined, + false + ) + ); + } itemElement = html.div( { - class: `context-menu-item ${item.enabled() ? "enabled" : ""}`, + class: classNames.join(" "), onmouseenter: (event) => this.selectItem(itemElement), onmousemove: (event) => { if (!itemElement.classList.contains("selected")) { @@ -122,13 +161,7 @@ export class MenuPanel extends SimpleElement { } }, }, - [ - html.div({ class: "check-mark" }, [item.checked ? "✓" : ""]), - html.div({ class: "item-content" }, [ - typeof item.title === "function" ? item.title() : item.title, - html.span({}, [buildShortCutString(item.shortCut)]), - ]), - ] + itemElementContent ); } this.menuElement.appendChild(itemElement); @@ -142,6 +175,16 @@ export class MenuPanel extends SimpleElement { } connectedCallback() { + if (this.visible) { + this.show(); + } + } + + hide() { + this.style.display = "none"; + } + + show() { this._savedActiveElement = document.activeElement; const position = { ...this.position }; this.style = `display: inherited; left: ${position.x}px; top: ${position.y}px;`; @@ -169,11 +212,22 @@ export class MenuPanel extends SimpleElement { } selectItem(itemElement) { + if (this._recentSubMenu) { + this._recentSubMenu.hide(); + } const selectedItem = this.findSelectedItem(); if (selectedItem && selectedItem !== itemElement) { selectedItem.classList.remove("selected"); } itemElement.classList.add("selected"); + if (itemElement.classList.contains("with-submenu")) { + const { y: menuElementY } = this.getBoundingClientRect(); + const { y, width } = itemElement.getBoundingClientRect(); + const submenu = itemElement.querySelector("menu-panel"); + submenu.position = { x: width, y: y - menuElementY }; + submenu.show(); + this._recentSubMenu = submenu; + } } handleKeyDown(event) { From 7fa6d9bc08e373bd9d76c2e7bc90fbaf6abb58ca Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 24 Jan 2024 14:04:37 +0300 Subject: [PATCH 07/38] Submenu should be populated right before it is shown --- .../client/web-components/menu-panel.js | 48 ++++++++++++------- src/fontra/views/plugins/plugins.html | 47 ++++++++++++++++++ 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 08941ab8b3..602f12eb1b 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -1,7 +1,7 @@ import { themeColorCSS } from "./theme-support.js"; import * as html from "/core/html-utils.js"; import { SimpleElement } from "/core/html-utils.js"; -import { capitalizeFirstLetter, reversed } from "/core/utils.js"; +import { capitalizeFirstLetter, enumerate, reversed } from "/core/utils.js"; export const MenuItemDivider = { title: "-" }; @@ -108,14 +108,20 @@ export class MenuPanel extends SimpleElement { // No context menu on our context menu please: this.menuElement.oncontextmenu = (event) => event.preventDefault(); - for (const item of menuItems) { - const hasSubMenu = item.items && item.items.length > 0; + this.menuItems = menuItems; + + for (const [index, item] of enumerate(menuItems)) { + const hasSubMenu = typeof item.getItems === "function"; let itemElement; if (item === MenuItemDivider || item.title === "-") { itemElement = html.hr({ class: "menu-item-divider" }); } else { const classNames = ["context-menu-item"]; - if (typeof item.enabled === "function" && item.enabled()) { + if ( + (!hasSubMenu || item.getItems().length > 0) && + typeof item.enabled === "function" && + item.enabled() + ) { classNames.push("enabled"); } if (hasSubMenu) { @@ -130,17 +136,17 @@ export class MenuPanel extends SimpleElement { ]; if (hasSubMenu) { itemElementContent.push(html.div({ class: "submenu-icon" }, ["►"])); - itemElementContent.push( - new MenuPanel( - item.items, - { - x: 0, - y: 0, - }, - undefined, - false - ) - ); + // itemElementContent.push( + // new MenuPanel( + // [], + // { + // x: 0, + // y: 0, + // }, + // undefined, + // false + // ) + // ); } itemElement = html.div( { @@ -163,6 +169,7 @@ export class MenuPanel extends SimpleElement { }, itemElementContent ); + itemElement.dataset.index = index; } this.menuElement.appendChild(itemElement); } @@ -223,7 +230,16 @@ export class MenuPanel extends SimpleElement { if (itemElement.classList.contains("with-submenu")) { const { y: menuElementY } = this.getBoundingClientRect(); const { y, width } = itemElement.getBoundingClientRect(); - const submenu = itemElement.querySelector("menu-panel"); + const submenu = new MenuPanel( + this.menuItems[itemElement.dataset.index].getItems(), + { + x: 0, + y: 0, + }, + undefined, + false + ); + itemElement.appendChild(submenu); submenu.position = { x: width, y: y - menuElementY }; submenu.show(); this._recentSubMenu = submenu; diff --git a/src/fontra/views/plugins/plugins.html b/src/fontra/views/plugins/plugins.html index 32d66ed0d3..89c97a1153 100644 --- a/src/fontra/views/plugins/plugins.html +++ b/src/fontra/views/plugins/plugins.html @@ -31,6 +31,53 @@ }, shortCut: undefined, }, + { + title: "Recently opened", + enabled: () => true, + callback: () => { + console.log(1); + }, + shortCut: undefined, + getItems() { + return [ + { + title: "File 1", + enabled: () => true, + callback: () => { + console.log(1); + }, + }, + { + title: "File 2", + enabled: () => true, + callback: () => { + console.log(2); + }, + }, + { + title: "File 3", + enabled: () => true, + callback: () => { + console.log(3); + }, + }, + { + title: "File 4", + enabled: () => true, + callback: () => { + console.log(4); + }, + }, + { + title: "File 5", + enabled: () => true, + callback: () => { + console.log(5); + }, + }, + ]; + }, + }, ]; }, }, From 99b084c451a2a34f179758346d913ce7daec3aa2 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 24 Jan 2024 14:08:46 +0300 Subject: [PATCH 08/38] Delete forgotten commented out lines --- src/fontra/client/web-components/menu-panel.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 602f12eb1b..5eb43b7280 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -136,17 +136,6 @@ export class MenuPanel extends SimpleElement { ]; if (hasSubMenu) { itemElementContent.push(html.div({ class: "submenu-icon" }, ["►"])); - // itemElementContent.push( - // new MenuPanel( - // [], - // { - // x: 0, - // y: 0, - // }, - // undefined, - // false - // ) - // ); } itemElement = html.div( { From cf62454a54d98dc581872a95e9ddcef8efae58f5 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 24 Jan 2024 14:10:08 +0300 Subject: [PATCH 09/38] Rename recentSubMenu -> lastShownSubMenu --- src/fontra/client/web-components/menu-panel.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 5eb43b7280..bdd1c6fc1d 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -208,8 +208,8 @@ export class MenuPanel extends SimpleElement { } selectItem(itemElement) { - if (this._recentSubMenu) { - this._recentSubMenu.hide(); + if (this._lastShownSubMenu) { + this._lastShownSubMenu.hide(); } const selectedItem = this.findSelectedItem(); if (selectedItem && selectedItem !== itemElement) { @@ -231,7 +231,7 @@ export class MenuPanel extends SimpleElement { itemElement.appendChild(submenu); submenu.position = { x: width, y: y - menuElementY }; submenu.show(); - this._recentSubMenu = submenu; + this._lastShownSubMenu = submenu; } } From 5eeed418e5e33d1d9a3d7e697e42a9f8aaf2dca4 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 24 Jan 2024 14:12:11 +0300 Subject: [PATCH 10/38] Delete the submenu when it's no longer visible --- src/fontra/client/web-components/menu-panel.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index bdd1c6fc1d..b9a544654f 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -209,7 +209,8 @@ export class MenuPanel extends SimpleElement { selectItem(itemElement) { if (this._lastShownSubMenu) { - this._lastShownSubMenu.hide(); + this._lastShownSubMenu.parentElement.removeChild(this._lastShownSubMenu); + this._lastShownSubMenu = undefined; } const selectedItem = this.findSelectedItem(); if (selectedItem && selectedItem !== itemElement) { From 9694b8f1d832dc0108ce83d33725f7a0003e424a Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 24 Jan 2024 14:37:26 +0300 Subject: [PATCH 11/38] Replaced ascii arrow with chevron-right --- src/fontra/client/tabler-icons/chevron-right.svg | 1 + src/fontra/client/web-components/menu-bar.js | 1 + src/fontra/client/web-components/menu-panel.js | 10 ++++++++-- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 src/fontra/client/tabler-icons/chevron-right.svg diff --git a/src/fontra/client/tabler-icons/chevron-right.svg b/src/fontra/client/tabler-icons/chevron-right.svg new file mode 100644 index 0000000000..854c6034ff --- /dev/null +++ b/src/fontra/client/tabler-icons/chevron-right.svg @@ -0,0 +1 @@ + diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index 61cc38c4da..c7d11a09ae 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -1,6 +1,7 @@ import * as html from "../core/html-utils.js"; import { SimpleElement } from "../core/html-utils.js"; import { MenuPanel } from "./menu-panel.js"; +import { InlineSVG } from "/web-components/inline-svg.js"; export class MenuBar extends SimpleElement { static styles = ` diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index b9a544654f..6501d017b4 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -2,6 +2,7 @@ import { themeColorCSS } from "./theme-support.js"; import * as html from "/core/html-utils.js"; import { SimpleElement } from "/core/html-utils.js"; import { capitalizeFirstLetter, enumerate, reversed } from "/core/utils.js"; +import { InlineSVG } from "/web-components/inline-svg.js"; export const MenuItemDivider = { title: "-" }; @@ -93,7 +94,8 @@ export class MenuPanel extends SimpleElement { } .submenu-icon { - font-size: 0.8em; + width: 1rem; + margin-top: 0.3rem; } `; @@ -135,7 +137,11 @@ export class MenuPanel extends SimpleElement { ]), ]; if (hasSubMenu) { - itemElementContent.push(html.div({ class: "submenu-icon" }, ["►"])); + itemElementContent.push( + html.div({ class: "submenu-icon" }, [ + new InlineSVG(`/tabler-icons/chevron-right.svg`), + ]) + ); } itemElement = html.div( { From a89f5c21c6f3a52fbd4ba4bbd64ad74ba929d6e4 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 24 Jan 2024 15:10:46 +0300 Subject: [PATCH 12/38] Fix spacing in submenu icon --- .../client/tabler-icons/chevron-right.svg | 2 +- .../client/web-components/menu-panel.js | 10 ++-- src/fontra/views/plugins/plugins.html | 50 +++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/fontra/client/tabler-icons/chevron-right.svg b/src/fontra/client/tabler-icons/chevron-right.svg index 854c6034ff..e35aed1741 100644 --- a/src/fontra/client/tabler-icons/chevron-right.svg +++ b/src/fontra/client/tabler-icons/chevron-right.svg @@ -1 +1 @@ - + diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 6501d017b4..e64a413dd2 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -94,8 +94,8 @@ export class MenuPanel extends SimpleElement { } .submenu-icon { - width: 1rem; - margin-top: 0.3rem; + width: 10px; + height: 14px; } `; @@ -139,7 +139,9 @@ export class MenuPanel extends SimpleElement { if (hasSubMenu) { itemElementContent.push( html.div({ class: "submenu-icon" }, [ - new InlineSVG(`/tabler-icons/chevron-right.svg`), + new InlineSVG(`/tabler-icons/chevron-right.svg`, { + style: "margin-top: 2px", + }), ]) ); } @@ -236,7 +238,7 @@ export class MenuPanel extends SimpleElement { false ); itemElement.appendChild(submenu); - submenu.position = { x: width, y: y - menuElementY }; + submenu.position = { x: width, y: y - menuElementY - 4 }; submenu.show(); this._lastShownSubMenu = submenu; } diff --git a/src/fontra/views/plugins/plugins.html b/src/fontra/views/plugins/plugins.html index 89c97a1153..366be94c3d 100644 --- a/src/fontra/views/plugins/plugins.html +++ b/src/fontra/views/plugins/plugins.html @@ -46,6 +46,56 @@ callback: () => { console.log(1); }, + getItems() { + return [ + { + title: "File 1", + enabled: () => true, + callback: () => { + console.log(1); + }, + getItems() { + return [ + { + title: "File 1", + enabled: () => true, + callback: () => { + console.log(1); + }, + }, + { + title: "File 2", + enabled: () => true, + callback: () => { + console.log(2); + }, + }, + { + title: "File 3", + enabled: () => true, + callback: () => { + console.log(3); + }, + }, + ]; + }, + }, + { + title: "File 2", + enabled: () => true, + callback: () => { + console.log(2); + }, + }, + { + title: "File 3", + enabled: () => true, + callback: () => { + console.log(3); + }, + }, + ]; + }, }, { title: "File 2", From 6039143c1b410b41c3f4a9803890129ffd86c7e4 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Fri, 26 Jan 2024 19:41:51 +0300 Subject: [PATCH 13/38] Made keeping the track of sub menus by a property --- .../client/web-components/menu-panel.js | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index e64a413dd2..594c497262 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -77,6 +77,10 @@ export class MenuPanel extends SimpleElement { grid-template-columns: 1em auto auto; } + .has-open-submenu { + background-color: #dedede; + } + .context-menu-item.enabled { color: inherit; } @@ -99,13 +103,14 @@ export class MenuPanel extends SimpleElement { } `; - constructor(menuItems, position, positionContainer, visible = true) { + constructor(menuItems, position, positionContainer, visible = true, childOf) { super(); this.style = "display: none;"; this.visible = visible; this.position = position; this.positionContainer = positionContainer; this.menuElement = html.div({ class: "menu-container", tabindex: 0 }); + this.childOf = childOf; // No context menu on our context menu please: this.menuElement.oncontextmenu = (event) => event.preventDefault(); @@ -154,7 +159,9 @@ export class MenuPanel extends SimpleElement { this.selectItem(itemElement); } }, - onmouseleave: (event) => itemElement.classList.remove("selected"), + onmouseleave: (event) => { + itemElement.classList.remove("selected"); + }, onmouseup: (event) => { event.preventDefault(); event.stopImmediatePropagation(); @@ -216,15 +223,25 @@ export class MenuPanel extends SimpleElement { } selectItem(itemElement) { - if (this._lastShownSubMenu) { - this._lastShownSubMenu.parentElement.removeChild(this._lastShownSubMenu); - this._lastShownSubMenu = undefined; + for (const menuPanel of MenuPanel.openMenuPanels) { + if (menuPanel.childOf === this) { + menuPanel.dismiss(); + break; + } } + + for (const item of this.menuElement.children) { + if (item.classList.contains("has-open-submenu")) { + item.classList.remove("has-open-submenu"); + } + } + const selectedItem = this.findSelectedItem(); if (selectedItem && selectedItem !== itemElement) { selectedItem.classList.remove("selected"); } itemElement.classList.add("selected"); + if (itemElement.classList.contains("with-submenu")) { const { y: menuElementY } = this.getBoundingClientRect(); const { y, width } = itemElement.getBoundingClientRect(); @@ -235,12 +252,13 @@ export class MenuPanel extends SimpleElement { y: 0, }, undefined, - false + false, + this ); - itemElement.appendChild(submenu); + this.menuElement.appendChild(submenu); submenu.position = { x: width, y: y - menuElementY - 4 }; submenu.show(); - this._lastShownSubMenu = submenu; + itemElement.classList.add("has-open-submenu"); } } From 67b3972a9279155c7551f6a171394c0889b5edfb Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Mon, 29 Jan 2024 12:27:24 +0300 Subject: [PATCH 14/38] Prevent blur event being fired when mouseup --- src/fontra/client/web-components/menu-bar.js | 16 +++++++++++++--- src/fontra/client/web-components/menu-panel.js | 4 ++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index 61cc38c4da..a4b6e0928c 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -58,6 +58,16 @@ export class MenuBar extends SimpleElement { this.contentElement.appendChild(menuPanel); } + overrideCallbacks(items) { + return items.map((item) => ({ + ...item, + callback: () => { + this.clearCurrentSelection(); + item.callback(); + }, + })); + } + render() { const fragment = document.createDocumentFragment(); for (const item of this.items) { @@ -65,12 +75,12 @@ export class MenuBar extends SimpleElement { { onmouseover: () => { if (this.clearCurrentSelection()) { - this.showMenu(item.getItems(), menuItem); + this.showMenu(this.overrideCallbacks(item.getItems()), menuItem); } }, - onclick: () => { + onclick: (event) => { this.clearCurrentSelection(); - this.showMenu(item.getItems(), menuItem); + this.showMenu(this.overrideCallbacks(item.getItems()), menuItem); }, class: "menu-item", }, diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 30d2d02f57..67fbd0aeee 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -113,6 +113,10 @@ export class MenuPanel extends SimpleElement { } }, onmouseleave: (event) => itemElement.classList.remove("selected"), + onmousedown: (event) => { + event.preventDefault(); + event.stopImmediatePropagation(); + }, onmouseup: (event) => { event.preventDefault(); event.stopImmediatePropagation(); From ac7dbc66ebf1ec1f0f0039c04c82cd4f9836b23e Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Mon, 29 Jan 2024 17:58:57 +0300 Subject: [PATCH 15/38] add onSelect event, prevent dismissing the menu when click on menu-bar in onmousedown event instead of instanceof check --- src/fontra/client/web-components/menu-bar.js | 28 ++++++++----------- .../client/web-components/menu-panel.js | 16 ++++++----- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index a4b6e0928c..5b55a70055 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -35,7 +35,7 @@ export class MenuBar extends SimpleElement { window.addEventListener("blur", this.clearCurrentSelection.bind(this)); } - clearCurrentSelection() { + clearCurrentSelection(event) { const currentSelection = this.contentElement.querySelector(".current"); if (!currentSelection) { return false; @@ -51,23 +51,19 @@ export class MenuBar extends SimpleElement { showMenu(items, menuItemElement) { menuItemElement.classList.add("current"); const clientRect = menuItemElement.getBoundingClientRect(); - const menuPanel = new MenuPanel(items, { + const position = { x: clientRect.x, y: clientRect.y + clientRect.height, - }); + }; + const menuPanel = new MenuPanel( + items, + position, + undefined, + this.clearCurrentSelection.bind(this) + ); this.contentElement.appendChild(menuPanel); } - overrideCallbacks(items) { - return items.map((item) => ({ - ...item, - callback: () => { - this.clearCurrentSelection(); - item.callback(); - }, - })); - } - render() { const fragment = document.createDocumentFragment(); for (const item of this.items) { @@ -75,12 +71,12 @@ export class MenuBar extends SimpleElement { { onmouseover: () => { if (this.clearCurrentSelection()) { - this.showMenu(this.overrideCallbacks(item.getItems()), menuItem); + this.showMenu(item.getItems(), menuItem); } }, - onclick: (event) => { + onclick: () => { this.clearCurrentSelection(); - this.showMenu(this.overrideCallbacks(item.getItems()), menuItem); + this.showMenu(item.getItems(), menuItem); }, class: "menu-item", }, diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 67fbd0aeee..d34dbbf929 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -17,11 +17,11 @@ export class MenuPanel extends SimpleElement { static openMenuPanels = []; static closeAllMenus(event) { - if (event) { - if (event.target instanceof MenuPanel) { - return; - } - } + // if (event) { + // if (event.target instanceof MenuPanel) { + // return; + // } + // } for (const element of MenuPanel.openMenuPanels) { element.parentElement?.removeChild(element); } @@ -88,10 +88,11 @@ export class MenuPanel extends SimpleElement { } `; - constructor(menuItems, position, positionContainer) { + constructor(menuItems, position, positionContainer, onSelect) { super(); this.style = "display: none;"; this.position = position; + this.onSelect = onSelect; this.positionContainer = positionContainer; this.menuElement = html.div({ class: "menu-container", tabindex: 0 }); @@ -112,17 +113,18 @@ export class MenuPanel extends SimpleElement { this.selectItem(itemElement); } }, - onmouseleave: (event) => itemElement.classList.remove("selected"), onmousedown: (event) => { event.preventDefault(); event.stopImmediatePropagation(); }, + onmouseleave: (event) => itemElement.classList.remove("selected"), onmouseup: (event) => { event.preventDefault(); event.stopImmediatePropagation(); if (item.enabled()) { item.callback?.(event); this.dismiss(); + this.onSelect?.(itemElement); } }, }, From 31aa77987f4717dee35e00a626df3c01bd36195f Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Mon, 29 Jan 2024 18:00:45 +0300 Subject: [PATCH 16/38] Delete commented-out code --- src/fontra/client/web-components/menu-panel.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index d34dbbf929..0c89d9c9f0 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -17,11 +17,6 @@ export class MenuPanel extends SimpleElement { static openMenuPanels = []; static closeAllMenus(event) { - // if (event) { - // if (event.target instanceof MenuPanel) { - // return; - // } - // } for (const element of MenuPanel.openMenuPanels) { element.parentElement?.removeChild(element); } From 867dba97053746a281edd1ba56070d75177ac5e8 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 31 Jan 2024 21:49:09 +0300 Subject: [PATCH 17/38] Hidemenu when hover on top-menu, delete individual callbacks on menu items --- src/fontra/client/web-components/menu-bar.js | 87 +++++++++++++------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index 5b55a70055..ec71f5ddba 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -9,6 +9,7 @@ export class MenuBar extends SimpleElement { align-items: center; position: absolute; font-size: 1rem; + width: 100%; } .menu-item { @@ -31,21 +32,60 @@ export class MenuBar extends SimpleElement { this.contentElement = this.shadowRoot.appendChild(html.div()); this.contentElement.classList.add("menu-bar"); this.render(); - window.addEventListener("mousedown", this.clearCurrentSelection.bind(this)); - window.addEventListener("blur", this.clearCurrentSelection.bind(this)); + window.addEventListener("mousedown", this.onBlur.bind(this)); + window.addEventListener("blur", this.onBlur.bind(this)); + this.contentElement.addEventListener("mouseover", this.onMouseover.bind(this)); + this.contentElement.addEventListener("click", this.onClick.bind(this)); + this.showMenuWhenHover = false; + } + + onClick(event) { + if (event.target.classList.contains("menu-item")) { + for (let i = 0; i < this.contentElement.childElementCount; i++) { + const node = this.contentElement.childNodes[i]; + if (node === event.target) { + this.clearCurrentSelection(); + this.showMenuWhenHover = true; + this.showMenu(this.items[i].getItems(), node); + break; + } + } + } + } + + onMouseover(event) { + if (event.target === this.contentElement) { + this.clearCurrentSelection(); + return; + } + if (event.target.classList.contains("menu-item")) { + this.clearCurrentSelection(); + for (let i = 0; i < this.contentElement.childElementCount; i++) { + const node = this.contentElement.childNodes[i]; + if (node === event.target) { + if (this.showMenuWhenHover) { + this.showMenu(this.items[i].getItems(), node); + } + break; + } + } + } + } + + onBlur() { + this.clearCurrentSelection(); + this.showMenuWhenHover = false; } clearCurrentSelection(event) { const currentSelection = this.contentElement.querySelector(".current"); - if (!currentSelection) { - return false; - } - currentSelection.classList.remove("current"); - const menuPanel = this.contentElement.querySelector("menu-panel"); - if (menuPanel) { - this.contentElement.removeChild(menuPanel); + if (currentSelection) { + currentSelection.classList.remove("current"); + const menuPanel = this.contentElement.querySelector("menu-panel"); + if (menuPanel) { + this.contentElement.removeChild(menuPanel); + } } - return true; } showMenu(items, menuItemElement) { @@ -55,34 +95,17 @@ export class MenuBar extends SimpleElement { x: clientRect.x, y: clientRect.y + clientRect.height, }; - const menuPanel = new MenuPanel( - items, - position, - undefined, - this.clearCurrentSelection.bind(this) - ); + const menuPanel = new MenuPanel(items, position, undefined, () => { + this.showMenuWhenHover = false; + this.clearCurrentSelection(); + }); this.contentElement.appendChild(menuPanel); } render() { const fragment = document.createDocumentFragment(); for (const item of this.items) { - const menuItem = html.div( - { - onmouseover: () => { - if (this.clearCurrentSelection()) { - this.showMenu(item.getItems(), menuItem); - } - }, - onclick: () => { - this.clearCurrentSelection(); - this.showMenu(item.getItems(), menuItem); - }, - class: "menu-item", - }, - [item.title] - ); - fragment.appendChild(menuItem); + fragment.appendChild(html.div({ class: "menu-item" }, [item.title])); } this.contentElement.appendChild(fragment); } From 88388b893637e25bd34a47a3d088bd69a01ac52b Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 31 Jan 2024 23:16:01 +0300 Subject: [PATCH 18/38] Delete childOf property --- src/fontra/client/web-components/menu-panel.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 594c497262..84e9d0f869 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -103,14 +103,13 @@ export class MenuPanel extends SimpleElement { } `; - constructor(menuItems, position, positionContainer, visible = true, childOf) { + constructor(menuItems, position, positionContainer, visible = true) { super(); this.style = "display: none;"; this.visible = visible; this.position = position; this.positionContainer = positionContainer; this.menuElement = html.div({ class: "menu-container", tabindex: 0 }); - this.childOf = childOf; // No context menu on our context menu please: this.menuElement.oncontextmenu = (event) => event.preventDefault(); From 3e5e2b8e3b05fe53563cf869e84a645478003f99 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 31 Jan 2024 23:19:24 +0300 Subject: [PATCH 19/38] Bring back childOf --- src/fontra/client/web-components/menu-panel.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 84e9d0f869..594c497262 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -103,13 +103,14 @@ export class MenuPanel extends SimpleElement { } `; - constructor(menuItems, position, positionContainer, visible = true) { + constructor(menuItems, position, positionContainer, visible = true, childOf) { super(); this.style = "display: none;"; this.visible = visible; this.position = position; this.positionContainer = positionContainer; this.menuElement = html.div({ class: "menu-container", tabindex: 0 }); + this.childOf = childOf; // No context menu on our context menu please: this.menuElement.oncontextmenu = (event) => event.preventDefault(); From 20ea75b0d0ac7ff9bf339265ca60d232d7973f5e Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 31 Jan 2024 23:22:58 +0300 Subject: [PATCH 20/38] Delete not used import --- src/fontra/client/web-components/menu-bar.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index c7d11a09ae..61cc38c4da 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -1,7 +1,6 @@ import * as html from "../core/html-utils.js"; import { SimpleElement } from "../core/html-utils.js"; import { MenuPanel } from "./menu-panel.js"; -import { InlineSVG } from "/web-components/inline-svg.js"; export class MenuBar extends SimpleElement { static styles = ` From 496bb799c2f0352f0722b063d68ca3d43ea5e8a6 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 31 Jan 2024 23:39:02 +0300 Subject: [PATCH 21/38] Fix merge error --- src/fontra/client/web-components/menu-panel.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 8059b4866f..0e5b4c0534 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -258,6 +258,7 @@ export class MenuPanel extends SimpleElement { y: 0, }, undefined, + undefined, false, this ); From 2065f70ba9b649ec148928e9c129117a40b747f5 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Mon, 12 Feb 2024 18:24:47 +0300 Subject: [PATCH 22/38] Dismiss the menu when click on already open menu --- src/fontra/client/web-components/menu-bar.js | 43 ++++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index ec71f5ddba..90c983b51e 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -41,21 +41,32 @@ export class MenuBar extends SimpleElement { onClick(event) { if (event.target.classList.contains("menu-item")) { - for (let i = 0; i < this.contentElement.childElementCount; i++) { - const node = this.contentElement.childNodes[i]; - if (node === event.target) { - this.clearCurrentSelection(); - this.showMenuWhenHover = true; - this.showMenu(this.items[i].getItems(), node); - break; + const currentSelection = this.contentElement.querySelector(".current"); + if (currentSelection === event.target) { + this.clearCurrentSelection(); + this.showMenuWhenHover = false; + } else { + for (let i = 0; i < this.contentElement.childElementCount; i++) { + const node = this.contentElement.childNodes[i]; + if (node === event.target) { + this.clearCurrentSelection(); + this.showMenuWhenHover = true; + this.showMenu(this.items[i].getItems(), node); + break; + } } } } } onMouseover(event) { + const currentSelection = this.contentElement.querySelector(".current"); + if (!currentSelection && !this.showMenuWhenHover) { + return; + } if (event.target === this.contentElement) { this.clearCurrentSelection(); + this.showMenuWhenHover = true; return; } if (event.target.classList.contains("menu-item")) { @@ -72,7 +83,7 @@ export class MenuBar extends SimpleElement { } } - onBlur() { + onBlur(event) { this.clearCurrentSelection(); this.showMenuWhenHover = false; } @@ -105,7 +116,21 @@ export class MenuBar extends SimpleElement { render() { const fragment = document.createDocumentFragment(); for (const item of this.items) { - fragment.appendChild(html.div({ class: "menu-item" }, [item.title])); + fragment.appendChild( + html.div( + { + class: "menu-item", + onmousedown: (event) => { + const currentSelection = this.contentElement.querySelector(".current"); + if (currentSelection === event.target) { + event.stopImmediatePropagation(); + console.log(1); + } + }, + }, + [item.title] + ) + ); } this.contentElement.appendChild(fragment); } From b91ad4a9fe20cb090ba8ae5a937d72898bdb457f Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Tue, 13 Feb 2024 17:05:45 +0300 Subject: [PATCH 23/38] Delete forgotten console.log --- src/fontra/client/web-components/menu-bar.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index 90c983b51e..428f902c0c 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -124,7 +124,6 @@ export class MenuBar extends SimpleElement { const currentSelection = this.contentElement.querySelector(".current"); if (currentSelection === event.target) { event.stopImmediatePropagation(); - console.log(1); } }, }, From f30008aaaac615ec85bbb5bd2ab7ea26da614fc8 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Thu, 15 Feb 2024 17:10:53 +0300 Subject: [PATCH 24/38] Top-bar menu --- src/fontra/client/web-components/menu-bar.js | 2 +- src/fontra/views/editor/editor.css | 38 +++++- src/fontra/views/editor/editor.html | 1 + src/fontra/views/editor/editor.js | 124 ++++++++++++++++++- 4 files changed, 159 insertions(+), 6 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index 428f902c0c..4d2c2e6328 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -21,7 +21,7 @@ export class MenuBar extends SimpleElement { .menu-item:hover, .menu-item.current { - background: #e1e1e1; + background: var(--editor-top-bar-link-hover); border-radius: 5px; } `; diff --git a/src/fontra/views/editor/editor.css b/src/fontra/views/editor/editor.css index 5619172ced..70482c66a8 100644 --- a/src/fontra/views/editor/editor.css +++ b/src/fontra/views/editor/editor.css @@ -13,6 +13,14 @@ --editor-mini-console-foreground-color-light: black; --editor-mini-console-foreground-color-dark: white; + + --editor-top-bar-background-color-light: #eee; + --editor-top-bar-background-color-dark: #444; + --editor-top-bar-border-color-light: #d3d3d3; + --editor-top-bar-border-color-dark: #2e2e2e; + --editor-top-bar-link-hover-light: #e1e1e1; + --editor-top-bar-link-hover-dark: rgb(47, 47, 47); + --editor-top-bar-height: 45px; } :root { @@ -31,6 +39,10 @@ --editor-mini-console-foreground-color: var( --editor-mini-console-foreground-color-light ); + + --editor-top-bar-background-color: var(--editor-top-bar-background-color-light); + --editor-top-bar-border-color: var(--editor-top-bar-border-color-light); + --editor-top-bar-link-hover: var(--editor-top-bar-link-hover-light); } :root.dark-theme { @@ -49,6 +61,7 @@ --editor-mini-console-foreground-color: var( --editor-mini-console-foreground-color-dark ); + --editor-top-bar-link-hover: var(--editor-top-bar-link-hover-dark); } @media (prefers-color-scheme: dark) { @@ -68,6 +81,9 @@ --editor-mini-console-foreground-color: var( --editor-mini-console-foreground-color-dark ); + --editor-top-bar-background-color: var(--editor-top-bar-background-color-dark); + --editor-top-bar-border-color: var(--editor-top-bar-border-color-dark); + --editor-top-bar-link-hover: var(--editor-top-bar-link-hover-dark); } :root.light-theme { @@ -86,6 +102,9 @@ --editor-mini-console-foreground-color: var( --editor-mini-console-foreground-color-light ); + --editor-top-bar-background-color: var(--editor-top-bar-background-color-light); + --editor-top-bar-border-color: var(--editor-top-bar-border-color-light); + --editor-top-bar-link-hover: var(--editor-top-bar-link-hover-light); } } @@ -100,11 +119,28 @@ body { display: grid; position: relative; grid-template-columns: auto 1fr auto; - grid-template-rows: 100%; + grid-template-rows: 1fr calc(100% - var(--editor-top-bar-height)); height: 100%; width: 100%; } +.top-bar-container { + grid-row-start: 1; + grid-row-end: 2; + grid-column-start: 1; + grid-column-end: 4; + z-index: 200; + height: var(--editor-top-bar-height); + background: var(--editor-top-bar-background-color); + border-bottom: 1px solid var(--editor-top-bar-border-color); +} + +.sidebar-container, +.main-container { + grid-row-start: 2; + grid-row-end: 3; +} + .sidebar-container { z-index: 100; background-color: var(--ui-element-background-color); diff --git a/src/fontra/views/editor/editor.html b/src/fontra/views/editor/editor.html index 27d2970ada..2f0637a003 100644 --- a/src/fontra/views/editor/editor.html +++ b/src/fontra/views/editor/editor.html @@ -29,6 +29,7 @@
+
diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 4cf76f54b5..add54279a0 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -58,6 +58,7 @@ import { import { VisualizationLayers } from "./visualization-layers.js"; import * as html from "/core/html-utils.js"; import { themeController } from "/core/theme-settings.js"; +import { MenuBar } from "/web-components/menu-bar.js"; import { MenuItemDivider, showMenu } from "/web-components/menu-panel.js"; import { dialog, dialogSetup, message } from "/web-components/modal-dialog.js"; import { parsePluginBasePath } from "/web-components/plugin-manager.js"; @@ -192,6 +193,7 @@ export class EditorController { this.sidebars = []; this.initSidebars(); + this.initTopBar(); this.initContextMenuItems(); this.initShortCuts(); this.initMiniConsole(); @@ -252,6 +254,113 @@ export class EditorController { this.updateWithDelay(); } + initTopBar() { + const menuBar = new MenuBar([ + { + title: "File", + getItems() { + return [ + { + title: "New...", + enabled: () => false, + callback: () => {}, + shortCut: undefined, + }, + { + title: "Open...", + enabled: () => false, + callback: () => {}, + shortCut: undefined, + }, + ]; + }, + }, + { + title: "Edit", + getItems: () => { + return this.buildContextMenuItems(); + }, + }, + { + title: "View", + getItems: () => { + return [ + { + title: "Zoom in", + enabled: () => true, + shortCut: { keysOrCodes: "+=", metaKey: true, globalOverride: true }, + callback: () => { + this.zoomIn(); + }, + }, + { + title: "Zoom out", + shortCut: { keysOrCodes: "-", metaKey: true, globalOverride: true }, + enabled: () => true, + callback: () => { + this.zoomOut(); + }, + }, + { + title: "Zoom to fit", + enabled: () => true, + shortCut: { keysOrCodes: "0", metaKey: true, globalOverride: true }, + callback: () => { + this.zoomFit(); + }, + }, + ]; + }, + }, + { + title: "Glyph", + enabled: () => true, + getItems: () => { + return [ + { + title: "Add source", + enabled: () => true, + callback: () => { + this.getSidebarPanel("designspace-navigation").addSource(); + }, + }, + ]; + }, + }, + { + title: "Extensions", + enabled: () => true, + getItems: () => { + return [ + { + title: "Plugin manager", + enabled: () => true, + callback: () => { + window.open("/plugins/plugins.html"); + }, + }, + ]; + }, + }, + { + title: "Help", + enabled: () => true, + getItems: () => { + return [ + { + title: "Documentation", + enabled: () => true, + callback: () => { + window.open("https://github.com/googlefonts/fontra"); + }, + }, + ]; + }, + }, + ]); + document.querySelector(".top-bar-container").appendChild(menuBar); + } + restoreOpenTabs(sidebarName) { // Restore the sidebar selection/visible state from localStorage. const panelName = localStorage.getItem(`fontra-selected-sidebar-${sidebarName}`); @@ -903,7 +1012,9 @@ export class EditorController { canCut() { return ( - !this.sceneSettings.selectedGlyph.isEditing || this.sceneController.selection.size + (this.sceneSettings.selectedGlyph && + !this.sceneSettings.selectedGlyph.isEditing) || + this.sceneController.selection.size ); } @@ -1635,8 +1746,7 @@ export class EditorController { } } - contextMenuHandler(event) { - event.preventDefault(); + buildContextMenuItems() { const menuItems = [...this.basicContextMenuItems]; if (this.sceneSettings.selectedGlyph?.isEditing) { this.sceneController.updateContextMenuState(event); @@ -1647,8 +1757,14 @@ export class EditorController { menuItems.push(MenuItemDivider); menuItems.push(...this.glyphSelectedContextMenuItems); } + return menuItems; + } + + contextMenuHandler(event) { + event.preventDefault(); + const { x, y } = event; - showMenu(menuItems, { x: x + 1, y: y - 1 }, event.target); + showMenu(this.buildContextMenuItems(), { x: x + 1, y: y - 1 }, event.target); } async newGlyph(glyphName, codePoint, varGlyph, undoLabel = null) { From f8addc2e124fae77d69d0cd5dc7d8613b9edca2c Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 21 Feb 2024 02:17:30 +0300 Subject: [PATCH 25/38] Delete top-menu in plugins page --- src/fontra/views/plugins/plugins.html | 196 -------------------------- 1 file changed, 196 deletions(-) diff --git a/src/fontra/views/plugins/plugins.html b/src/fontra/views/plugins/plugins.html index 366be94c3d..5b3cd92bfc 100644 --- a/src/fontra/views/plugins/plugins.html +++ b/src/fontra/views/plugins/plugins.html @@ -16,202 +16,6 @@
- From e20439445a2a9c634bdaf349fe9952e760942dd8 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Wed, 21 Feb 2024 08:35:52 +0300 Subject: [PATCH 26/38] Disable the zoom to fit if it is already actual --- src/fontra/client/core/canvas-controller.js | 11 +++++++++++ src/fontra/views/editor/editor.js | 12 +++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/fontra/client/core/canvas-controller.js b/src/fontra/client/core/canvas-controller.js index 5ffcf6f171..6ffa7840e0 100644 --- a/src/fontra/client/core/canvas-controller.js +++ b/src/fontra/client/core/canvas-controller.js @@ -219,6 +219,17 @@ export class CanvasController { }); } + isActualViewBox(viewBox) { + const canvasCenter = this.canvasPoint(rectCenter(viewBox)); + return ( + this.magnification === this._getProposedViewBoxMagnification(viewBox) && + Math.round(this.origin.x) === + Math.round(this.canvasWidth / 2 + this.origin.x - canvasCenter.x) && + Math.round(this.origin.y) === + Math.round(this.canvasHeight / 2 + this.origin.y - canvasCenter.y) + ); + } + setViewBox(viewBox) { this.magnification = this._getProposedViewBoxMagnification(viewBox); const canvasCenter = this.canvasPoint(rectCenter(viewBox)); diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index add54279a0..d6e37be438 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -303,7 +303,17 @@ export class EditorController { }, { title: "Zoom to fit", - enabled: () => true, + enabled: () => { + let viewBox = this.sceneController.getSelectionBox(); + const size = rectSize(viewBox); + if (size.width < 4 && size.height < 4) { + const center = rectCenter(viewBox); + viewBox = centeredRect(center.x, center.y, 10, 10); + } else { + viewBox = rectAddMargin(viewBox, 0.1); + } + return !this.canvasController.isActualViewBox(viewBox); + }, shortCut: { keysOrCodes: "0", metaKey: true, globalOverride: true }, callback: () => { this.zoomFit(); From 1782e91de0e35845812477d8ece7be96ee5e4f2e Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Fri, 23 Feb 2024 12:57:29 +0300 Subject: [PATCH 27/38] Help menu links --- src/fontra/views/editor/editor.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index d6e37be438..d3f6ea7c7b 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -357,9 +357,23 @@ export class EditorController { enabled: () => true, getItems: () => { return [ + { + title: "Homepage", + enabled: () => true, + callback: () => { + window.open("https://fontra.xyz/"); + }, + }, { title: "Documentation", enabled: () => true, + callback: () => { + window.open("https://gferreira.github.io/fontra-docs/"); + }, + }, + { + title: "GitHub", + enabled: () => true, callback: () => { window.open("https://github.com/googlefonts/fontra"); }, From e88aafbc5e2c204ff468842355f30491ec88fb2d Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Fri, 23 Feb 2024 13:09:07 +0300 Subject: [PATCH 28/38] Thinner top-bar --- src/fontra/client/web-components/menu-bar.js | 4 ++-- src/fontra/views/editor/editor.css | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index 4d2c2e6328..f6a25c2ef3 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -5,7 +5,7 @@ import { MenuPanel } from "./menu-panel.js"; export class MenuBar extends SimpleElement { static styles = ` .menu-bar { - padding: 0.5rem 1rem; + padding: 0.2rem 0.5rem; align-items: center; position: absolute; font-size: 1rem; @@ -13,7 +13,7 @@ export class MenuBar extends SimpleElement { } .menu-item { - padding: 0.5rem 1rem; + padding: 0.4rem 0.6rem; display: inline-block; cursor: default; user-select: none; diff --git a/src/fontra/views/editor/editor.css b/src/fontra/views/editor/editor.css index 70482c66a8..12e772ebb6 100644 --- a/src/fontra/views/editor/editor.css +++ b/src/fontra/views/editor/editor.css @@ -20,7 +20,7 @@ --editor-top-bar-border-color-dark: #2e2e2e; --editor-top-bar-link-hover-light: #e1e1e1; --editor-top-bar-link-hover-dark: rgb(47, 47, 47); - --editor-top-bar-height: 45px; + --editor-top-bar-height: 35px; } :root { From b39c2df4feb69c3497b072cd3a53b07b52d30137 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Tue, 27 Feb 2024 08:46:36 +0300 Subject: [PATCH 29/38] Fix: The "Edit" menu doesn't work when a glyph is in edit mode" --- src/fontra/views/editor/editor.js | 4 ++-- src/fontra/views/editor/scene-controller.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index d3f6ea7c7b..573441e5c2 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -1770,7 +1770,7 @@ export class EditorController { } } - buildContextMenuItems() { + buildContextMenuItems(event) { const menuItems = [...this.basicContextMenuItems]; if (this.sceneSettings.selectedGlyph?.isEditing) { this.sceneController.updateContextMenuState(event); @@ -1788,7 +1788,7 @@ export class EditorController { event.preventDefault(); const { x, y } = event; - showMenu(this.buildContextMenuItems(), { x: x + 1, y: y - 1 }, event.target); + showMenu(this.buildContextMenuItems(event), { x: x + 1, y: y - 1 }, event.target); } async newGlyph(glyphName, codePoint, varGlyph, undoLabel = null) { diff --git a/src/fontra/views/editor/scene-controller.js b/src/fontra/views/editor/scene-controller.js index c3e558f1f4..19b93bab54 100644 --- a/src/fontra/views/editor/scene-controller.js +++ b/src/fontra/views/editor/scene-controller.js @@ -568,7 +568,7 @@ export class SceneController { } localPoint(event) { - if (event.x !== undefined) { + if (event && event.x !== undefined) { this._currentLocalPoint = this.canvasController.localPoint(event); } return this._currentLocalPoint || { x: 0, y: 0 }; From 9ec1d4c9d4456b66d0dcc76705d1b62fa6f65242 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Tue, 27 Feb 2024 09:02:24 +0300 Subject: [PATCH 30/38] Disable the add source if there is no selected glyph --- src/fontra/views/editor/editor.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 573441e5c2..7bde60c57e 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -329,7 +329,9 @@ export class EditorController { return [ { title: "Add source", - enabled: () => true, + enabled: () => { + return typeof this.sceneModel.selectedGlyph !== "undefined"; + }, callback: () => { this.getSidebarPanel("designspace-navigation").addSource(); }, From b254f4243cae49ab8296be8feede7cd57682ee9d Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Tue, 27 Feb 2024 19:37:11 +0300 Subject: [PATCH 31/38] Add delete source to Glyph menu --- src/fontra/views/editor/editor.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 6d422a02c9..446fa8d185 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -337,6 +337,20 @@ export class EditorController { this.getSidebarPanel("designspace-navigation").addSource(); }, }, + { + title: "Delete source", + enabled: () => { + return typeof this.sceneModel.selectedGlyph !== "undefined"; + }, + callback: () => { + const designspaceNavigationPanel = this.getSidebarPanel( + "designspace-navigation" + ); + designspaceNavigationPanel.removeSource( + designspaceNavigationPanel.sourcesList.getSelectedItemIndex() + ); + }, + }, ]; }, }, From 2edee7fc13f5e0dec29dcec75801e15f6d61e10e Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Tue, 27 Feb 2024 19:42:34 +0300 Subject: [PATCH 32/38] Edit local axes --- src/fontra/views/editor/editor.js | 9 +++++++++ src/fontra/views/editor/panel-designspace-navigation.js | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 446fa8d185..75769bb345 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -351,6 +351,15 @@ export class EditorController { ); }, }, + { + title: "Edit local axes", + enabled: () => { + return typeof this.sceneModel.selectedGlyph !== "undefined"; + }, + callback: () => { + this.getSidebarPanel("designspace-navigation").editLocalAxes(); + }, + }, ]; }, }, diff --git a/src/fontra/views/editor/panel-designspace-navigation.js b/src/fontra/views/editor/panel-designspace-navigation.js index 38ffd01c0f..c187020697 100644 --- a/src/fontra/views/editor/panel-designspace-navigation.js +++ b/src/fontra/views/editor/panel-designspace-navigation.js @@ -906,7 +906,7 @@ export default class DesignspaceNavigationPanel extends Panel { button.disabled = !this.sceneModel.selectedGlyph; } - async editLocalAxes(event) { + async editLocalAxes() { const varGlyphController = await this.sceneModel.getSelectedVariableGlyphController(); if (!varGlyphController) { From f04663ad98a489712883233f12e54c9d1bb8e60a Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Tue, 27 Feb 2024 19:49:35 +0300 Subject: [PATCH 33/38] The labels of menu items that open a dialog should end with "..." --- src/fontra/views/editor/editor.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 75769bb345..cf4e771e11 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -329,7 +329,7 @@ export class EditorController { getItems: () => { return [ { - title: "Add source", + title: "Add source...", enabled: () => { return typeof this.sceneModel.selectedGlyph !== "undefined"; }, @@ -338,7 +338,7 @@ export class EditorController { }, }, { - title: "Delete source", + title: "Delete source...", enabled: () => { return typeof this.sceneModel.selectedGlyph !== "undefined"; }, @@ -352,7 +352,7 @@ export class EditorController { }, }, { - title: "Edit local axes", + title: "Edit local axes...", enabled: () => { return typeof this.sceneModel.selectedGlyph !== "undefined"; }, From c22e8016cc1af6e94b2803cb79c81f1e295e6627 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Tue, 27 Feb 2024 21:45:43 +0300 Subject: [PATCH 34/38] Add select previous-next source under glyph menu --- src/fontra/views/editor/editor.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index cf4e771e11..04b25a81f9 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -279,7 +279,13 @@ export class EditorController { { title: "Edit", getItems: () => { - return this.buildContextMenuItems(); + const menuItems = [...this.basicContextMenuItems]; + if (this.sceneSettings.selectedGlyph?.isEditing) { + this.sceneController.updateContextMenuState(event); + menuItems.push(MenuItemDivider); + menuItems.push(...this.glyphEditContextMenuItems); + } + return menuItems; }, }, { @@ -327,7 +333,7 @@ export class EditorController { title: "Glyph", enabled: () => true, getItems: () => { - return [ + const items = [ { title: "Add source...", enabled: () => { @@ -361,6 +367,12 @@ export class EditorController { }, }, ]; + if (typeof this.sceneModel.selectedGlyph !== "undefined") { + this.sceneController.updateContextMenuState(); + items.push(MenuItemDivider); + items.push(...this.glyphSelectedContextMenuItems); + } + return items; }, }, { From 6a2fc722bdae2a7237ae248fdc270b68a5d656c8 Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Tue, 27 Feb 2024 23:03:09 +0300 Subject: [PATCH 35/38] Reset the menu state when menu panel dismissed itself --- src/fontra/client/web-components/menu-bar.js | 19 +++++++++++++++---- .../client/web-components/menu-panel.js | 5 ++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index f6a25c2ef3..dc4b7862db 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -106,10 +106,21 @@ export class MenuBar extends SimpleElement { x: clientRect.x, y: clientRect.y + clientRect.height, }; - const menuPanel = new MenuPanel(items, position, undefined, () => { - this.showMenuWhenHover = false; - this.clearCurrentSelection(); - }); + const menuPanel = new MenuPanel( + items, + position, + undefined, + () => { + this.showMenuWhenHover = false; + this.clearCurrentSelection(); + }, + true, + undefined, + () => { + this.showMenuWhenHover = false; + this.clearCurrentSelection(); + } + ); this.contentElement.appendChild(menuPanel); } diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 0e5b4c0534..a925fc7ad3 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -104,13 +104,15 @@ export class MenuPanel extends SimpleElement { positionContainer, onSelect, visible = true, - childOf + childOf, + onClose ) { super(); this.style = "display: none;"; this.visible = visible; this.position = position; this.onSelect = onSelect; + this.onClose = onClose; this.positionContainer = positionContainer; this.menuElement = html.div({ class: "menu-container", tabindex: 0 }); this.childOf = childOf; @@ -226,6 +228,7 @@ export class MenuPanel extends SimpleElement { } this.parentElement?.removeChild(this); this._savedActiveElement?.focus(); + this.onClose?.(); } selectItem(itemElement) { From decdf7166903bf6ab55bd28ca3b3a4742d31742a Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Thu, 29 Feb 2024 00:55:18 +0300 Subject: [PATCH 36/38] Make MenuPanel constructor arguments an object --- src/fontra/client/web-components/menu-bar.js | 14 +++---- .../client/web-components/menu-panel.js | 40 ++++++++----------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index dc4b7862db..bb5244a2af 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -106,21 +106,17 @@ export class MenuBar extends SimpleElement { x: clientRect.x, y: clientRect.y + clientRect.height, }; - const menuPanel = new MenuPanel( - items, + const menuPanel = new MenuPanel(items, { position, - undefined, - () => { + onSelect() { this.showMenuWhenHover = false; this.clearCurrentSelection(); }, - true, - undefined, - () => { + onClose() { this.showMenuWhenHover = false; this.clearCurrentSelection(); - } - ); + }, + }); this.contentElement.appendChild(menuPanel); } diff --git a/src/fontra/client/web-components/menu-panel.js b/src/fontra/client/web-components/menu-panel.js index 09b58a9af4..c4ada8a915 100644 --- a/src/fontra/client/web-components/menu-panel.js +++ b/src/fontra/client/web-components/menu-panel.js @@ -10,7 +10,7 @@ export function showMenu(menuItems, position, positionContainer, container) { if (!container) { container = document.querySelector("#menu-panel-container"); } - const menu = new MenuPanel(menuItems, position, positionContainer); + const menu = new MenuPanel(menuItems, { position, positionContainer }); container.appendChild(menu); } @@ -98,24 +98,17 @@ export class MenuPanel extends SimpleElement { } `; - constructor( - menuItems, - position, - positionContainer, - onSelect, - visible = true, - childOf, - onClose - ) { + constructor(menuItems, options = {}) { super(); + options = { visible: true, ...options }; this.style = "display: none;"; - this.visible = visible; - this.position = position; - this.onSelect = onSelect; - this.onClose = onClose; - this.positionContainer = positionContainer; + this.visible = options.visible; + this.position = options.position; + this.onSelect = options.onSelect; + this.onClose = options.onClose; + this.positionContainer = options.positionContainer; this.menuElement = html.div({ class: "menu-container", tabindex: 0 }); - this.childOf = childOf; + this.childOf = options.childOf; this.menuSearchText = ""; // No context menu on our context menu please: @@ -255,16 +248,15 @@ export class MenuPanel extends SimpleElement { if (itemElement.classList.contains("with-submenu")) { const { y: menuElementY } = this.getBoundingClientRect(); const { y, width } = itemElement.getBoundingClientRect(); - const submenu = new MenuPanel( + const submenu = new Menupanel( this.menuItems[itemElement.dataset.index].getItems(), { - x: 0, - y: 0, - }, - undefined, - undefined, - false, - this + position: { + x: 0, + y: 0, + }, + childOf: this, + } ); this.menuElement.appendChild(submenu); submenu.position = { x: width, y: y - menuElementY - 4 }; From 82e5db0020c6a757d92d5023526e5df99a88671b Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Thu, 29 Feb 2024 00:58:49 +0300 Subject: [PATCH 37/38] Move selected glyph items under View --- src/fontra/views/editor/editor.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/fontra/views/editor/editor.js b/src/fontra/views/editor/editor.js index 04b25a81f9..7880047d6a 100644 --- a/src/fontra/views/editor/editor.js +++ b/src/fontra/views/editor/editor.js @@ -291,7 +291,7 @@ export class EditorController { { title: "View", getItems: () => { - return [ + const items = [ { title: "Zoom in", enabled: () => true, @@ -327,13 +327,19 @@ export class EditorController { }, }, ]; + if (typeof this.sceneModel.selectedGlyph !== "undefined") { + this.sceneController.updateContextMenuState(); + items.push(MenuItemDivider); + items.push(...this.glyphSelectedContextMenuItems); + } + return items; }, }, { title: "Glyph", enabled: () => true, getItems: () => { - const items = [ + return [ { title: "Add source...", enabled: () => { @@ -367,12 +373,6 @@ export class EditorController { }, }, ]; - if (typeof this.sceneModel.selectedGlyph !== "undefined") { - this.sceneController.updateContextMenuState(); - items.push(MenuItemDivider); - items.push(...this.glyphSelectedContextMenuItems); - } - return items; }, }, { From 493b044000b1bbf70e669820dac94b1ac5d73dcc Mon Sep 17 00:00:00 2001 From: Fatih Erikli Date: Thu, 29 Feb 2024 01:01:39 +0300 Subject: [PATCH 38/38] Fix 'this' w arrow functions --- src/fontra/client/web-components/menu-bar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fontra/client/web-components/menu-bar.js b/src/fontra/client/web-components/menu-bar.js index bb5244a2af..4167d42c49 100644 --- a/src/fontra/client/web-components/menu-bar.js +++ b/src/fontra/client/web-components/menu-bar.js @@ -108,11 +108,11 @@ export class MenuBar extends SimpleElement { }; const menuPanel = new MenuPanel(items, { position, - onSelect() { + onSelect: () => { this.showMenuWhenHover = false; this.clearCurrentSelection(); }, - onClose() { + onClose: () => { this.showMenuWhenHover = false; this.clearCurrentSelection(); },