From 60d2571e830b9f8c7c2a63b1781e55609c8aa03d Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Tue, 1 Oct 2024 15:46:43 +0200 Subject: [PATCH 1/9] Add actions to transformation panel --- src/fontra/client/lang/en.json | 1 + src/fontra/client/lang/zh-CN.json | 1 + .../views/editor/panel-transformation.js | 36 +++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/src/fontra/client/lang/en.json b/src/fontra/client/lang/en.json index 3a3cf2aca..3c9f1e4c6 100644 --- a/src/fontra/client/lang/en.json +++ b/src/fontra/client/lang/en.json @@ -3,6 +3,7 @@ "action-topics.glyph-editor-appearance": "Glyph editor appearance", "action-topics.menu.edit": "Edit", "action-topics.menu.view": "View", + "action-topics.selection-transformations": "Selection Transformations", "action-topics.sidebars": "Sidebars", "action-topics.tools": "Tools", "action.add-anchor": "Add Anchor", diff --git a/src/fontra/client/lang/zh-CN.json b/src/fontra/client/lang/zh-CN.json index 6762a3b33..b0157dd24 100644 --- a/src/fontra/client/lang/zh-CN.json +++ b/src/fontra/client/lang/zh-CN.json @@ -3,6 +3,7 @@ "action-topics.glyph-editor-appearance": "字符形编辑器外观", "action-topics.menu.edit": "编辑", "action-topics.menu.view": "视图", + "action-topics.selection-transformations": "Selection Transformations", "action-topics.sidebars": "Sidebars", "action-topics.tools": "Tools", "action.add-anchor": "添加锚点", diff --git a/src/fontra/views/editor/panel-transformation.js b/src/fontra/views/editor/panel-transformation.js index 913c8e4b8..07d8181f9 100644 --- a/src/fontra/views/editor/panel-transformation.js +++ b/src/fontra/views/editor/panel-transformation.js @@ -1,3 +1,4 @@ +import { registerAction } from "../core/actions.js"; import { ChangeCollector, applyChange, consolidateChanges } from "../core/changes.js"; import { EditBehaviorFactory } from "./edit-behavior.js"; import Panel from "./panel.js"; @@ -410,6 +411,26 @@ export default class TransformationPanel extends Panel { label: translate("sidebar.selection-transformation.distribute"), }); + const topic = "0070-action-topics.selection-transformations"; + + const registerActionsDistribute = [ + ["align.left", alignLeft], + ["align.center", alignCenter], + ["align.right", alignRight], + ["align.top", alignTop], + ["align.middle", alignMiddle], + ["align.bottom", alignBottom], + ["distribute.horizontally", distributeHorizontally], + ["distribute.vertically", distributeVertically], + ]; + for (const [keyPart, moveDescriptor] of registerActionsDistribute) { + registerAction( + `action.selection-transformation.${keyPart}`, + { topic, titleKey: `sidebar.selection-transformation.${keyPart}` }, + () => this.moveObjects(moveDescriptor) + ); + } + formContents.push({ type: "universal-row", field1: { @@ -466,6 +487,21 @@ export default class TransformationPanel extends Panel { const labelExclude = translate( "sidebar.selection-transformation.path-operations.exclude" ); + + const registerActionsPathOperations = [ + ["path-operations.union", unionPath, labelUnion], + ["path-operations.subtract", subtractPath, labelSubtract], + ["path-operations.intersect", intersectPath, labelIntersect], + ["path-operations.exclude", excludePath, labelExclude], + ]; + for (const [keyPart, pathOperationFunc, label] of registerActionsPathOperations) { + registerAction( + `action.selection-transformation.${keyPart}`, + { topic, titleKey: `sidebar.selection-transformation.${keyPart}` }, + () => this.doPathOperations(pathOperationFunc, label) + ); + } + formContents.push({ type: "universal-row", field1: { From e59433d1b23039d5caf29a60f98a55728a94fd99 Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Tue, 1 Oct 2024 16:03:16 +0200 Subject: [PATCH 2/9] Update const name --- src/fontra/views/editor/panel-transformation.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fontra/views/editor/panel-transformation.js b/src/fontra/views/editor/panel-transformation.js index 07d8181f9..1994d1d3a 100644 --- a/src/fontra/views/editor/panel-transformation.js +++ b/src/fontra/views/editor/panel-transformation.js @@ -413,7 +413,7 @@ export default class TransformationPanel extends Panel { const topic = "0070-action-topics.selection-transformations"; - const registerActionsDistribute = [ + const registerActions = [ ["align.left", alignLeft], ["align.center", alignCenter], ["align.right", alignRight], @@ -423,7 +423,7 @@ export default class TransformationPanel extends Panel { ["distribute.horizontally", distributeHorizontally], ["distribute.vertically", distributeVertically], ]; - for (const [keyPart, moveDescriptor] of registerActionsDistribute) { + for (const [keyPart, moveDescriptor] of registerActions) { registerAction( `action.selection-transformation.${keyPart}`, { topic, titleKey: `sidebar.selection-transformation.${keyPart}` }, From 8350e390f36be8ea2ec17c2e07482c0e3ccfaa8d Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Thu, 3 Oct 2024 10:32:07 +0200 Subject: [PATCH 3/9] Create new method registerActions and call in constructor --- .../views/editor/panel-transformation.js | 84 +++++++++++-------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/src/fontra/views/editor/panel-transformation.js b/src/fontra/views/editor/panel-transformation.js index 1994d1d3a..2f1326824 100644 --- a/src/fontra/views/editor/panel-transformation.js +++ b/src/fontra/views/editor/panel-transformation.js @@ -102,6 +102,56 @@ export default class TransformationPanel extends Panel { skewY: 0, customDistributionSpacing: null, }; + this.registerActions(); + } + + registerActions() { + const topic = "0070-action-topics.selection-transformations"; + + const registerActions = [ + ["align.left", alignLeft], + ["align.center", alignCenter], + ["align.right", alignRight], + ["align.top", alignTop], + ["align.middle", alignMiddle], + ["align.bottom", alignBottom], + ["distribute.horizontally", distributeHorizontally], + ["distribute.vertically", distributeVertically], + ]; + for (const [keyPart, moveDescriptor] of registerActions) { + registerAction( + `action.selection-transformation.${keyPart}`, + { topic, titleKey: `sidebar.selection-transformation.${keyPart}` }, + () => this.moveObjects(moveDescriptor) + ); + } + + const labelUnion = translate( + "sidebar.selection-transformation.path-operations.union" + ); + const labelSubtract = translate( + "sidebar.selection-transformation.path-operations.subtract" + ); + const labelIntersect = translate( + "sidebar.selection-transformation.path-operations.intersect" + ); + const labelExclude = translate( + "sidebar.selection-transformation.path-operations.exclude" + ); + + const registerActionsPathOperations = [ + ["path-operations.union", unionPath, labelUnion], + ["path-operations.subtract", subtractPath, labelSubtract], + ["path-operations.intersect", intersectPath, labelIntersect], + ["path-operations.exclude", excludePath, labelExclude], + ]; + for (const [keyPart, pathOperationFunc, label] of registerActionsPathOperations) { + registerAction( + `action.selection-transformation.${keyPart}`, + { topic, titleKey: `sidebar.selection-transformation.${keyPart}` }, + () => this.doPathOperations(pathOperationFunc, label) + ); + } } getContentElement() { @@ -411,26 +461,6 @@ export default class TransformationPanel extends Panel { label: translate("sidebar.selection-transformation.distribute"), }); - const topic = "0070-action-topics.selection-transformations"; - - const registerActions = [ - ["align.left", alignLeft], - ["align.center", alignCenter], - ["align.right", alignRight], - ["align.top", alignTop], - ["align.middle", alignMiddle], - ["align.bottom", alignBottom], - ["distribute.horizontally", distributeHorizontally], - ["distribute.vertically", distributeVertically], - ]; - for (const [keyPart, moveDescriptor] of registerActions) { - registerAction( - `action.selection-transformation.${keyPart}`, - { topic, titleKey: `sidebar.selection-transformation.${keyPart}` }, - () => this.moveObjects(moveDescriptor) - ); - } - formContents.push({ type: "universal-row", field1: { @@ -488,20 +518,6 @@ export default class TransformationPanel extends Panel { "sidebar.selection-transformation.path-operations.exclude" ); - const registerActionsPathOperations = [ - ["path-operations.union", unionPath, labelUnion], - ["path-operations.subtract", subtractPath, labelSubtract], - ["path-operations.intersect", intersectPath, labelIntersect], - ["path-operations.exclude", excludePath, labelExclude], - ]; - for (const [keyPart, pathOperationFunc, label] of registerActionsPathOperations) { - registerAction( - `action.selection-transformation.${keyPart}`, - { topic, titleKey: `sidebar.selection-transformation.${keyPart}` }, - () => this.doPathOperations(pathOperationFunc, label) - ); - } - formContents.push({ type: "universal-row", field1: { From 1d9301cc31b9a557d4aa1526d6a78030aa83a4d4 Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Thu, 3 Oct 2024 10:48:31 +0200 Subject: [PATCH 4/9] Refactoring code --- .../views/editor/panel-transformation.js | 71 +++++++------------ 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/src/fontra/views/editor/panel-transformation.js b/src/fontra/views/editor/panel-transformation.js index 2f1326824..9ba797dd1 100644 --- a/src/fontra/views/editor/panel-transformation.js +++ b/src/fontra/views/editor/panel-transformation.js @@ -126,30 +126,20 @@ export default class TransformationPanel extends Panel { ); } - const labelUnion = translate( - "sidebar.selection-transformation.path-operations.union" - ); - const labelSubtract = translate( - "sidebar.selection-transformation.path-operations.subtract" - ); - const labelIntersect = translate( - "sidebar.selection-transformation.path-operations.intersect" - ); - const labelExclude = translate( - "sidebar.selection-transformation.path-operations.exclude" - ); - const registerActionsPathOperations = [ - ["path-operations.union", unionPath, labelUnion], - ["path-operations.subtract", subtractPath, labelSubtract], - ["path-operations.intersect", intersectPath, labelIntersect], - ["path-operations.exclude", excludePath, labelExclude], + ["union", unionPath], + ["subtract", subtractPath], + ["intersect", intersectPath], + ["exclude", excludePath], ]; - for (const [keyPart, pathOperationFunc, label] of registerActionsPathOperations) { + for (const [keyPart, pathOperationFunc] of registerActionsPathOperations) { registerAction( - `action.selection-transformation.${keyPart}`, - { topic, titleKey: `sidebar.selection-transformation.${keyPart}` }, - () => this.doPathOperations(pathOperationFunc, label) + `action.selection-transformation.path-operations.${keyPart}`, + { + topic, + titleKey: `sidebar.selection-transformation.path-operations.${keyPart}`, + }, + () => this.doPathOperations(pathOperationFunc, keyPart) ); } } @@ -500,24 +490,14 @@ export default class TransformationPanel extends Panel { }); formContents.push({ type: "spacer" }); + + const labelKeyPathOperations = "sidebar.selection-transformation.path-operations"; + formContents.push({ type: "header", - label: translate("sidebar.selection-transformation.path-operations"), + label: translate(labelKeyPathOperations), }); - const labelUnion = translate( - "sidebar.selection-transformation.path-operations.union" - ); - const labelSubtract = translate( - "sidebar.selection-transformation.path-operations.subtract" - ); - const labelIntersect = translate( - "sidebar.selection-transformation.path-operations.intersect" - ); - const labelExclude = translate( - "sidebar.selection-transformation.path-operations.exclude" - ); - formContents.push({ type: "universal-row", field1: { @@ -525,8 +505,8 @@ export default class TransformationPanel extends Panel { key: "removeOverlaps", auxiliaryElement: html.createDomElement("icon-button", { "src": "/tabler-icons/layers-union.svg", - "onclick": (event) => this.doPathOperations(unionPath, labelUnion), - "data-tooltip": labelUnion, + "onclick": (event) => this.doPathOperations(unionPath, "union"), + "data-tooltip": translate(`${labelKeyPathOperations}.union`), "data-tooltipposition": "top-left", "class": "ui-form-icon ui-form-icon-button", }), @@ -536,8 +516,8 @@ export default class TransformationPanel extends Panel { key: "subtractContours", auxiliaryElement: html.createDomElement("icon-button", { "src": "/tabler-icons/layers-subtract.svg", - "onclick": (event) => this.doPathOperations(subtractPath, labelSubtract), - "data-tooltip": labelSubtract, + "onclick": (event) => this.doPathOperations(subtractPath, "subtract"), + "data-tooltip": translate(`${labelKeyPathOperations}.subtract`), "data-tooltipposition": "top", "class": "ui-form-icon", }), @@ -547,8 +527,8 @@ export default class TransformationPanel extends Panel { key: "intersectContours", auxiliaryElement: html.createDomElement("icon-button", { "src": "/tabler-icons/layers-intersect-2.svg", - "onclick": (event) => this.doPathOperations(intersectPath, labelIntersect), - "data-tooltip": labelIntersect, + "onclick": (event) => this.doPathOperations(intersectPath, "exclude"), + "data-tooltip": translate(`${labelKeyPathOperations}.exclude`), "data-tooltipposition": "top-right", "class": "ui-form-icon", }), @@ -562,8 +542,8 @@ export default class TransformationPanel extends Panel { key: "excludeContours", auxiliaryElement: html.createDomElement("icon-button", { "src": "/tabler-icons/layers-difference.svg", - "onclick": (event) => this.doPathOperations(excludePath, labelExclude), - "data-tooltip": labelExclude, + "onclick": (event) => this.doPathOperations(excludePath, "intersect"), + "data-tooltip": translate(`${labelKeyPathOperations}.intersect`), "data-tooltipposition": "top-left", "class": "ui-form-icon ui-form-icon-button", }), @@ -589,7 +569,10 @@ export default class TransformationPanel extends Panel { }; } - async doPathOperations(pathOperationFunc, undoLabel) { + async doPathOperations(pathOperationFunc, key) { + const undoLabel = translate( + `sidebar.selection-transformation.path-operations.${key}` + ); const doUnion = pathOperationFunc === unionPath; let { point: pointIndices } = parseSelection(this.sceneController.selection); pointIndices = pointIndices || []; From a1eb50ecffc6e2c4106bd843df1ab45debbbecf1 Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Thu, 3 Oct 2024 13:47:30 +0200 Subject: [PATCH 5/9] Fix bug if there is no glyph selected. --- src/fontra/views/editor/panel-transformation.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/fontra/views/editor/panel-transformation.js b/src/fontra/views/editor/panel-transformation.js index 9ba797dd1..2228da49d 100644 --- a/src/fontra/views/editor/panel-transformation.js +++ b/src/fontra/views/editor/panel-transformation.js @@ -584,6 +584,10 @@ export default class TransformationPanel extends Panel { const positionedGlyph = this.sceneController.sceneModel.getSelectedPositionedGlyph(); + if (!positionedGlyph) { + return; + } + const selectedContourIndicesMap = getSelectionByContour( positionedGlyph.glyph.path, pointIndices From f7679b00b722159123c1518bfb74abf72c6f0dc3 Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Thu, 3 Oct 2024 13:50:00 +0200 Subject: [PATCH 6/9] Fast return if no glyph selected --- src/fontra/views/editor/panel-transformation.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/fontra/views/editor/panel-transformation.js b/src/fontra/views/editor/panel-transformation.js index 2228da49d..d1ea6e460 100644 --- a/src/fontra/views/editor/panel-transformation.js +++ b/src/fontra/views/editor/panel-transformation.js @@ -570,6 +570,13 @@ export default class TransformationPanel extends Panel { } async doPathOperations(pathOperationFunc, key) { + const positionedGlyph = + this.sceneController.sceneModel.getSelectedPositionedGlyph(); + + if (!positionedGlyph) { + return; + } + const undoLabel = translate( `sidebar.selection-transformation.path-operations.${key}` ); @@ -581,13 +588,6 @@ export default class TransformationPanel extends Panel { return; } - const positionedGlyph = - this.sceneController.sceneModel.getSelectedPositionedGlyph(); - - if (!positionedGlyph) { - return; - } - const selectedContourIndicesMap = getSelectionByContour( positionedGlyph.glyph.path, pointIndices From 38f9058af1dbff3bb6442535c4abeb3b2075da54 Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Thu, 3 Oct 2024 14:00:30 +0200 Subject: [PATCH 7/9] Fix wrong names for path operations --- src/fontra/views/editor/panel-transformation.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fontra/views/editor/panel-transformation.js b/src/fontra/views/editor/panel-transformation.js index d1ea6e460..e108e7386 100644 --- a/src/fontra/views/editor/panel-transformation.js +++ b/src/fontra/views/editor/panel-transformation.js @@ -527,8 +527,8 @@ export default class TransformationPanel extends Panel { key: "intersectContours", auxiliaryElement: html.createDomElement("icon-button", { "src": "/tabler-icons/layers-intersect-2.svg", - "onclick": (event) => this.doPathOperations(intersectPath, "exclude"), - "data-tooltip": translate(`${labelKeyPathOperations}.exclude`), + "onclick": (event) => this.doPathOperations(intersectPath, "intersect"), + "data-tooltip": translate(`${labelKeyPathOperations}.intersect`), "data-tooltipposition": "top-right", "class": "ui-form-icon", }), @@ -542,8 +542,8 @@ export default class TransformationPanel extends Panel { key: "excludeContours", auxiliaryElement: html.createDomElement("icon-button", { "src": "/tabler-icons/layers-difference.svg", - "onclick": (event) => this.doPathOperations(excludePath, "intersect"), - "data-tooltip": translate(`${labelKeyPathOperations}.intersect`), + "onclick": (event) => this.doPathOperations(excludePath, "exclude"), + "data-tooltip": translate(`${labelKeyPathOperations}.exclude`), "data-tooltipposition": "top-left", "class": "ui-form-icon ui-form-icon-button", }), From 464aa1f2f8281b3c7c97b567a1f683e9d53d43cc Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Thu, 3 Oct 2024 14:10:08 +0200 Subject: [PATCH 8/9] Only run doPathOperations if is in edit mode (isEditing) --- src/fontra/views/editor/panel-transformation.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/fontra/views/editor/panel-transformation.js b/src/fontra/views/editor/panel-transformation.js index e108e7386..ad592c65e 100644 --- a/src/fontra/views/editor/panel-transformation.js +++ b/src/fontra/views/editor/panel-transformation.js @@ -570,6 +570,10 @@ export default class TransformationPanel extends Panel { } async doPathOperations(pathOperationFunc, key) { + if (!this.sceneController.sceneSettings.selectedGlyph?.isEditing) { + return; + } + const positionedGlyph = this.sceneController.sceneModel.getSelectedPositionedGlyph(); From aeaa2e0d47699c655d4e0391e781c84ccc2726c0 Mon Sep 17 00:00:00 2001 From: Olli Meier Date: Thu, 3 Oct 2024 14:22:01 +0200 Subject: [PATCH 9/9] Better variable names --- src/fontra/views/editor/panel-transformation.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fontra/views/editor/panel-transformation.js b/src/fontra/views/editor/panel-transformation.js index ad592c65e..9b426dff0 100644 --- a/src/fontra/views/editor/panel-transformation.js +++ b/src/fontra/views/editor/panel-transformation.js @@ -108,7 +108,7 @@ export default class TransformationPanel extends Panel { registerActions() { const topic = "0070-action-topics.selection-transformations"; - const registerActions = [ + const moveActions = [ ["align.left", alignLeft], ["align.center", alignCenter], ["align.right", alignRight], @@ -118,7 +118,7 @@ export default class TransformationPanel extends Panel { ["distribute.horizontally", distributeHorizontally], ["distribute.vertically", distributeVertically], ]; - for (const [keyPart, moveDescriptor] of registerActions) { + for (const [keyPart, moveDescriptor] of moveActions) { registerAction( `action.selection-transformation.${keyPart}`, { topic, titleKey: `sidebar.selection-transformation.${keyPart}` }, @@ -126,13 +126,13 @@ export default class TransformationPanel extends Panel { ); } - const registerActionsPathOperations = [ + const pathActions = [ ["union", unionPath], ["subtract", subtractPath], ["intersect", intersectPath], ["exclude", excludePath], ]; - for (const [keyPart, pathOperationFunc] of registerActionsPathOperations) { + for (const [keyPart, pathOperationFunc] of pathActions) { registerAction( `action.selection-transformation.path-operations.${keyPart}`, {