diff --git a/src/vs/base/common/keyCodes.ts b/src/vs/base/common/keyCodes.ts index 7e3de3f322b0732a3e1e7725f452b59f5b319c7d..3898558935491cb07f971cc82b74d0fbbae2fe46 100644 --- a/src/vs/base/common/keyCodes.ts +++ b/src/vs/base/common/keyCodes.ts @@ -5,6 +5,7 @@ import { OperatingSystem } from 'vs/base/common/platform'; import { illegalArgument } from 'vs/base/common/errors'; +import { Modifiers, UILabelProvider, AriaLabelProvider, ElectronAcceleratorLabelProvider, UserSettingsLabelProvider } from 'vs/base/common/keybindingLabels'; /** * Virtual Key Codes, the value does not hold any inherent meaning. @@ -589,13 +590,83 @@ export abstract class ResolvedKeybinding { */ public abstract isChord(): boolean; - /** - * Returns the parts that should be used for dispatching. - */ - public abstract getDispatchParts(): (string | null)[]; /** * Returns the parts that comprise of the keybinding. * Simple keybindings return one element. */ public abstract getParts(): ResolvedKeybindingPart[]; + + /** + * Returns the parts that should be used for dispatching. + */ + public abstract getDispatchParts(): (string | null)[]; +} + +export abstract class BaseResolvedKeybinding extends ResolvedKeybinding { + + protected readonly _os: OperatingSystem; + protected readonly _parts: T[]; + + constructor(os: OperatingSystem, parts: T[]) { + super(); + if (parts.length === 0) { + throw illegalArgument(`parts`); + } + this._os = os; + this._parts = parts; + } + + public getLabel(): string | null { + return UILabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getLabel(keybinding)); + } + + public getAriaLabel(): string | null { + return AriaLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getAriaLabel(keybinding)); + } + + public getElectronAccelerator(): string | null { + if (this._parts.length > 1) { + // Electron cannot handle chords + return null; + } + return ElectronAcceleratorLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getElectronAccelerator(keybinding)); + } + + public getUserSettingsLabel(): string | null { + return UserSettingsLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getUserSettingsLabel(keybinding)); + } + + public isWYSIWYG(): boolean { + return this._parts.every((keybinding) => this._isWYSIWYG(keybinding)); + } + + public isChord(): boolean { + return (this._parts.length > 1); + } + + public getParts(): ResolvedKeybindingPart[] { + return this._parts.map((keybinding) => this._getPart(keybinding)); + } + + private _getPart(keybinding: T): ResolvedKeybindingPart { + return new ResolvedKeybindingPart( + keybinding.ctrlKey, + keybinding.shiftKey, + keybinding.altKey, + keybinding.metaKey, + this._getLabel(keybinding), + this._getAriaLabel(keybinding) + ); + } + + public getDispatchParts(): (string | null)[] { + return this._parts.map((keybinding) => this._getDispatchPart(keybinding)); + } + + protected abstract _getLabel(keybinding: T): string | null; + protected abstract _getAriaLabel(keybinding: T): string | null; + protected abstract _getElectronAccelerator(keybinding: T): string | null; + protected abstract _getUserSettingsLabel(keybinding: T): string | null; + protected abstract _isWYSIWYG(keybinding: T): boolean; + protected abstract _getDispatchPart(keybinding: T): string | null; } diff --git a/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts b/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts index a2793f9c114047ee88fe3ce9d7d5738a0b57a221..fb6c328c8813a6e5e1ab58c99cb606fbcd9888e7 100644 --- a/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts +++ b/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts @@ -3,26 +3,16 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { KeyCode, KeyCodeUtils, Keybinding, ResolvedKeybinding, ResolvedKeybindingPart, SimpleKeybinding } from 'vs/base/common/keyCodes'; -import { AriaLabelProvider, ElectronAcceleratorLabelProvider, UILabelProvider, UserSettingsLabelProvider } from 'vs/base/common/keybindingLabels'; +import { KeyCode, KeyCodeUtils, Keybinding, SimpleKeybinding, BaseResolvedKeybinding } from 'vs/base/common/keyCodes'; import { OperatingSystem } from 'vs/base/common/platform'; /** * Do not instantiate. Use KeybindingService to get a ResolvedKeybinding seeded with information about the current kb layout. */ -export class USLayoutResolvedKeybinding extends ResolvedKeybinding { - - private readonly _os: OperatingSystem; - private readonly _parts: SimpleKeybinding[]; - - constructor(actual: Keybinding, OS: OperatingSystem) { - super(); - this._os = OS; - if (!actual) { - throw new Error(`Invalid USLayoutResolvedKeybinding`); - } else { - this._parts = actual.parts; - } +export class USLayoutResolvedKeybinding extends BaseResolvedKeybinding { + + constructor(actual: Keybinding, os: OperatingSystem) { + super(os, actual.parts); } private _keyCodeToUILabel(keyCode: KeyCode): string { @@ -41,34 +31,20 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding { return KeyCodeUtils.toString(keyCode); } - private _getUILabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { - if (!keybinding) { - return null; - } + protected _getLabel(keybinding: SimpleKeybinding): string | null { if (keybinding.isDuplicateModifierCase()) { return ''; } return this._keyCodeToUILabel(keybinding.keyCode); } - public getLabel(): string | null { - return UILabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getUILabelForKeybinding(keybinding)); - } - - private _getAriaLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { - if (!keybinding) { - return null; - } + protected _getAriaLabel(keybinding: SimpleKeybinding): string | null { if (keybinding.isDuplicateModifierCase()) { return ''; } return KeyCodeUtils.toString(keybinding.keyCode); } - public getAriaLabel(): string | null { - return AriaLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getAriaLabelForKeybinding(keybinding)); - } - private _keyCodeToElectronAccelerator(keyCode: KeyCode): string | null { if (keyCode >= KeyCode.NUMPAD_0 && keyCode <= KeyCode.NUMPAD_DIVIDE) { // Electron cannot handle numpad keys @@ -89,65 +65,27 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding { return KeyCodeUtils.toString(keyCode); } - private _getElectronAcceleratorLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { - if (!keybinding) { - return null; - } + protected _getElectronAccelerator(keybinding: SimpleKeybinding): string | null { if (keybinding.isDuplicateModifierCase()) { return null; } return this._keyCodeToElectronAccelerator(keybinding.keyCode); } - public getElectronAccelerator(): string | null { - if (this._parts.length > 1) { - // Electron cannot handle chords - return null; - } - - return ElectronAcceleratorLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getElectronAcceleratorLabelForKeybinding(keybinding)); - } - - private _getUserSettingsLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { - if (!keybinding) { - return null; - } + protected _getUserSettingsLabel(keybinding: SimpleKeybinding): string | null { if (keybinding.isDuplicateModifierCase()) { return ''; } - return KeyCodeUtils.toUserSettingsUS(keybinding.keyCode); - } - - public getUserSettingsLabel(): string | null { - const result = UserSettingsLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getUserSettingsLabelForKeybinding(keybinding)); + const result = KeyCodeUtils.toUserSettingsUS(keybinding.keyCode); return (result ? result.toLowerCase() : result); } - public isWYSIWYG(): boolean { + protected _isWYSIWYG(): boolean { return true; } - public isChord(): boolean { - return (this._parts.length > 1); - } - - public getParts(): ResolvedKeybindingPart[] { - return this._parts.map((keybinding) => this._toResolvedKeybindingPart(keybinding)); - } - - private _toResolvedKeybindingPart(keybinding: SimpleKeybinding): ResolvedKeybindingPart { - return new ResolvedKeybindingPart( - keybinding.ctrlKey, - keybinding.shiftKey, - keybinding.altKey, - keybinding.metaKey, - this._getUILabelForKeybinding(keybinding), - this._getAriaLabelForKeybinding(keybinding) - ); - } - - public getDispatchParts(): (string | null)[] { - return this._parts.map((keybinding) => USLayoutResolvedKeybinding.getDispatchStr(keybinding)); + protected _getDispatchPart(keybinding: SimpleKeybinding): string | null { + return USLayoutResolvedKeybinding.getDispatchStr(keybinding); } public static getDispatchStr(keybinding: SimpleKeybinding): string | null { diff --git a/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts b/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts index ef250891cd98360b0e4a8324b0b75cc3ab6914ed..37afe210ef79dbb84858b51ce569657615af0909 100644 --- a/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts +++ b/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts @@ -4,8 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { CharCode } from 'vs/base/common/charCode'; -import { KeyCode, KeyCodeUtils, Keybinding, ResolvedKeybinding, ResolvedKeybindingPart, SimpleKeybinding } from 'vs/base/common/keyCodes'; -import { AriaLabelProvider, ElectronAcceleratorLabelProvider, UILabelProvider, UserSettingsLabelProvider } from 'vs/base/common/keybindingLabels'; +import { KeyCode, KeyCodeUtils, Keybinding, ResolvedKeybinding, SimpleKeybinding, BaseResolvedKeybinding } from 'vs/base/common/keyCodes'; import { OperatingSystem } from 'vs/base/common/platform'; import { IMMUTABLE_CODE_TO_KEY_CODE, IMMUTABLE_KEY_CODE_TO_CODE, ScanCode, ScanCodeBinding, ScanCodeUtils } from 'vs/base/common/scanCode'; import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding'; @@ -63,44 +62,32 @@ export function macLinuxKeyboardMappingEquals(a: IMacLinuxKeyboardMapping | null */ const CHAR_CODE_TO_KEY_CODE: ({ keyCode: KeyCode; shiftKey: boolean } | null)[] = []; -export class NativeResolvedKeybinding extends ResolvedKeybinding { +export class NativeResolvedKeybinding extends BaseResolvedKeybinding { private readonly _mapper: MacLinuxKeyboardMapper; - private readonly _OS: OperatingSystem; - private readonly _parts: ScanCodeBinding[]; - constructor(mapper: MacLinuxKeyboardMapper, OS: OperatingSystem, parts: ScanCodeBinding[]) { - super(); - if (parts.length === 0) { - throw new Error(`Invalid NativeResolvedKeybinding`); - } + constructor(mapper: MacLinuxKeyboardMapper, os: OperatingSystem, parts: ScanCodeBinding[]) { + super(os, parts); this._mapper = mapper; - this._OS = OS; - this._parts = parts; } - public getLabel(): string | null { - return UILabelProvider.toLabel(this._OS, this._parts, (keybinding) => this._mapper.getUILabelForScanCodeBinding(keybinding)); + protected _getLabel(keybinding: ScanCodeBinding): string | null { + return this._mapper.getUILabelForScanCodeBinding(keybinding); } - public getAriaLabel(): string | null { - return AriaLabelProvider.toLabel(this._OS, this._parts, (keybinding) => this._mapper.getAriaLabelForScanCodeBinding(keybinding)); + protected _getAriaLabel(keybinding: ScanCodeBinding): string | null { + return this._mapper.getAriaLabelForScanCodeBinding(keybinding); } - public getElectronAccelerator(): string | null { - if (this._parts.length > 1) { - // Electron cannot handle chords - return null; - } - - return ElectronAcceleratorLabelProvider.toLabel(this._OS, this._parts, (keybinding) => this._mapper.getElectronAcceleratorLabelForScanCodeBinding(keybinding)); + protected _getElectronAccelerator(keybinding: ScanCodeBinding): string | null { + return this._mapper.getElectronAcceleratorLabelForScanCodeBinding(keybinding); } - public getUserSettingsLabel(): string | null { - return UserSettingsLabelProvider.toLabel(this._OS, this._parts, (keybinding) => this._mapper.getUserSettingsLabelForScanCodeBinding(keybinding)); + protected _getUserSettingsLabel(keybinding: ScanCodeBinding): string | null { + return this._mapper.getUserSettingsLabelForScanCodeBinding(keybinding); } - private _isWYSIWYG(binding: ScanCodeBinding | null): boolean { + protected _isWYSIWYG(binding: ScanCodeBinding | null): boolean { if (!binding) { return true; } @@ -119,31 +106,8 @@ export class NativeResolvedKeybinding extends ResolvedKeybinding { return (a.toLowerCase() === b.toLowerCase()); } - public isWYSIWYG(): boolean { - return this._parts.every((keybinding) => this._isWYSIWYG(keybinding)); - } - - public isChord(): boolean { - return (this._parts.length > 1); - } - - public getParts(): ResolvedKeybindingPart[] { - return this._parts.map((keybinding) => this._toResolvedKeybindingPart(keybinding)); - } - - private _toResolvedKeybindingPart(binding: ScanCodeBinding): ResolvedKeybindingPart { - return new ResolvedKeybindingPart( - binding.ctrlKey, - binding.shiftKey, - binding.altKey, - binding.metaKey, - this._mapper.getUILabelForScanCodeBinding(binding), - this._mapper.getAriaLabelForScanCodeBinding(binding) - ); - } - - public getDispatchParts(): (string | null)[] { - return this._parts.map((keybinding) => this._mapper.getDispatchStrForScanCodeBinding(keybinding)); + protected _getDispatchPart(keybinding: ScanCodeBinding): string | null { + return this._mapper.getDispatchStrForScanCodeBinding(keybinding); } } diff --git a/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts b/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts index 395d2bb6403710a72da7bbc8de13d08c8848bebd..38d534fcebb23391e95e029fff30c73512ec0d8b 100644 --- a/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts +++ b/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { CharCode } from 'vs/base/common/charCode'; -import { KeyCode, KeyCodeUtils, Keybinding, ResolvedKeybinding, ResolvedKeybindingPart, SimpleKeybinding } from 'vs/base/common/keyCodes'; -import { AriaLabelProvider, ElectronAcceleratorLabelProvider, UILabelProvider, UserSettingsLabelProvider } from 'vs/base/common/keybindingLabels'; +import { KeyCode, KeyCodeUtils, Keybinding, ResolvedKeybinding, SimpleKeybinding, BaseResolvedKeybinding } from 'vs/base/common/keyCodes'; +import { UILabelProvider } from 'vs/base/common/keybindingLabels'; import { OperatingSystem } from 'vs/base/common/platform'; import { IMMUTABLE_CODE_TO_KEY_CODE, ScanCode, ScanCodeBinding, ScanCodeUtils } from 'vs/base/common/scanCode'; import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding'; @@ -76,38 +76,23 @@ export interface IScanCodeMapping { withShiftAltGr: string; } -export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { +export class WindowsNativeResolvedKeybinding extends BaseResolvedKeybinding { private readonly _mapper: WindowsKeyboardMapper; - private readonly _parts: SimpleKeybinding[]; constructor(mapper: WindowsKeyboardMapper, parts: SimpleKeybinding[]) { - super(); - if (parts.length === 0) { - throw new Error(`Invalid WindowsNativeResolvedKeybinding`); - } + super(OperatingSystem.Windows, parts); this._mapper = mapper; - this._parts = parts; } - private _getUILabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { - if (!keybinding) { - return null; - } + protected _getLabel(keybinding: SimpleKeybinding): string | null { if (keybinding.isDuplicateModifierCase()) { return ''; } return this._mapper.getUILabelForKeyCode(keybinding.keyCode); } - public getLabel(): string | null { - return UILabelProvider.toLabel(OperatingSystem.Windows, this._parts, (keybinding) => this._getUILabelForKeybinding(keybinding)); - } - - private _getUSLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { - if (!keybinding) { - return null; - } + private _getUSLabelForKeybinding(keybinding: SimpleKeybinding): string | null { if (keybinding.isDuplicateModifierCase()) { return ''; } @@ -115,23 +100,16 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { } public getUSLabel(): string | null { - return UILabelProvider.toLabel(OperatingSystem.Windows, this._parts, (keybinding) => this._getUSLabelForKeybinding(keybinding)); + return UILabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getUSLabelForKeybinding(keybinding)); } - private _getAriaLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { - if (!keybinding) { - return null; - } + protected _getAriaLabel(keybinding: SimpleKeybinding): string | null { if (keybinding.isDuplicateModifierCase()) { return ''; } return this._mapper.getAriaLabelForKeyCode(keybinding.keyCode); } - public getAriaLabel(): string | null { - return AriaLabelProvider.toLabel(OperatingSystem.Windows, this._parts, (keybinding) => this._getAriaLabelForKeybinding(keybinding)); - } - private _keyCodeToElectronAccelerator(keyCode: KeyCode): string | null { if (keyCode >= KeyCode.NUMPAD_0 && keyCode <= KeyCode.NUMPAD_DIVIDE) { // Electron cannot handle numpad keys @@ -153,45 +131,26 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { return KeyCodeUtils.toString(keyCode); } - private _getElectronAcceleratorLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { - if (!keybinding) { - return null; - } + protected _getElectronAccelerator(keybinding: SimpleKeybinding): string | null { if (keybinding.isDuplicateModifierCase()) { return null; } return this._keyCodeToElectronAccelerator(keybinding.keyCode); } - public getElectronAccelerator(): string | null { - if (this._parts.length > 1) { - // Electron cannot handle chords - return null; - } - - return ElectronAcceleratorLabelProvider.toLabel(OperatingSystem.Windows, this._parts, (keybinding) => this._getElectronAcceleratorLabelForKeybinding(keybinding)); - } - - private _getUserSettingsLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { - if (!keybinding) { - return null; - } + protected _getUserSettingsLabel(keybinding: SimpleKeybinding): string | null { if (keybinding.isDuplicateModifierCase()) { return ''; } - return this._mapper.getUserSettingsLabelForKeyCode(keybinding.keyCode); - } - - public getUserSettingsLabel(): string | null { - const result = UserSettingsLabelProvider.toLabel(OperatingSystem.Windows, this._parts, (keybinding) => this._getUserSettingsLabelForKeybinding(keybinding)); + const result = this._mapper.getUserSettingsLabelForKeyCode(keybinding.keyCode); return (result ? result.toLowerCase() : result); } - public isWYSIWYG(): boolean { - return this._parts.every((keybinding) => this._isWYSIWYG(keybinding.keyCode)); + protected _isWYSIWYG(keybinding: SimpleKeybinding): boolean { + return this.__isWYSIWYG(keybinding.keyCode); } - private _isWYSIWYG(keyCode: KeyCode): boolean { + private __isWYSIWYG(keyCode: KeyCode): boolean { if ( keyCode === KeyCode.LeftArrow || keyCode === KeyCode.UpArrow @@ -205,30 +164,7 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { return (ariaLabel === userSettingsLabel); } - public isChord(): boolean { - return (this._parts.length > 1); - } - - public getParts(): ResolvedKeybindingPart[] { - return this._parts.map((keybinding) => this._toResolvedKeybindingPart(keybinding)); - } - - private _toResolvedKeybindingPart(keybinding: SimpleKeybinding): ResolvedKeybindingPart { - return new ResolvedKeybindingPart( - keybinding.ctrlKey, - keybinding.shiftKey, - keybinding.altKey, - keybinding.metaKey, - this._getUILabelForKeybinding(keybinding), - this._getAriaLabelForKeybinding(keybinding) - ); - } - - public getDispatchParts(): (string | null)[] { - return this._parts.map((keybinding) => this._getDispatchStr(keybinding)); - } - - private _getDispatchStr(keybinding: SimpleKeybinding): string | null { + protected _getDispatchPart(keybinding: SimpleKeybinding): string | null { if (keybinding.isModifierKey()) { return null; }