Merge remote-tracking branch 'origin/master'

This commit is contained in:
Joao Moreno 2018-07-06 16:45:41 +02:00
commit 1d831bdcf1
16 changed files with 103 additions and 48 deletions

View file

@ -5,16 +5,16 @@
'use strict';
import { ProtocolHandler, Uri, window, Disposable, commands } from 'vscode';
import { UriHandler, Uri, window, Disposable, commands } from 'vscode';
import { dispose } from './util';
import * as querystring from 'querystring';
export class GitProtocolHandler implements ProtocolHandler {
export class GitProtocolHandler implements UriHandler {
private disposables: Disposable[] = [];
constructor() {
this.disposables.push(window.registerProtocolHandler(this));
this.disposables.push(window.registerUriHandler(this));
}
handleUri(uri: Uri): void {

View file

@ -682,7 +682,7 @@ export class CodeMenu {
const twoRowsEditorLayout = this.createMenuItem(nls.localize({ key: 'miTwoRowsEditorLayout', comment: ['&& denotes a mnemonic'] }, "T&&wo Rows"), 'workbench.action.editorLayoutTwoRows');
const threeRowsEditorLayout = this.createMenuItem(nls.localize({ key: 'miThreeRowsEditorLayout', comment: ['&& denotes a mnemonic'] }, "Three &&Rows"), 'workbench.action.editorLayoutThreeRows');
const twoByTwoGridEditorLayout = this.createMenuItem(nls.localize({ key: 'miTwoByTwoGridEditorLayout', comment: ['&& denotes a mnemonic'] }, "&&Grid (2x2)"), 'workbench.action.editorLayoutTwoByTwoGrid');
const twoColumnsRightEditorLayout = this.createMenuItem(nls.localize({ key: 'miTwoColumnsRightEditorLayout', comment: ['&& denotes a mnemonic'] }, "Two C&&olumns Right"), 'workbench.action.editorLayoutTwoColumnsRight');
const twoRowsRightEditorLayout = this.createMenuItem(nls.localize({ key: 'miTwoRowsRightEditorLayout', comment: ['&& denotes a mnemonic'] }, "Two R&&ows Right"), 'workbench.action.editorLayoutTwoRowsRight');
const twoColumnsBottomEditorLayout = this.createMenuItem(nls.localize({ key: 'miTwoColumnsBottomEditorLayout', comment: ['&& denotes a mnemonic'] }, "Two &&Columns Bottom"), 'workbench.action.editorLayoutTwoColumnsBottom');
const toggleEditorLayout = this.createMenuItem(nls.localize({ key: 'miToggleEditorLayout', comment: ['&& denotes a mnemonic'] }, "Toggle Vertical/Horizontal &&Layout"), 'workbench.action.toggleEditorGroupLayout');
@ -699,7 +699,7 @@ export class CodeMenu {
twoRowsEditorLayout,
threeRowsEditorLayout,
twoByTwoGridEditorLayout,
twoColumnsRightEditorLayout,
twoRowsRightEditorLayout,
twoColumnsBottomEditorLayout,
__separator__(),
toggleEditorLayout

38
src/vs/vscode.d.ts vendored
View file

@ -5732,6 +5732,21 @@ declare module 'vscode' {
readonly focused: boolean;
}
/**
* A uri handler is responsible for handling system-wide [uris](#Uri).
*
* @see [window.registerUriHandler](#window.registerUriHandler).
*/
export interface UriHandler {
/**
* Handle the provided system-wide [uri](#Uri).
*
* @see [window.registerUriHandler](#window.registerUriHandler).
*/
handleUri(uri: Uri): ProviderResult<void>;
}
/**
* Namespace for dealing with the current window of the editor. That is visible
* and active editors, as well as, UI elements to show messages, selections, and
@ -6203,6 +6218,29 @@ declare module 'vscode' {
*/
export function createTreeView<T>(viewId: string, options: { treeDataProvider: TreeDataProvider<T> }): TreeView<T>;
/**
* Registers a [uri handler](#UriHandler) capable of handling system-wide [uris](#Uri).
* In case there are multiple windows open, the topmost window will handle the uri.
* A uri handler is scoped to the extension it is contributed from; it will only
* be able to handle uris which are directed to the extension itself. A uri must respect
* the following rules:
*
* - The uri-scheme must be the product name;
* - The uri-authority must be the extension id (eg. `my.extension`);
* - The uri-path, -query and -fragment parts are arbitrary.
*
* For example, if the `my.extension` extension registers a uri handler, it will only
* be allowed to handle uris with the prefix `product-name://my.extension`.
*
* An extension can only register a single uri handler in its entire activation lifetime.
*
* * *Note:* There is an activation event `onUri` that fires when a uri directed for
* the current extension is about to be handled.
*
* @param handler The uri handler to register for this extension.
*/
export function registerUriHandler(handler: UriHandler): Disposable;
/**
* Registers a webview panel serializer.
*

View file

@ -638,22 +638,6 @@ declare module 'vscode' {
//#endregion
//#region URLs
export interface ProtocolHandler {
handleUri(uri: Uri): void;
}
export namespace window {
/**
* Registers a protocol handler capable of handling system-wide URIs.
*/
export function registerProtocolHandler(handler: ProtocolHandler): Disposable;
}
//#endregion
//#region Joh -> exclusive document filters
export interface DocumentFilter {

View file

@ -42,7 +42,7 @@ export class MainThreadUrls implements MainThreadUrlsShape {
this.proxy = context.getProxy(ExtHostContext.ExtHostUrls);
}
$registerProtocolHandler(handle: number, extensionId: string): TPromise<void> {
$registerUriHandler(handle: number, extensionId: string): TPromise<void> {
const handler = new ExtensionUrlHandler(this.proxy, handle, extensionId);
const disposable = this.urlService.registerHandler(handler);
@ -52,7 +52,7 @@ export class MainThreadUrls implements MainThreadUrlsShape {
return TPromise.as(null);
}
$unregisterProtocolHandler(handle: number): TPromise<void> {
$unregisterUriHandler(handle: number): TPromise<void> {
const tuple = this.handlers.get(handle);
if (!tuple) {

View file

@ -452,9 +452,9 @@ export function createApiFactory(
registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => {
return extHostDecorations.registerDecorationProvider(provider, extension.id);
}),
registerProtocolHandler: proposedApiFunction(extension, (handler: vscode.ProtocolHandler) => {
return extHostUrls.registerProtocolHandler(extension.id, handler);
}),
registerUriHandler(handler: vscode.UriHandler) {
return extHostUrls.registerUriHandler(extension.id, handler);
},
get quickInputBackButton() {
return proposedApiFunction(extension, (): vscode.QuickInputButton => {
return extHostQuickOpen.backButton;

View file

@ -453,8 +453,8 @@ export interface ExtHostWebviewsShape {
}
export interface MainThreadUrlsShape extends IDisposable {
$registerProtocolHandler(handle: number, extensionId: string): TPromise<void>;
$unregisterProtocolHandler(handle: number): TPromise<void>;
$registerUriHandler(handle: number, extensionId: string): TPromise<void>;
$unregisterUriHandler(handle: number): TPromise<void>;
}
export interface ExtHostUrlsShape {

View file

@ -8,6 +8,8 @@ import { MainContext, IMainContext, ExtHostUrlsShape, MainThreadUrlsShape } from
import URI, { UriComponents } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { toDisposable } from 'vs/base/common/lifecycle';
import { asWinJsPromise } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
export class ExtHostUrls implements ExtHostUrlsShape {
@ -15,7 +17,7 @@ export class ExtHostUrls implements ExtHostUrlsShape {
private readonly _proxy: MainThreadUrlsShape;
private handles = new Set<string>();
private handlers = new Map<number, vscode.ProtocolHandler>();
private handlers = new Map<number, vscode.UriHandler>();
constructor(
mainContext: IMainContext
@ -23,7 +25,7 @@ export class ExtHostUrls implements ExtHostUrlsShape {
this._proxy = mainContext.getProxy(MainContext.MainThreadUrls);
}
registerProtocolHandler(extensionId: string, handler: vscode.ProtocolHandler): vscode.Disposable {
registerUriHandler(extensionId: string, handler: vscode.UriHandler): vscode.Disposable {
if (this.handles.has(extensionId)) {
throw new Error(`Protocol handler already registered for extension ${extensionId}`);
}
@ -31,12 +33,12 @@ export class ExtHostUrls implements ExtHostUrlsShape {
const handle = ExtHostUrls.HandlePool++;
this.handles.add(extensionId);
this.handlers.set(handle, handler);
this._proxy.$registerProtocolHandler(handle, extensionId);
this._proxy.$registerUriHandler(handle, extensionId);
return toDisposable(() => {
this.handles.delete(extensionId);
this.handlers.delete(handle);
this._proxy.$unregisterProtocolHandler(handle);
this._proxy.$unregisterUriHandler(handle);
});
}
@ -47,7 +49,9 @@ export class ExtHostUrls implements ExtHostUrlsShape {
return TPromise.as(null);
}
handler.handleUri(URI.revive(uri));
asWinJsPromise(_ => handler.handleUri(URI.revive(uri)))
.done(null, onUnexpectedError);
return TPromise.as(null);
}
}

View file

@ -37,7 +37,7 @@ import {
ShowEditorsInActiveGroupAction, MoveEditorToLastGroupAction, OpenFirstEditorInGroup, MoveGroupUpAction, MoveGroupDownAction, FocusLastGroupAction, SplitEditorLeftAction, SplitEditorRightAction,
SplitEditorUpAction, SplitEditorDownAction, MoveEditorToLeftGroupAction, MoveEditorToRightGroupAction, MoveEditorToAboveGroupAction, MoveEditorToBelowGroupAction, CloseAllEditorGroupsAction,
JoinAllGroupsAction, FocusLeftGroup, FocusAboveGroup, FocusRightGroup, FocusBelowGroup, EditorLayoutSingleAction, EditorLayoutTwoColumnsAction, EditorLayoutThreeColumnsAction, EditorLayoutTwoByTwoGridAction,
EditorLayoutTwoRowsAction, EditorLayoutThreeRowsAction, EditorLayoutTwoColumnsBottomAction, EditorLayoutTwoColumnsRightAction, NewEditorGroupLeftAction, NewEditorGroupRightAction,
EditorLayoutTwoRowsAction, EditorLayoutThreeRowsAction, EditorLayoutTwoColumnsBottomAction, EditorLayoutTwoRowsRightAction, NewEditorGroupLeftAction, NewEditorGroupRightAction,
NewEditorGroupAboveAction, NewEditorGroupBelowAction, SplitEditorOrthogonalAction
} from 'vs/workbench/browser/parts/editor/editorActions';
import * as editorCommands from 'vs/workbench/browser/parts/editor/editorCommands';
@ -368,7 +368,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutThreeColum
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoRowsAction, EditorLayoutTwoRowsAction.ID, EditorLayoutTwoRowsAction.LABEL), 'View: Two Rows Editor Layout', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutThreeRowsAction, EditorLayoutThreeRowsAction.ID, EditorLayoutThreeRowsAction.LABEL), 'View: Three Rows Editor Layout', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoByTwoGridAction, EditorLayoutTwoByTwoGridAction.ID, EditorLayoutTwoByTwoGridAction.LABEL), 'View: Grid Editor Layout (2x2)', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoColumnsRightAction, EditorLayoutTwoColumnsRightAction.ID, EditorLayoutTwoColumnsRightAction.LABEL), 'View: Two Columns Right Editor Layout', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoRowsRightAction, EditorLayoutTwoRowsRightAction.ID, EditorLayoutTwoRowsRightAction.LABEL), 'View: Two Rows Right Editor Layout', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoColumnsBottomAction, EditorLayoutTwoColumnsBottomAction.ID, EditorLayoutTwoColumnsBottomAction.LABEL), 'View: Two Columns Bottom Editor Layout', category);
// Register Editor Picker Actions including quick navigate support

View file

@ -1551,10 +1551,10 @@ export class EditorLayoutTwoColumnsBottomAction extends ExecuteCommandAction {
}
}
export class EditorLayoutTwoColumnsRightAction extends ExecuteCommandAction {
export class EditorLayoutTwoRowsRightAction extends ExecuteCommandAction {
static readonly ID = 'workbench.action.editorLayoutTwoColumnsRight';
static readonly LABEL = nls.localize('editorLayoutTwoColumnsRight', "Two Columns Right Editor Layout");
static readonly ID = 'workbench.action.editorLayoutTwoRowsRight';
static readonly LABEL = nls.localize('editorLayoutTwoRowsRight', "Two Rows Right Editor Layout");
constructor(
id: string,

View file

@ -840,8 +840,8 @@ function layoutMenuRegistration() {
MenuRegistry.appendMenuItem(MenuId.MenubarLayoutMenu, {
group: '2_layouts',
command: {
id: 'workbench.action.editorLayoutTwoColumnsRight',
title: nls.localize({ key: 'miTwoColumnsRightEditorLayout', comment: ['&& denotes a mnemonic'] }, "Two C&&olumns Right")
id: 'workbench.action.editorLayoutTwoRowsRight',
title: nls.localize({ key: 'miTwoRowsRightEditorLayout', comment: ['&& denotes a mnemonic'] }, "Two R&&ows Right")
},
order: 8
});

View file

@ -214,7 +214,9 @@ export class DefineKeybindingWidget extends Widget {
this._domNode.setClassName('defineKeybindingWidget');
this._domNode.setWidth(DefineKeybindingWidget.WIDTH);
this._domNode.setHeight(DefineKeybindingWidget.HEIGHT);
dom.append(this._domNode.domNode, dom.$('.message', null, nls.localize('defineKeybinding.initial', "Press desired key combination and then press ENTER.")));
const message = nls.localize('defineKeybinding.initial', "Press desired key combination and then press ENTER.");
dom.append(this._domNode.domNode, dom.$('.message', null, message));
this._register(attachStylerCallback(this.themeService, { editorWidgetBackground, widgetShadow }, colors => {
if (colors.editorWidgetBackground) {
@ -230,7 +232,7 @@ export class DefineKeybindingWidget extends Widget {
}
}));
this._keybindingInputWidget = this._register(this.instantiationService.createInstance(KeybindingInputWidget, this._domNode.domNode, {}));
this._keybindingInputWidget = this._register(this.instantiationService.createInstance(KeybindingInputWidget, this._domNode.domNode, { ariaLabel: message }));
this._register(this._keybindingInputWidget.onKeybinding(keybinding => this.onKeybinding(keybinding)));
this._register(this._keybindingInputWidget.onEnter(() => this.hide()));
this._register(this._keybindingInputWidget.onEscape(() => this.onCancel()));

View file

@ -74,6 +74,8 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
private searchFocusContextKey: IContextKey<boolean>;
private sortByPrecedence: Checkbox;
private ariaLabelElement: HTMLElement;
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IThemeService themeService: IThemeService,
@ -100,6 +102,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
createEditor(parent: HTMLElement): void {
const keybindingsEditorElement = DOM.append(parent, $('div', { class: 'keybindings-editor' }));
this.createAriaLabelElement(keybindingsEditorElement);
this.createOverlayContainer(keybindingsEditorElement);
this.createHeader(keybindingsEditorElement);
this.createBody(keybindingsEditorElement);
@ -268,6 +271,12 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
return TPromise.as(null);
}
private createAriaLabelElement(parent: HTMLElement): void {
this.ariaLabelElement = DOM.append(parent, DOM.$(''));
this.ariaLabelElement.setAttribute('id', 'keybindings-editor-aria-label-element');
this.ariaLabelElement.setAttribute('aria-live', 'assertive');
}
private createOverlayContainer(parent: HTMLElement): void {
this.overlayContainer = DOM.append(parent, $('.overlay-container'));
this.overlayContainer.style.position = 'absolute';
@ -293,7 +302,8 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
this.searchWidget = this._register(this.instantiationService.createInstance(SearchWidget, searchContainer, {
ariaLabel: localize('SearchKeybindings.AriaLabel', "Search keybindings"),
placeholder: localize('SearchKeybindings.Placeholder', "Search keybindings"),
focusKey: this.searchFocusContextKey
focusKey: this.searchFocusContextKey,
ariaLabelledBy: 'keybindings-editor-aria-label-element'
}));
this._register(this.searchWidget.onDidChange(searchValue => this.delayedFiltering.trigger(() => this.filterKeybindings())));
@ -302,8 +312,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
isChecked: false,
title: localize('sortByPrecedene', "Sort by Precedence")
}));
this._register(
this.sortByPrecedence.onChange(() => this.renderKeybindingsEntries(false)));
this._register(this.sortByPrecedence.onChange(() => this.renderKeybindingsEntries(false)));
searchContainer.appendChild(this.sortByPrecedence.domNode);
this.createOpenKeybindingsElement(this.headerContainer);
@ -397,6 +406,9 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
if (this.keybindingsEditorModel) {
const filter = this.searchWidget.getValue();
const keybindingsEntries: IKeybindingItemEntry[] = this.keybindingsEditorModel.fetch(filter, this.sortByPrecedence.checked);
this.ariaLabelElement.setAttribute('aria-label', this.getAriaLabel(keybindingsEntries));
if (keybindingsEntries.length === 0) {
this.latestEmptyFilters.push(filter);
}
@ -425,6 +437,14 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
}
}
private getAriaLabel(keybindingsEntries: IKeybindingItemEntry[]): string {
if (this.sortByPrecedence.checked) {
return localize('show sorted keybindings', "Showing {0} Keybindings in precendence order", keybindingsEntries.length);
} else {
return localize('show keybindings', "Showing {0} Keybindings in alphabetical order", keybindingsEntries.length);
}
}
private layoutKebindingsList(): void {
const listHeight = this.dimension.height - (DOM.getDomNodePagePosition(this.headerContainer).height + 12 /*padding*/);
this.keybindingsListContainer.style.height = `${listHeight}px`;

View file

@ -126,7 +126,8 @@ export class PreferencesEditor extends BaseEditor {
ariaLabel: nls.localize('SearchSettingsWidget.AriaLabel', "Search settings"),
placeholder: nls.localize('SearchSettingsWidget.Placeholder', "Search Settings"),
focusKey: this.searchFocusContextKey,
showResultCount: true
showResultCount: true,
ariaLive: 'assertive'
}));
this._register(this.searchWidget.onDidChange(value => this.onInputChanged()));
this._register(this.searchWidget.onFocus(() => this.lastFocusedWidget = this.searchWidget));

View file

@ -561,6 +561,8 @@ export class SettingsTargetsWidget extends Widget {
export interface SearchOptions extends IInputOptions {
focusKey?: IContextKey<boolean>;
showResultCount?: boolean;
ariaLive?: string;
ariaLabelledBy?: string;
}
export class SearchWidget extends Widget {
@ -608,7 +610,10 @@ export class SearchWidget extends Widget {
}));
}
this.inputBox.inputElement.setAttribute('aria-live', 'assertive');
this.inputBox.inputElement.setAttribute('aria-live', this.options.ariaLive || 'off');
if (this.options.ariaLabelledBy) {
this.inputBox.inputElement.setAttribute('aria-labelledBy', this.options.ariaLabelledBy);
}
const focusTracker = this._register(DOM.trackFocus(this.inputBox.inputElement));
this._register(focusTracker.onDidFocus(() => this._onFocus.fire()));

View file

@ -189,7 +189,8 @@ export class SettingsEditor2 extends BaseEditor {
this.searchWidget = this._register(this.instantiationService.createInstance(SearchWidget, searchContainer, {
ariaLabel: localize('SearchSettings.AriaLabel', "Search settings"),
placeholder: localize('SearchSettings.Placeholder', "Search settings"),
focusKey: this.searchFocusContextKey
focusKey: this.searchFocusContextKey,
ariaLive: 'assertive'
}));
this._register(this.searchWidget.onDidChange(() => this.onSearchInputChanged()));