Skip to content

Commit ad209fb

Browse files
committed
Introduce BaseResolvedKeybinding
1 parent 871a6fe commit ad209fb

4 files changed

Lines changed: 118 additions & 209 deletions

File tree

src/vs/base/common/keyCodes.ts

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import { OperatingSystem } from 'vs/base/common/platform';
77
import { illegalArgument } from 'vs/base/common/errors';
8+
import { Modifiers, UILabelProvider, AriaLabelProvider, ElectronAcceleratorLabelProvider, UserSettingsLabelProvider } from 'vs/base/common/keybindingLabels';
89

910
/**
1011
* Virtual Key Codes, the value does not hold any inherent meaning.
@@ -589,13 +590,83 @@ export abstract class ResolvedKeybinding {
589590
*/
590591
public abstract isChord(): boolean;
591592

592-
/**
593-
* Returns the parts that should be used for dispatching.
594-
*/
595-
public abstract getDispatchParts(): (string | null)[];
596593
/**
597594
* Returns the parts that comprise of the keybinding.
598595
* Simple keybindings return one element.
599596
*/
600597
public abstract getParts(): ResolvedKeybindingPart[];
598+
599+
/**
600+
* Returns the parts that should be used for dispatching.
601+
*/
602+
public abstract getDispatchParts(): (string | null)[];
603+
}
604+
605+
export abstract class BaseResolvedKeybinding<T extends Modifiers> extends ResolvedKeybinding {
606+
607+
protected readonly _os: OperatingSystem;
608+
protected readonly _parts: T[];
609+
610+
constructor(os: OperatingSystem, parts: T[]) {
611+
super();
612+
if (parts.length === 0) {
613+
throw illegalArgument(`parts`);
614+
}
615+
this._os = os;
616+
this._parts = parts;
617+
}
618+
619+
public getLabel(): string | null {
620+
return UILabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getLabel(keybinding));
621+
}
622+
623+
public getAriaLabel(): string | null {
624+
return AriaLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getAriaLabel(keybinding));
625+
}
626+
627+
public getElectronAccelerator(): string | null {
628+
if (this._parts.length > 1) {
629+
// Electron cannot handle chords
630+
return null;
631+
}
632+
return ElectronAcceleratorLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getElectronAccelerator(keybinding));
633+
}
634+
635+
public getUserSettingsLabel(): string | null {
636+
return UserSettingsLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getUserSettingsLabel(keybinding));
637+
}
638+
639+
public isWYSIWYG(): boolean {
640+
return this._parts.every((keybinding) => this._isWYSIWYG(keybinding));
641+
}
642+
643+
public isChord(): boolean {
644+
return (this._parts.length > 1);
645+
}
646+
647+
public getParts(): ResolvedKeybindingPart[] {
648+
return this._parts.map((keybinding) => this._getPart(keybinding));
649+
}
650+
651+
private _getPart(keybinding: T): ResolvedKeybindingPart {
652+
return new ResolvedKeybindingPart(
653+
keybinding.ctrlKey,
654+
keybinding.shiftKey,
655+
keybinding.altKey,
656+
keybinding.metaKey,
657+
this._getLabel(keybinding),
658+
this._getAriaLabel(keybinding)
659+
);
660+
}
661+
662+
public getDispatchParts(): (string | null)[] {
663+
return this._parts.map((keybinding) => this._getDispatchPart(keybinding));
664+
}
665+
666+
protected abstract _getLabel(keybinding: T): string | null;
667+
protected abstract _getAriaLabel(keybinding: T): string | null;
668+
protected abstract _getElectronAccelerator(keybinding: T): string | null;
669+
protected abstract _getUserSettingsLabel(keybinding: T): string | null;
670+
protected abstract _isWYSIWYG(keybinding: T): boolean;
671+
protected abstract _getDispatchPart(keybinding: T): string | null;
601672
}

src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts

Lines changed: 13 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,16 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { KeyCode, KeyCodeUtils, Keybinding, ResolvedKeybinding, ResolvedKeybindingPart, SimpleKeybinding } from 'vs/base/common/keyCodes';
7-
import { AriaLabelProvider, ElectronAcceleratorLabelProvider, UILabelProvider, UserSettingsLabelProvider } from 'vs/base/common/keybindingLabels';
6+
import { KeyCode, KeyCodeUtils, Keybinding, SimpleKeybinding, BaseResolvedKeybinding } from 'vs/base/common/keyCodes';
87
import { OperatingSystem } from 'vs/base/common/platform';
98

109
/**
1110
* Do not instantiate. Use KeybindingService to get a ResolvedKeybinding seeded with information about the current kb layout.
1211
*/
13-
export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
14-
15-
private readonly _os: OperatingSystem;
16-
private readonly _parts: SimpleKeybinding[];
17-
18-
constructor(actual: Keybinding, OS: OperatingSystem) {
19-
super();
20-
this._os = OS;
21-
if (!actual) {
22-
throw new Error(`Invalid USLayoutResolvedKeybinding`);
23-
} else {
24-
this._parts = actual.parts;
25-
}
12+
export class USLayoutResolvedKeybinding extends BaseResolvedKeybinding<SimpleKeybinding> {
13+
14+
constructor(actual: Keybinding, os: OperatingSystem) {
15+
super(os, actual.parts);
2616
}
2717

2818
private _keyCodeToUILabel(keyCode: KeyCode): string {
@@ -41,34 +31,20 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
4131
return KeyCodeUtils.toString(keyCode);
4232
}
4333

44-
private _getUILabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
45-
if (!keybinding) {
46-
return null;
47-
}
34+
protected _getLabel(keybinding: SimpleKeybinding): string | null {
4835
if (keybinding.isDuplicateModifierCase()) {
4936
return '';
5037
}
5138
return this._keyCodeToUILabel(keybinding.keyCode);
5239
}
5340

54-
public getLabel(): string | null {
55-
return UILabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getUILabelForKeybinding(keybinding));
56-
}
57-
58-
private _getAriaLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
59-
if (!keybinding) {
60-
return null;
61-
}
41+
protected _getAriaLabel(keybinding: SimpleKeybinding): string | null {
6242
if (keybinding.isDuplicateModifierCase()) {
6343
return '';
6444
}
6545
return KeyCodeUtils.toString(keybinding.keyCode);
6646
}
6747

68-
public getAriaLabel(): string | null {
69-
return AriaLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getAriaLabelForKeybinding(keybinding));
70-
}
71-
7248
private _keyCodeToElectronAccelerator(keyCode: KeyCode): string | null {
7349
if (keyCode >= KeyCode.NUMPAD_0 && keyCode <= KeyCode.NUMPAD_DIVIDE) {
7450
// Electron cannot handle numpad keys
@@ -89,65 +65,27 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
8965
return KeyCodeUtils.toString(keyCode);
9066
}
9167

92-
private _getElectronAcceleratorLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
93-
if (!keybinding) {
94-
return null;
95-
}
68+
protected _getElectronAccelerator(keybinding: SimpleKeybinding): string | null {
9669
if (keybinding.isDuplicateModifierCase()) {
9770
return null;
9871
}
9972
return this._keyCodeToElectronAccelerator(keybinding.keyCode);
10073
}
10174

102-
public getElectronAccelerator(): string | null {
103-
if (this._parts.length > 1) {
104-
// Electron cannot handle chords
105-
return null;
106-
}
107-
108-
return ElectronAcceleratorLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getElectronAcceleratorLabelForKeybinding(keybinding));
109-
}
110-
111-
private _getUserSettingsLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
112-
if (!keybinding) {
113-
return null;
114-
}
75+
protected _getUserSettingsLabel(keybinding: SimpleKeybinding): string | null {
11576
if (keybinding.isDuplicateModifierCase()) {
11677
return '';
11778
}
118-
return KeyCodeUtils.toUserSettingsUS(keybinding.keyCode);
119-
}
120-
121-
public getUserSettingsLabel(): string | null {
122-
const result = UserSettingsLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getUserSettingsLabelForKeybinding(keybinding));
79+
const result = KeyCodeUtils.toUserSettingsUS(keybinding.keyCode);
12380
return (result ? result.toLowerCase() : result);
12481
}
12582

126-
public isWYSIWYG(): boolean {
83+
protected _isWYSIWYG(): boolean {
12784
return true;
12885
}
12986

130-
public isChord(): boolean {
131-
return (this._parts.length > 1);
132-
}
133-
134-
public getParts(): ResolvedKeybindingPart[] {
135-
return this._parts.map((keybinding) => this._toResolvedKeybindingPart(keybinding));
136-
}
137-
138-
private _toResolvedKeybindingPart(keybinding: SimpleKeybinding): ResolvedKeybindingPart {
139-
return new ResolvedKeybindingPart(
140-
keybinding.ctrlKey,
141-
keybinding.shiftKey,
142-
keybinding.altKey,
143-
keybinding.metaKey,
144-
this._getUILabelForKeybinding(keybinding),
145-
this._getAriaLabelForKeybinding(keybinding)
146-
);
147-
}
148-
149-
public getDispatchParts(): (string | null)[] {
150-
return this._parts.map((keybinding) => USLayoutResolvedKeybinding.getDispatchStr(keybinding));
87+
protected _getDispatchPart(keybinding: SimpleKeybinding): string | null {
88+
return USLayoutResolvedKeybinding.getDispatchStr(keybinding);
15189
}
15290

15391
public static getDispatchStr(keybinding: SimpleKeybinding): string | null {

src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts

Lines changed: 15 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { CharCode } from 'vs/base/common/charCode';
7-
import { KeyCode, KeyCodeUtils, Keybinding, ResolvedKeybinding, ResolvedKeybindingPart, SimpleKeybinding } from 'vs/base/common/keyCodes';
8-
import { AriaLabelProvider, ElectronAcceleratorLabelProvider, UILabelProvider, UserSettingsLabelProvider } from 'vs/base/common/keybindingLabels';
7+
import { KeyCode, KeyCodeUtils, Keybinding, ResolvedKeybinding, SimpleKeybinding, BaseResolvedKeybinding } from 'vs/base/common/keyCodes';
98
import { OperatingSystem } from 'vs/base/common/platform';
109
import { IMMUTABLE_CODE_TO_KEY_CODE, IMMUTABLE_KEY_CODE_TO_CODE, ScanCode, ScanCodeBinding, ScanCodeUtils } from 'vs/base/common/scanCode';
1110
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
@@ -63,44 +62,32 @@ export function macLinuxKeyboardMappingEquals(a: IMacLinuxKeyboardMapping | null
6362
*/
6463
const CHAR_CODE_TO_KEY_CODE: ({ keyCode: KeyCode; shiftKey: boolean } | null)[] = [];
6564

66-
export class NativeResolvedKeybinding extends ResolvedKeybinding {
65+
export class NativeResolvedKeybinding extends BaseResolvedKeybinding<ScanCodeBinding> {
6766

6867
private readonly _mapper: MacLinuxKeyboardMapper;
69-
private readonly _OS: OperatingSystem;
70-
private readonly _parts: ScanCodeBinding[];
7168

72-
constructor(mapper: MacLinuxKeyboardMapper, OS: OperatingSystem, parts: ScanCodeBinding[]) {
73-
super();
74-
if (parts.length === 0) {
75-
throw new Error(`Invalid NativeResolvedKeybinding`);
76-
}
69+
constructor(mapper: MacLinuxKeyboardMapper, os: OperatingSystem, parts: ScanCodeBinding[]) {
70+
super(os, parts);
7771
this._mapper = mapper;
78-
this._OS = OS;
79-
this._parts = parts;
8072
}
8173

82-
public getLabel(): string | null {
83-
return UILabelProvider.toLabel(this._OS, this._parts, (keybinding) => this._mapper.getUILabelForScanCodeBinding(keybinding));
74+
protected _getLabel(keybinding: ScanCodeBinding): string | null {
75+
return this._mapper.getUILabelForScanCodeBinding(keybinding);
8476
}
8577

86-
public getAriaLabel(): string | null {
87-
return AriaLabelProvider.toLabel(this._OS, this._parts, (keybinding) => this._mapper.getAriaLabelForScanCodeBinding(keybinding));
78+
protected _getAriaLabel(keybinding: ScanCodeBinding): string | null {
79+
return this._mapper.getAriaLabelForScanCodeBinding(keybinding);
8880
}
8981

90-
public getElectronAccelerator(): string | null {
91-
if (this._parts.length > 1) {
92-
// Electron cannot handle chords
93-
return null;
94-
}
95-
96-
return ElectronAcceleratorLabelProvider.toLabel(this._OS, this._parts, (keybinding) => this._mapper.getElectronAcceleratorLabelForScanCodeBinding(keybinding));
82+
protected _getElectronAccelerator(keybinding: ScanCodeBinding): string | null {
83+
return this._mapper.getElectronAcceleratorLabelForScanCodeBinding(keybinding);
9784
}
9885

99-
public getUserSettingsLabel(): string | null {
100-
return UserSettingsLabelProvider.toLabel(this._OS, this._parts, (keybinding) => this._mapper.getUserSettingsLabelForScanCodeBinding(keybinding));
86+
protected _getUserSettingsLabel(keybinding: ScanCodeBinding): string | null {
87+
return this._mapper.getUserSettingsLabelForScanCodeBinding(keybinding);
10188
}
10289

103-
private _isWYSIWYG(binding: ScanCodeBinding | null): boolean {
90+
protected _isWYSIWYG(binding: ScanCodeBinding | null): boolean {
10491
if (!binding) {
10592
return true;
10693
}
@@ -119,31 +106,8 @@ export class NativeResolvedKeybinding extends ResolvedKeybinding {
119106
return (a.toLowerCase() === b.toLowerCase());
120107
}
121108

122-
public isWYSIWYG(): boolean {
123-
return this._parts.every((keybinding) => this._isWYSIWYG(keybinding));
124-
}
125-
126-
public isChord(): boolean {
127-
return (this._parts.length > 1);
128-
}
129-
130-
public getParts(): ResolvedKeybindingPart[] {
131-
return this._parts.map((keybinding) => this._toResolvedKeybindingPart(keybinding));
132-
}
133-
134-
private _toResolvedKeybindingPart(binding: ScanCodeBinding): ResolvedKeybindingPart {
135-
return new ResolvedKeybindingPart(
136-
binding.ctrlKey,
137-
binding.shiftKey,
138-
binding.altKey,
139-
binding.metaKey,
140-
this._mapper.getUILabelForScanCodeBinding(binding),
141-
this._mapper.getAriaLabelForScanCodeBinding(binding)
142-
);
143-
}
144-
145-
public getDispatchParts(): (string | null)[] {
146-
return this._parts.map((keybinding) => this._mapper.getDispatchStrForScanCodeBinding(keybinding));
109+
protected _getDispatchPart(keybinding: ScanCodeBinding): string | null {
110+
return this._mapper.getDispatchStrForScanCodeBinding(keybinding);
147111
}
148112
}
149113

0 commit comments

Comments
 (0)