From aa0807ca3f6a92a3cdaca9bb7e59cf9be1fa0975 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Thu, 6 Oct 2022 17:37:26 +0200 Subject: [PATCH] Limit interface scale (#1502) * limit interface scale * debounce interface scale updates * limit font-size + refactor * remove excessive settings duplicate * remove useless async * fix interface scale step * change mainMenuManager visibility to private * fix menu registration * update menu actions when autoScaleInterface changes --- .../browser/arduino-ide-frontend-module.ts | 2 + .../contributions/edit-contributions.ts | 56 ----- .../browser/contributions/interface-scale.ts | 228 ++++++++++++++++++ .../dialogs/settings/settings-component.tsx | 25 +- 4 files changed, 246 insertions(+), 65 deletions(-) create mode 100644 arduino-ide-extension/src/browser/contributions/interface-scale.ts diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index afa5eb5ec..380c2c9ab 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -333,6 +333,7 @@ import { StartupTaskProvider } from '../electron-common/startup-task'; import { DeleteSketch } from './contributions/delete-sketch'; import { UserFields } from './contributions/user-fields'; import { UpdateIndexes } from './contributions/update-indexes'; +import { InterfaceScale } from './contributions/interface-scale'; const registerArduinoThemes = () => { const themes: MonacoThemeJson[] = [ @@ -746,6 +747,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { Contribution.configure(bind, UserFields); Contribution.configure(bind, DeleteSketch); Contribution.configure(bind, UpdateIndexes); + Contribution.configure(bind, InterfaceScale); bindContributionProvider(bind, StartupTaskProvider); bind(StartupTaskProvider).toService(BoardsServiceProvider); // to reuse the boards config in another window diff --git a/arduino-ide-extension/src/browser/contributions/edit-contributions.ts b/arduino-ide-extension/src/browser/contributions/edit-contributions.ts index 7c75c7225..cc1451ec3 100644 --- a/arduino-ide-extension/src/browser/contributions/edit-contributions.ts +++ b/arduino-ide-extension/src/browser/contributions/edit-contributions.ts @@ -49,30 +49,6 @@ export class EditContributions extends Contribution { registry.registerCommand(EditContributions.Commands.USE_FOR_FIND, { execute: () => this.run('editor.action.previousSelectionMatchFindAction'), }); - registry.registerCommand(EditContributions.Commands.INCREASE_FONT_SIZE, { - execute: async () => { - const settings = await this.settingsService.settings(); - if (settings.autoScaleInterface) { - settings.interfaceScale = settings.interfaceScale + 1; - } else { - settings.editorFontSize = settings.editorFontSize + 1; - } - await this.settingsService.update(settings); - await this.settingsService.save(); - }, - }); - registry.registerCommand(EditContributions.Commands.DECREASE_FONT_SIZE, { - execute: async () => { - const settings = await this.settingsService.settings(); - if (settings.autoScaleInterface) { - settings.interfaceScale = settings.interfaceScale - 1; - } else { - settings.editorFontSize = settings.editorFontSize - 1; - } - await this.settingsService.update(settings); - await this.settingsService.save(); - }, - }); /* Tools */ registry.registerCommand( EditContributions.Commands.AUTO_FORMAT, { execute: () => this.run('editor.action.formatDocument') } @@ -147,23 +123,6 @@ ${value} order: '3', }); - registry.registerMenuAction(ArduinoMenus.EDIT__FONT_CONTROL_GROUP, { - commandId: EditContributions.Commands.INCREASE_FONT_SIZE.id, - label: nls.localize( - 'arduino/editor/increaseFontSize', - 'Increase Font Size' - ), - order: '0', - }); - registry.registerMenuAction(ArduinoMenus.EDIT__FONT_CONTROL_GROUP, { - commandId: EditContributions.Commands.DECREASE_FONT_SIZE.id, - label: nls.localize( - 'arduino/editor/decreaseFontSize', - 'Decrease Font Size' - ), - order: '1', - }); - registry.registerMenuAction(ArduinoMenus.EDIT__FIND_GROUP, { commandId: EditContributions.Commands.FIND.id, label: nls.localize('vscode/findController/startFindAction', 'Find'), @@ -220,15 +179,6 @@ ${value} when: 'editorFocus', }); - registry.registerKeybinding({ - command: EditContributions.Commands.INCREASE_FONT_SIZE.id, - keybinding: 'CtrlCmd+=', - }); - registry.registerKeybinding({ - command: EditContributions.Commands.DECREASE_FONT_SIZE.id, - keybinding: 'CtrlCmd+-', - }); - registry.registerKeybinding({ command: EditContributions.Commands.FIND.id, keybinding: 'CtrlCmd+F', @@ -315,12 +265,6 @@ export namespace EditContributions { export const USE_FOR_FIND: Command = { id: 'arduino-for-find', }; - export const INCREASE_FONT_SIZE: Command = { - id: 'arduino-increase-font-size', - }; - export const DECREASE_FONT_SIZE: Command = { - id: 'arduino-decrease-font-size', - }; export const AUTO_FORMAT: Command = { id: 'arduino-auto-format', // `Auto Format` should belong to `Tool`. }; diff --git a/arduino-ide-extension/src/browser/contributions/interface-scale.ts b/arduino-ide-extension/src/browser/contributions/interface-scale.ts new file mode 100644 index 000000000..eefd1ab6e --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/interface-scale.ts @@ -0,0 +1,228 @@ +import { inject, injectable } from '@theia/core/shared/inversify'; +import { + Contribution, + Command, + MenuModelRegistry, + KeybindingRegistry, +} from './contribution'; +import { ArduinoMenus, PlaceholderMenuNode } from '../menu/arduino-menus'; +import { + CommandRegistry, + DisposableCollection, + MaybePromise, + nls, +} from '@theia/core/lib/common'; + +import { Settings } from '../dialogs/settings/settings'; +import { MainMenuManager } from '../../common/main-menu-manager'; +import debounce = require('lodash.debounce'); + +@injectable() +export class InterfaceScale extends Contribution { + @inject(MenuModelRegistry) + private readonly menuRegistry: MenuModelRegistry; + + @inject(MainMenuManager) + private readonly mainMenuManager: MainMenuManager; + + private readonly menuActionsDisposables = new DisposableCollection(); + private fontScalingEnabled: InterfaceScale.FontScalingEnabled = { + increase: true, + decrease: true, + }; + + private currentSettings: Settings; + private updateSettingsDebounced = debounce( + async () => { + await this.settingsService.update(this.currentSettings); + await this.settingsService.save(); + }, + 100, + { maxWait: 200 } + ); + + override onStart(): MaybePromise { + const updateCurrent = (settings: Settings) => { + this.currentSettings = settings; + this.updateFontScalingEnabled(); + }; + this.settingsService.onDidChange((settings) => updateCurrent(settings)); + this.settingsService.settings().then((settings) => updateCurrent(settings)); + } + + override registerCommands(registry: CommandRegistry): void { + registry.registerCommand(InterfaceScale.Commands.INCREASE_FONT_SIZE, { + execute: () => this.updateFontSize('increase'), + isEnabled: () => this.fontScalingEnabled.increase, + }); + registry.registerCommand(InterfaceScale.Commands.DECREASE_FONT_SIZE, { + execute: () => this.updateFontSize('decrease'), + isEnabled: () => this.fontScalingEnabled.decrease, + }); + } + + override registerMenus(registry: MenuModelRegistry): void { + this.menuActionsDisposables.dispose(); + const increaseFontSizeMenuAction = { + commandId: InterfaceScale.Commands.INCREASE_FONT_SIZE.id, + label: nls.localize( + 'arduino/editor/increaseFontSize', + 'Increase Font Size' + ), + order: '0', + }; + const decreaseFontSizeMenuAction = { + commandId: InterfaceScale.Commands.DECREASE_FONT_SIZE.id, + label: nls.localize( + 'arduino/editor/decreaseFontSize', + 'Decrease Font Size' + ), + order: '1', + }; + + if (this.fontScalingEnabled.increase) { + this.menuActionsDisposables.push( + registry.registerMenuAction( + ArduinoMenus.EDIT__FONT_CONTROL_GROUP, + increaseFontSizeMenuAction + ) + ); + } else { + this.menuActionsDisposables.push( + registry.registerMenuNode( + ArduinoMenus.EDIT__FONT_CONTROL_GROUP, + new PlaceholderMenuNode( + ArduinoMenus.EDIT__FONT_CONTROL_GROUP, + increaseFontSizeMenuAction.label, + { order: increaseFontSizeMenuAction.order } + ) + ) + ); + } + if (this.fontScalingEnabled.decrease) { + this.menuActionsDisposables.push( + this.menuRegistry.registerMenuAction( + ArduinoMenus.EDIT__FONT_CONTROL_GROUP, + decreaseFontSizeMenuAction + ) + ); + } else { + this.menuActionsDisposables.push( + this.menuRegistry.registerMenuNode( + ArduinoMenus.EDIT__FONT_CONTROL_GROUP, + new PlaceholderMenuNode( + ArduinoMenus.EDIT__FONT_CONTROL_GROUP, + decreaseFontSizeMenuAction.label, + { order: decreaseFontSizeMenuAction.order } + ) + ) + ); + } + this.mainMenuManager.update(); + } + + private updateFontScalingEnabled(): void { + let fontScalingEnabled = { + increase: true, + decrease: true, + }; + + if (this.currentSettings.autoScaleInterface) { + fontScalingEnabled = { + increase: + this.currentSettings.interfaceScale + InterfaceScale.ZoomLevel.STEP <= + InterfaceScale.ZoomLevel.MAX, + decrease: + this.currentSettings.interfaceScale - InterfaceScale.ZoomLevel.STEP >= + InterfaceScale.ZoomLevel.MIN, + }; + } else { + fontScalingEnabled = { + increase: + this.currentSettings.editorFontSize + InterfaceScale.FontSize.STEP <= + InterfaceScale.FontSize.MAX, + decrease: + this.currentSettings.editorFontSize - InterfaceScale.FontSize.STEP >= + InterfaceScale.FontSize.MIN, + }; + } + + const isChanged = Object.keys(fontScalingEnabled).some( + (key: keyof InterfaceScale.FontScalingEnabled) => + fontScalingEnabled[key] !== this.fontScalingEnabled[key] + ); + if (isChanged) { + this.fontScalingEnabled = fontScalingEnabled; + this.registerMenus(this.menuRegistry); + } + } + + private updateFontSize(mode: 'increase' | 'decrease'): void { + if (this.currentSettings.autoScaleInterface) { + mode === 'increase' + ? (this.currentSettings.interfaceScale += InterfaceScale.ZoomLevel.STEP) + : (this.currentSettings.interfaceScale -= + InterfaceScale.ZoomLevel.STEP); + } else { + mode === 'increase' + ? (this.currentSettings.editorFontSize += InterfaceScale.FontSize.STEP) + : (this.currentSettings.editorFontSize -= InterfaceScale.FontSize.STEP); + } + this.updateFontScalingEnabled(); + this.updateSettingsDebounced(); + } + + override registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: InterfaceScale.Commands.INCREASE_FONT_SIZE.id, + keybinding: 'CtrlCmd+=', + }); + registry.registerKeybinding({ + command: InterfaceScale.Commands.DECREASE_FONT_SIZE.id, + keybinding: 'CtrlCmd+-', + }); + } +} + +export namespace InterfaceScale { + export namespace Commands { + export const INCREASE_FONT_SIZE: Command = { + id: 'arduino-increase-font-size', + }; + export const DECREASE_FONT_SIZE: Command = { + id: 'arduino-decrease-font-size', + }; + } + + export namespace ZoomLevel { + export const MIN = -8; + export const MAX = 9; + export const STEP = 1; + + export function toPercentage(scale: number): number { + return scale * 20 + 100; + } + export function fromPercentage(percentage: number): number { + return (percentage - 100) / 20; + } + export namespace Step { + export function toPercentage(step: number): number { + return step * 20; + } + export function fromPercentage(percentage: number): number { + return percentage / 20; + } + } + } + + export namespace FontSize { + export const MIN = 8; + export const MAX = 72; + export const STEP = 2; + } + + export interface FontScalingEnabled { + increase: boolean; + decrease: boolean; + } +} diff --git a/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx b/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx index dac80d61c..bbc73b8c3 100644 --- a/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx +++ b/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx @@ -23,14 +23,22 @@ import { LanguageInfo, } from '@theia/core/lib/common/i18n/localization'; import SettingsStepInput from './settings-step-input'; +import { InterfaceScale } from '../../contributions/interface-scale'; + +const maxScale = InterfaceScale.ZoomLevel.toPercentage( + InterfaceScale.ZoomLevel.MAX +); +const minScale = InterfaceScale.ZoomLevel.toPercentage( + InterfaceScale.ZoomLevel.MIN +); +const scaleStep = InterfaceScale.ZoomLevel.Step.toPercentage( + InterfaceScale.ZoomLevel.STEP +); + +const maxFontSize = InterfaceScale.FontSize.MAX; +const minFontSize = InterfaceScale.FontSize.MIN; +const fontSizeStep = InterfaceScale.FontSize.STEP; -const maxScale = 280; -const minScale = -60; -const scaleStep = 20; - -const maxFontSize = 72; -const minFontSize = 0; -const fontSizeStep = 2; export class SettingsComponent extends React.Component< SettingsComponent.Props, SettingsComponent.State @@ -554,8 +562,7 @@ export class SettingsComponent extends React.Component< }; private setInterfaceScale = (percentage: number) => { - const interfaceScale = (percentage - 100) / 20; - + const interfaceScale = InterfaceScale.ZoomLevel.fromPercentage(percentage); this.setState({ interfaceScale }); };