提交 45a41dc8 编写于 作者: S Sandeep Somavarapu

Implement #23400

上级 0794dd98
......@@ -9,6 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { Delayer } from 'vs/base/common/async';
import * as DOM from 'vs/base/browser/dom';
import { OS } from 'vs/base/common/platform';
import { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox';
import { Builder, Dimension } from 'vs/base/browser/builder';
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';
......@@ -23,7 +24,10 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IKeybindingService, IUserFriendlyKeybinding } 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, IKeybindingsEditor, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_DEFINE } from 'vs/workbench/parts/preferences/common/preferences';
import {
IPreferencesService, IKeybindingsEditor, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_COPY,
KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS
} from 'vs/workbench/parts/preferences/common/preferences';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IKeybindingEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing';
import { IListService } from 'vs/platform/list/browser/listService';
......@@ -87,6 +91,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
private delayedFilterLogging: Delayer<void>;
private keybindingsEditorContextKey: IContextKey<boolean>;
private keybindingFocusContextKey: IContextKey<boolean>;
private sortByPrecedence: Checkbox;
constructor(
@ITelemetryService telemetryService: ITelemetryService,
......@@ -240,6 +245,14 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
this.searchWidget.focus();
}
showConflicts(keybindingEntry: IKeybindingItemEntry): TPromise<any> {
const value = `"${keybindingEntry.keybindingItem.keybinding.getAriaLabel()}"`;
if (value !== this.searchWidget.getValue()) {
this.searchWidget.setValue(value);
}
return TPromise.as(null);
}
private createOverlayContainer(parent: HTMLElement): void {
this.overlayContainer = DOM.append(parent, $('.overlay-container'));
this.overlayContainer.style.position = 'absolute';
......@@ -258,7 +271,9 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
private createHeader(parent: HTMLElement): void {
this.headerContainer = DOM.append(parent, $('.keybindings-header'));
this.searchWidget = this._register(this.instantiationService.createInstance(SearchWidget, DOM.append(this.headerContainer, $('.search-container')), {
const searchContainer = DOM.append(this.headerContainer, $('.search-container'));
this.searchWidget = this._register(this.instantiationService.createInstance(SearchWidget, searchContainer, {
ariaLabel: localize('SearchKeybindings.AriaLabel', "Search keybindings"),
placeholder: localize('SearchKeybindings.Placeholder', "Search keybindings"),
navigateByArrows: true
......@@ -266,6 +281,14 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
this._register(this.searchWidget.onDidChange(searchValue => this.delayedFiltering.trigger(() => this.filterKeybindings())));
this._register(this.searchWidget.onNavigate(back => this._onNavigate(back)));
this.sortByPrecedence = this._register(new Checkbox({
actionClassName: 'sort-by-precedence',
isChecked: false,
onChange: () => this.renderKeybindingsEntries(false),
title: localize('sortByPrecedene', "Sort by Precedence")
}));
searchContainer.appendChild(this.sortByPrecedence.domNode);
this.createOpenKeybindingsElement(this.headerContainer);
}
......@@ -322,14 +345,14 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
}
private filterKeybindings(): void {
this.renderKeybindingsEntries(true);
this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(this.searchWidget.value()));
this.renderKeybindingsEntries(this.searchWidget.hasFocus());
this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(this.searchWidget.getValue()));
}
private renderKeybindingsEntries(reset: boolean): void {
if (this.keybindingsEditorModel) {
const filter = this.searchWidget.value();
const keybindingsEntries: IKeybindingItemEntry[] = this.keybindingsEditorModel.fetch(filter);
const filter = this.searchWidget.getValue();
const keybindingsEntries: IKeybindingItemEntry[] = this.keybindingsEditorModel.fetch(filter, this.sortByPrecedence.checked);
if (keybindingsEntries.length === 0) {
this.latestEmptyFilters.push(filter);
}
......@@ -351,6 +374,8 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
this.unAssignedKeybindingItemToRevealAndFocus = null;
} else if (currentSelectedIndex !== -1 && currentSelectedIndex < this.listEntries.length) {
this.selectEntry(currentSelectedIndex);
} else {
this.focus();
}
}
}
......@@ -414,7 +439,9 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
new Separator(),
this.createDefineAction(<IKeybindingItemEntry>e.element),
this.createRemoveAction(<IKeybindingItemEntry>e.element),
this.createResetAction(<IKeybindingItemEntry>e.element)]),
this.createResetAction(<IKeybindingItemEntry>e.element),
new Separator(),
this.createShowConflictsAction(<IKeybindingItemEntry>e.element)]),
getKeyBinding: (action) => this.keybindingsService.lookupKeybinding(action.id)
});
}
......@@ -462,6 +489,15 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
};
}
private createShowConflictsAction(keybindingItem: IKeybindingItemEntry): IAction {
return <IAction>{
label: localize('showConflictsLabel', "Show Conflicts"),
enabled: !!keybindingItem.keybindingItem.keybinding,
id: KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS,
run: () => this.showConflicts(keybindingItem)
};
}
private createCopyAction(keybindingItem: IKeybindingItemEntry): IAction {
return <IAction>{
label: localize('copyLabel', "Copy"),
......
......@@ -13,6 +13,23 @@
padding: 0px 10px 11px 0;
}
.keybindings-editor > .keybindings-header > .search-container {
position: relative;
}
.keybindings-editor > .keybindings-header > .search-container > .sort-by-precedence {
position: absolute;
top: 0;
right: 10px;
margin-top: 5px;
background: url('sort_precedence.svg') center center no-repeat;
}
.hc-black .keybindings-editor > .keybindings-header > .search-container > .sort-by-precedence,
.vs-dark .keybindings-editor > .keybindings-header > .search-container > .sort-by-precedence {
background: url('sort_precedence_inverse.svg') center center no-repeat;
}
.keybindings-editor > .keybindings-header .search-container > .settings-search-input {
vertical-align: middle;
}
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.st0{opacity:0}.st0,.st1{fill:#f6f6f6}.st2{fill:#424242}.st3{fill:#f0eff1}</style><g id="outline"><path class="st0" d="M0 0h16v16H0z"/><path class="st1" d="M5 1v5H0v9h11v-2.586l1 1 4-4V1H5zm5 3v2L8 4.586V4h2zm-2 8H3V9h5v3z"/></g><g id="icon_x5F_bg"><path class="st2" d="M3 9h2v2H3zM6 10h2v2H6zM14 3v3h.586L15 5.586V2H6v4h1V3z"/><path class="st2" d="M9 10.414V13H2V8h6V7H1v7h9V11.414zM9.414 6H10V4H8v.586z"/><path class="st2" d="M13 5h-2v4L9 7v2l3 3 3-3V7l-2 2z"/></g><g id="icon_x5F_fg"><path class="st3" d="M8 9.414V8H2v5h7v-2.586l-1-1zM5 11H3V9h2v2zm3 1H6v-2h2v2zM8 4.586V4h6V3H7v3h1z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.st0{opacity:0}.st0,.st1{fill:#f6f6f6}.st2{fill:#424242}.st3{fill:#f0eff1}</style><g id="outline"><path class="st0" d="M0 0h16v16H0z"/><path class="st1" d="M5 1v5H0v9h11v-2.586l1 1 4-4V1H5zm5 3v2L8 4.586V4h2zm-2 8H3V9h5v3z"/></g><g id="icon_x5F_bg"><path class="st2" d="M3 9h2v2H3zM6 10h2v2H6zM14 3v3h.586L15 5.586V2H6v4h1V3z"/><path class="st2" d="M9 10.414V13H2V8h6V7H1v7h9V11.414zM9.414 6H10V4H8v.586z"/><path class="st2" d="M13 5h-2v4L9 7v2l3 3 3-3V7l-2 2z"/></g><g id="icon_x5F_fg"><path class="st3" d="M8 9.414V8H2v5h7v-2.586l-1-1zM5 11H3V9h2v2zm3 1H6v-2h2v2zM8 4.586V4h6V3H7v3h1z"/></g></svg>
\ No newline at end of file
......@@ -20,7 +20,7 @@ import { KeybindingsEditor, KeybindingsEditorInput } from 'vs/workbench/parts/pr
import { OpenGlobalSettingsAction, OpenGlobalKeybindingsAction, OpenWorkspaceSettingsAction, ConfigureLanguageBasedSettingsAction } from 'vs/workbench/parts/preferences/browser/preferencesActions';
import {
IPreferencesService, IKeybindingsEditor, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_SEARCH,
KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_RESET
KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS
} from 'vs/workbench/parts/preferences/common/preferences';
import { PreferencesService } from 'vs/workbench/parts/preferences/browser/preferencesService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
......@@ -211,6 +211,17 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
handler: (accessor, args: any) => (accessor.get(IWorkbenchEditorService).getActiveEditor() as IKeybindingsEditor).search('')
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS),
primary: null,
handler: (accessor, args: any) => {
const editor = accessor.get(IWorkbenchEditorService).getActiveEditor() as IKeybindingsEditor;
editor.showConflicts(editor.activeKeybindingEntry);
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: KEYBINDINGS_EDITOR_COMMAND_COPY,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
......
......@@ -188,7 +188,7 @@ export class PreferencesEditor extends BaseEditor {
return this.sideBySidePreferencesWidget.setInput(<DefaultPreferencesEditorInput>newInput.details, newInput.master, options).then(({ defaultPreferencesRenderer, editablePreferencesRenderer }) => {
this.preferencesRenderers.defaultPreferencesRenderer = defaultPreferencesRenderer;
this.preferencesRenderers.editablePreferencesRenderer = editablePreferencesRenderer;
this.filterPreferences(this.searchWidget.value());
this.filterPreferences(this.searchWidget.getValue());
});
}
......
......@@ -241,10 +241,10 @@ export class SearchWidget extends Widget {
private inputBox: InputBox;
private _onDidChange = this._register(new Emitter<string>());
public onDidChange: Event<string> = this._onDidChange.event;
public readonly onDidChange: Event<string> = this._onDidChange.event;
private _onNavigate = this._register(new Emitter<boolean>());
public onNavigate: Event<boolean> = this._onNavigate.event;
public readonly onNavigate: Event<boolean> = this._onNavigate.event;
constructor(parent: HTMLElement, protected options: SearchOptions,
@IContextViewService private contextViewService: IContextViewService,
......@@ -297,19 +297,27 @@ export class SearchWidget extends Widget {
public focus() {
this.inputBox.focus();
if (this.value) {
if (this.getValue()) {
this.inputBox.select();
}
}
public hasFocus(): boolean {
return this.inputBox.hasFocus();
}
public clear() {
this.inputBox.value = '';
}
public value(): string {
public getValue(): string {
return this.inputBox.value;
}
public setValue(value: string): string {
return this.inputBox.value = value;
}
private _onKeyDown(keyboardEvent: IKeyboardEvent): void {
let handled = false;
switch (keyboardEvent.keyCode) {
......
......@@ -73,6 +73,7 @@ const wordFilter = or(matchesPrefix, matchesWords, matchesContiguousSubString);
export class KeybindingsEditorModel extends EditorModel {
private _keybindingItems: IKeybindingItem[];
private _keybindingItemsSortedByPrecedence: IKeybindingItem[];
private modifierLabels: ModifierLabels;
constructor(
......@@ -88,7 +89,7 @@ export class KeybindingsEditorModel extends EditorModel {
};
}
public fetch(searchValue: string): IKeybindingItemEntry[] {
public fetch(searchValue: string, sortByPrecedence: boolean = false): IKeybindingItemEntry[] {
searchValue = searchValue.trim();
const quoteAtFirstChar = searchValue.charAt(0) === '"';
const quoteAtLastChar = searchValue.charAt(searchValue.length - 1) === '"';
......@@ -99,15 +100,18 @@ export class KeybindingsEditorModel extends EditorModel {
searchValue = searchValue.substring(0, searchValue.length - 1);
}
searchValue = searchValue.trim();
return searchValue ? this.fetchKeybindingItems(searchValue, quoteAtFirstChar && quoteAtLastChar) :
this._keybindingItems.map(keybindingItem => ({ id: KeybindingsEditorModel.getId(keybindingItem), keybindingItem, templateId: KEYBINDING_ENTRY_TEMPLATE_ID }));
return this.fetchKeybindingItems(sortByPrecedence ? this._keybindingItemsSortedByPrecedence : this._keybindingItems, searchValue, quoteAtFirstChar && quoteAtLastChar);
}
private fetchKeybindingItems(searchValue: string, completeMatch: boolean): IKeybindingItemEntry[] {
private fetchKeybindingItems(keybindingItems: IKeybindingItem[], searchValue: string, completeMatch: boolean): IKeybindingItemEntry[] {
if (!searchValue) {
return keybindingItems.map(keybindingItem => ({ id: KeybindingsEditorModel.getId(keybindingItem), keybindingItem, templateId: KEYBINDING_ENTRY_TEMPLATE_ID }));
}
const result: IKeybindingItemEntry[] = [];
const words = searchValue.split(' ');
const keybindingWords = this.splitKeybindingWords(words);
for (const keybindingItem of this._keybindingItems) {
for (const keybindingItem of keybindingItems) {
let keybindingMatches = new KeybindingItemMatches(this.modifierLabels, keybindingItem, searchValue, words, keybindingWords, completeMatch);
if (keybindingMatches.commandIdMatches
|| keybindingMatches.commandLabelMatches
......@@ -148,11 +152,11 @@ export class KeybindingsEditorModel extends EditorModel {
return editorActions;
}, {});
this._keybindingItems = [];
this._keybindingItemsSortedByPrecedence = [];
const boundCommands: Map<string, boolean> = new Map<string, boolean>();
for (const keybinding of this.keybindingsService.getKeybindings()) {
if (keybinding.command) { // Skip keybindings without commands
this._keybindingItems.push(KeybindingsEditorModel.toKeybindingEntry(keybinding.command, keybinding, workbenchActionsRegistry, editorActions));
this._keybindingItemsSortedByPrecedence.push(KeybindingsEditorModel.toKeybindingEntry(keybinding.command, keybinding, workbenchActionsRegistry, editorActions));
boundCommands.set(keybinding.command, true);
}
}
......@@ -160,9 +164,9 @@ export class KeybindingsEditorModel extends EditorModel {
const commandsWithDefaultKeybindings = this.keybindingsService.getDefaultKeybindings().map(keybinding => keybinding.command);
for (const command of KeybindingResolver.getAllUnboundCommands(boundCommands)) {
const keybindingItem = new ResolvedKeybindingItem(null, command, null, null, commandsWithDefaultKeybindings.indexOf(command) === -1);
this._keybindingItems.push(KeybindingsEditorModel.toKeybindingEntry(command, keybindingItem, workbenchActionsRegistry, editorActions));
this._keybindingItemsSortedByPrecedence.push(KeybindingsEditorModel.toKeybindingEntry(command, keybindingItem, workbenchActionsRegistry, editorActions));
}
this._keybindingItems = this._keybindingItems.sort((a, b) => KeybindingsEditorModel.compareKeybindingData(a, b));
this._keybindingItems = this._keybindingItemsSortedByPrecedence.slice(0).sort((a, b) => KeybindingsEditorModel.compareKeybindingData(a, b));
return this;
});
}
......
......@@ -91,6 +91,7 @@ export interface IKeybindingsEditor extends IEditor {
removeKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise<any>;
resetKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise<any>;
copyKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise<any>;
showConflicts(keybindingEntry: IKeybindingItemEntry): TPromise<any>;
}
export const CONTEXT_SETTINGS_EDITOR = new RawContextKey<boolean>('inSettingsEditor', false);
......@@ -102,4 +103,5 @@ export const KEYBINDINGS_EDITOR_COMMAND_SEARCH = 'keybindings.editor.searchKeybi
export const KEYBINDINGS_EDITOR_COMMAND_DEFINE = 'keybindings.editor.defineKeybinding';
export const KEYBINDINGS_EDITOR_COMMAND_REMOVE = 'keybindings.editor.removeKeybinding';
export const KEYBINDINGS_EDITOR_COMMAND_RESET = 'keybindings.editor.resetKeybinding';
export const KEYBINDINGS_EDITOR_COMMAND_COPY = 'keybindings.editor.copyKeybindingEntry';
\ No newline at end of file
export const KEYBINDINGS_EDITOR_COMMAND_COPY = 'keybindings.editor.copyKeybindingEntry';
export const KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS = 'keybindings.editor.showConflicts';
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册