提交 8f5b2f5d 编写于 作者: S Sandeep Somavarapu

#18095 Keybindings editor

- Define keybinding action with keyboard shortcut
- Search keybindings action with keyboard shortcut
上级 8ca2c28a
......@@ -17,10 +17,10 @@ import { EditorInput } from 'vs/workbench/common/editor';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { KeybindingsEditorModel, IKeybindingItemEntry, IKeybindingItem, IListEntry, KEYBINDING_ENTRY_TEMPLATE_ID, KEYBINDING_HEADER_TEMPLATE_ID } from 'vs/workbench/parts/preferences/common/keybindingsEditorModel';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService, IKeybindingItem2, KeybindingSource } from 'vs/platform/keybinding/common/keybinding';
import { IKeybindingService, KeybindingSource } from 'vs/platform/keybinding/common/keybinding';
import { SearchWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
import { DefineKeybindingWidget } from 'vs/workbench/parts/preferences/browser/keybindingWidgets';
import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences';
import { IPreferencesService, IKeybindingsEditor, CONTEXT_KEYBINDING_FOCUS, KEYBINDINGS_EDITOR_ID, CONTEXT_KEYBINDINGS_EDITOR } from 'vs/workbench/parts/preferences/common/preferences';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { renderHtml } from 'vs/base/browser/htmlContentRenderer';
import { IKeybindingEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing';
......@@ -28,15 +28,10 @@ import { IListService } from 'vs/platform/list/browser/listService';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { IDelegate, IRenderer, IListContextMenuEvent, IListEvent } from 'vs/base/browser/ui/list/list';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
let $ = DOM.$;
export interface IKeybindingsEditor {
defineKeybinding(keybindingItem: IKeybindingItem);
}
export class KeybindingsEditorInput extends EditorInput {
public static ID: string = 'worknench.input.keybindings';
......@@ -66,17 +61,21 @@ export class KeybindingsEditorInput extends EditorInput {
export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor {
public static ID: string = 'workbench.editor.keybindings';
public static ID: string = KEYBINDINGS_EDITOR_ID;
private headerContainer: HTMLElement;
private searchWidget: SearchWidget;
private defineKeybindingWidget: DefineKeybindingWidget;
private overlayContainer: HTMLElement;
private headerContainer: HTMLElement;
private dimension: Dimension;
private defineKeybindingWidget: DefineKeybindingWidget;
private delayedFiltering: Delayer<void>;
private keybindingsListContainer: HTMLElement;
private keybindingsList: List<IListEntry>;
private dimension: Dimension;
private delayedFiltering: Delayer<void>;
private keybindingsEditorContextKey: IContextKey<boolean>;
private keybindingFocusContextKey: IContextKey<boolean>;
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IThemeService themeService: IThemeService,
......@@ -85,11 +84,15 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
@IPreferencesService private preferencesService: IPreferencesService,
@IKeybindingEditingService private keybindingEditingService: IKeybindingEditingService,
@IListService private listService: IListService,
@IContextKeyService private contextKeyService: IContextKeyService,
@IInstantiationService private instantiationService: IInstantiationService
) {
super(KeybindingsEditor.ID, telemetryService, themeService);
this.delayedFiltering = new Delayer<void>(300);
this._register(keybindingsService.onDidUpdateKeybindings(() => this.render()));
this.keybindingsEditorContextKey = CONTEXT_KEYBINDINGS_EDITOR.bindTo(this.contextKeyService);
this.keybindingFocusContextKey = CONTEXT_KEYBINDING_FOCUS.bindTo(this.contextKeyService);
}
createEditor(parent: Builder): void {
......@@ -100,6 +103,10 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
this.createOverlayContainer(keybindingsEditorElement);
this.createHeader(keybindingsEditorElement);
this.createBody(keybindingsEditorElement);
const focusTracker = this._register(DOM.trackFocus(parentElement));
this._register(focusTracker.addFocusListener(() => this.keybindingsEditorContextKey.set(true)));
this._register(focusTracker.addBlurListener(() => this.keybindingsEditorContextKey.reset()));
}
setInput(input: KeybindingsEditorInput): TPromise<void> {
......@@ -115,6 +122,8 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
clearInput(): void {
super.clearInput();
this.searchWidget.clear();
this.keybindingsEditorContextKey.reset();
this.keybindingFocusContextKey.reset();
}
layout(dimension: Dimension): void {
......@@ -134,6 +143,28 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
this.searchWidget.focus();
}
get activeKeybindingEntry(): IKeybindingItemEntry {
const focusedElement = this.keybindingsList.getFocusedElements()[0];
return focusedElement && focusedElement.templateId === KEYBINDING_ENTRY_TEMPLATE_ID ? <IKeybindingItemEntry>focusedElement : null;
}
defineKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise<any> {
this.overlayContainer.style.display = 'block';
return this.defineKeybindingWidget.define().then(key => {
if (key) {
return this.keybindingEditingService.editKeybinding(key, keybindingEntry.keybindingItem);
}
return null;
}).then(() => {
this.overlayContainer.style.display = 'none';
this.focus();
});
}
search(filter: string): void {
this.searchWidget.focus();
}
private createOverlayContainer(parent: HTMLElement): void {
this.overlayContainer = DOM.append(parent, $('.overlay-container'));
this.overlayContainer.style.position = 'absolute';
......@@ -163,12 +194,14 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
}
private createList(parent: HTMLElement): void {
const delegate = new Delegate();
this.keybindingsListContainer = DOM.append(parent, $('.keybindings-list-container'));
this.keybindingsList = this._register(new List<IListEntry>(this.keybindingsListContainer, delegate, [new KeybindingHeaderRenderer(), new KeybindingItemRenderer(this)], { identityProvider: e => e.id }));
this.keybindingsList = this._register(new List<IListEntry>(this.keybindingsListContainer, new Delegate(), [new KeybindingHeaderRenderer(), new KeybindingItemRenderer(this)], { identityProvider: e => e.id }));
this._register(this.keybindingsList.onContextMenu(e => this.onContextMenu(e)));
this._register(this.keybindingsList.onFocusChange(e => this.onFocusChange(e)));
this._register(this.keybindingsList.onDOMFocus(() => this.keybindingsList.focusNext()));
this._register(this.keybindingsList.onDOMBlur(() => this.keybindingFocusContextKey.reset()));
this._register(this.listService.register(this.keybindingsList));
}
......@@ -196,8 +229,17 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
}
private onFocusChange(e: IListEvent<IListEntry>): void {
if (e.elements[0] && e.elements[0].templateId === KEYBINDING_HEADER_TEMPLATE_ID) {
this.keybindingFocusContextKey.reset();
const element = e.elements[0];
if (!element) {
return;
}
if (element.templateId === KEYBINDING_HEADER_TEMPLATE_ID) {
this.keybindingsList.focusNext();
return;
}
if (element.templateId === KEYBINDING_ENTRY_TEMPLATE_ID) {
this.keybindingFocusContextKey.set(true);
}
}
......@@ -209,19 +251,6 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
run: () => this.keybindingEditingService.removeKeybinding(keybinding)
};
}
defineKeybinding(keybindingItem: IKeybindingItem2): void {
this.overlayContainer.style.display = 'block';
this.defineKeybindingWidget.define().then(key => {
this.overlayContainer.style.display = 'none';
if (key) {
this.keybindingEditingService.editKeybinding(key, keybindingItem);
}
}, () => {
this.overlayContainer.style.display = 'none';
this.focus();
});
}
}
class Delegate implements IDelegate<IListEntry> {
......@@ -327,30 +356,30 @@ class ActionsColumn extends Column {
this.actionBar.clear();
const actions = [];
if (keybindingItemEntry.keybindingItem.keybinding) {
actions.push(this.createEditAction(keybindingItemEntry.keybindingItem));
actions.push(this.createEditAction(keybindingItemEntry));
} else {
actions.push(this.createAddAction(keybindingItemEntry.keybindingItem));
actions.push(this.createAddAction(keybindingItemEntry));
}
this.actionBar.push(actions, { icon: true });
}
private createEditAction(keybinding: IKeybindingItem): IAction {
private createEditAction(keybindingItemEntry: IKeybindingItemEntry): IAction {
return <IAction>{
class: 'edit',
enabled: true,
id: 'editKeybinding',
tooltip: localize('change', "Change Keybinding"),
run: () => this.keybindingsEditor.defineKeybinding(keybinding)
run: () => this.keybindingsEditor.defineKeybinding(keybindingItemEntry)
};
}
private createAddAction(keybinding: IKeybindingItem): IAction {
private createAddAction(keybindingItemEntry: IKeybindingItemEntry): IAction {
return <IAction>{
class: 'add',
enabled: true,
id: 'addKeybinding',
tooltip: localize('add', "Add Keybinding"),
run: () => this.keybindingsEditor.defineKeybinding(keybinding)
run: () => this.keybindingsEditor.defineKeybinding(keybindingItemEntry)
};
}
}
......
......@@ -69,7 +69,7 @@
}
.keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list-row.keybindings-list-header,
.keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list-row.even {
.keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list-row.even:not(.focused) {
background-color: rgba(130, 130, 130, 0.04);
}
......
......@@ -16,12 +16,13 @@ import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { DefaultPreferencesEditorInput, PreferencesEditor, PreferencesEditorInput } from 'vs/workbench/parts/preferences/browser/preferencesEditor';
import { KeybindingsEditor, KeybindingsEditorInput } from 'vs/workbench/parts/preferences/browser/keybindingsEditor';
import { OpenGlobalSettingsAction, OpenGlobalKeybindingsAction, OpenWorkspaceSettingsAction, ConfigureLanguageBasedSettingsAction } from 'vs/workbench/parts/preferences/browser/preferencesActions';
import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences';
import { OpenGlobalSettingsAction, OpenGlobalKeybindingsAction, OpenWorkspaceSettingsAction, ConfigureLanguageBasedSettingsAction, DefineKeybindingAction, SearchKeybindingAction } from 'vs/workbench/parts/preferences/browser/preferencesActions';
import { IPreferencesService, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR } from 'vs/workbench/parts/preferences/common/preferences';
import { PreferencesService } from 'vs/workbench/parts/preferences/browser/preferencesService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { PreferencesContentProvider } from 'vs/workbench/parts/preferences/common/preferencesContentProvider';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
registerSingleton(IPreferencesService, PreferencesService);
......@@ -163,5 +164,10 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(OpenGlobalSettingsActi
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenWorkspaceSettingsAction, OpenWorkspaceSettingsAction.ID, OpenWorkspaceSettingsAction.LABEL), 'Preferences: Open Workspace Settings', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenGlobalKeybindingsAction, OpenGlobalKeybindingsAction.ID, OpenGlobalKeybindingsAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_S) }), 'Preferences: Open Keyboard Shortcuts', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureLanguageBasedSettingsAction, ConfigureLanguageBasedSettingsAction.ID, ConfigureLanguageBasedSettingsAction.LABEL), 'Preferences: Configure Language Specific Settings', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(SearchKeybindingAction, SearchKeybindingAction.ID, SearchKeybindingAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.KEY_F,
}, CONTEXT_KEYBINDINGS_EDITOR), '');
registry.registerWorkbenchAction(new SyncActionDescriptor(DefineKeybindingAction, DefineKeybindingAction.ID, DefineKeybindingAction.LABEL, {
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K),
}, ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS)), '');
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(PreferencesContentProvider);
\ No newline at end of file
......@@ -10,7 +10,8 @@ import URI from 'vs/base/common/uri';
import { Action } from 'vs/base/common/actions';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IQuickOpenService, IPickOpenEntry, IFilePickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen';
import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences';
import { IPreferencesService, IKeybindingsEditor, KEYBINDINGS_EDITOR_ID } from 'vs/workbench/parts/preferences/common/preferences';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
export class OpenGlobalSettingsAction extends Action {
......@@ -113,4 +114,51 @@ export class ConfigureLanguageBasedSettingsAction extends Action {
});
}
}
export class DefineKeybindingAction extends Action {
public static ID = 'keybindings.editor.define';
public static LABEL = nls.localize('keybindings.editor.define', "Define Keybinding");
constructor(
id: string,
label: string,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
) {
super(id, label);
}
public run(event?: any): TPromise<any> {
const activeEditor = this.editorService.getActiveEditor();
if (activeEditor.getId() === KEYBINDINGS_EDITOR_ID) {
const keybindingsEditor = activeEditor as IKeybindingsEditor;
if (keybindingsEditor.activeKeybindingEntry) {
return keybindingsEditor.defineKeybinding(keybindingsEditor.activeKeybindingEntry);
}
}
return TPromise.as(null);
}
}
export class SearchKeybindingAction extends Action {
public static ID = 'keybindings.editor.search';
public static LABEL = nls.localize('keybindings.editor.search', "Search Keybindings");
constructor(
id: string,
label: string,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
) {
super(id, label);
}
public run(event?: any): TPromise<any> {
const activeEditor = this.editorService.getActiveEditor();
if (activeEditor.getId() === KEYBINDINGS_EDITOR_ID) {
(activeEditor as IKeybindingsEditor).search('');
}
return TPromise.as(null);
}
}
\ No newline at end of file
......@@ -10,6 +10,7 @@ import { IRange } from 'vs/editor/common/editorCommon';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IEditor } from 'vs/platform/editor/common/editor';
import { IKeybindingItemEntry } from 'vs/workbench/parts/preferences/common/keybindingsEditorModel';
export interface ISettingsGroup {
id: string;
......@@ -80,8 +81,18 @@ export interface IPreferencesService {
configureSettingsForLanguage(language: string): void;
}
export const CONTEXT_SETTINGS_EDITOR = new RawContextKey<boolean>('settingsEditor', false);
export const CONTEXT_KEYBINDINGS_EDITOR = new RawContextKey<boolean>('inKeybindingsEditor', false);
export const SETTINGS_EDITOR_COMMAND_SEARCH = 'settings.action.search';
export const ACTION_DEFINE_KEYBINDING = 'kebindings.action.define';
\ No newline at end of file
export interface IKeybindingsEditor extends IEditor {
activeKeybindingEntry: IKeybindingItemEntry;
search(filter: string): void;
defineKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise<any>;
}
export const KEYBINDINGS_EDITOR_ID = 'workbench.editor.keybindings';
export const CONTEXT_SETTINGS_EDITOR = new RawContextKey<boolean>('inSettingsEditor', false);
export const CONTEXT_KEYBINDINGS_EDITOR = new RawContextKey<boolean>('inKeybindings', false);
export const CONTEXT_KEYBINDING_FOCUS = new RawContextKey<boolean>('keybindingFocus', false);
export const SETTINGS_EDITOR_COMMAND_SEARCH = 'settings.action.search';
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册