mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode 1ec43773e37997841c5af42b33ddb180e9735bf2
This commit is contained in:
@@ -1,196 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree';
|
||||
import { IInstantiationService, IConstructorSignature0, ServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
/**
|
||||
* The action bar contributor allows to add actions to an actionbar in a given context.
|
||||
*/
|
||||
export class ActionBarContributor {
|
||||
|
||||
/**
|
||||
* Returns true if this contributor has actions for the given context.
|
||||
*/
|
||||
hasActions(context: unknown): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of primary actions in the given context.
|
||||
*/
|
||||
getActions(context: unknown): ReadonlyArray<IAction> {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some predefined scopes to contribute actions to
|
||||
*/
|
||||
export const Scope = {
|
||||
|
||||
/**
|
||||
* Actions inside tree widgets.
|
||||
*/
|
||||
VIEWER: 'viewer'
|
||||
};
|
||||
|
||||
/**
|
||||
* The ContributableActionProvider leverages the actionbar contribution model to find actions.
|
||||
*/
|
||||
export class ContributableActionProvider implements IActionProvider {
|
||||
private readonly registry: IActionBarRegistry = Registry.as<IActionBarRegistry>(Extensions.Actionbar);
|
||||
|
||||
private toContext(tree: ITree, element: unknown): unknown {
|
||||
return {
|
||||
viewer: tree,
|
||||
element: element
|
||||
};
|
||||
}
|
||||
|
||||
hasActions(tree: ITree, element: unknown): boolean {
|
||||
const context = this.toContext(tree, element);
|
||||
|
||||
const contributors = this.registry.getActionBarContributors(Scope.VIEWER);
|
||||
return contributors.some(contributor => contributor.hasActions(context));
|
||||
}
|
||||
|
||||
getActions(tree: ITree, element: unknown): ReadonlyArray<IAction> {
|
||||
const actions: IAction[] = [];
|
||||
const context = this.toContext(tree, element);
|
||||
|
||||
// Collect Actions
|
||||
const contributors = this.registry.getActionBarContributors(Scope.VIEWER);
|
||||
for (const contributor of contributors) {
|
||||
if (contributor.hasActions(context)) {
|
||||
actions.push(...contributor.getActions(context));
|
||||
}
|
||||
}
|
||||
|
||||
return prepareActions(actions);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function used in parts to massage actions before showing in action areas
|
||||
export function prepareActions(actions: IAction[]): IAction[] {
|
||||
if (!actions.length) {
|
||||
return actions;
|
||||
}
|
||||
|
||||
// Clean up leading separators
|
||||
let firstIndexOfAction = -1;
|
||||
for (let i = 0; i < actions.length; i++) {
|
||||
if (actions[i].id === Separator.ID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
firstIndexOfAction = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (firstIndexOfAction === -1) {
|
||||
return [];
|
||||
}
|
||||
|
||||
actions = actions.slice(firstIndexOfAction);
|
||||
|
||||
// Clean up trailing separators
|
||||
for (let h = actions.length - 1; h >= 0; h--) {
|
||||
const isSeparator = actions[h].id === Separator.ID;
|
||||
if (isSeparator) {
|
||||
actions.splice(h, 1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up separator duplicates
|
||||
let foundAction = false;
|
||||
for (let k = actions.length - 1; k >= 0; k--) {
|
||||
const isSeparator = actions[k].id === Separator.ID;
|
||||
if (isSeparator && !foundAction) {
|
||||
actions.splice(k, 1);
|
||||
} else if (!isSeparator) {
|
||||
foundAction = true;
|
||||
} else if (isSeparator) {
|
||||
foundAction = false;
|
||||
}
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
export const Extensions = {
|
||||
Actionbar: 'workbench.contributions.actionbar'
|
||||
};
|
||||
|
||||
export interface IActionBarRegistry {
|
||||
/**
|
||||
* Registers an Actionbar contributor. It will be called to contribute actions to all the action bars
|
||||
* that are used in the Workbench in the given scope.
|
||||
*/
|
||||
registerActionBarContributor<Services extends BrandedService[]>(scope: string, ctor: { new(...services: Services): ActionBarContributor }): void;
|
||||
|
||||
/**
|
||||
* Returns an array of registered action bar contributors known to the workbench for the given scope.
|
||||
*/
|
||||
getActionBarContributors(scope: string): ActionBarContributor[];
|
||||
|
||||
/**
|
||||
* Starts the registry by providing the required services.
|
||||
*/
|
||||
start(accessor: ServicesAccessor): void;
|
||||
}
|
||||
|
||||
class ActionBarRegistry implements IActionBarRegistry {
|
||||
private readonly actionBarContributorConstructors: { scope: string; ctor: IConstructorSignature0<ActionBarContributor>; }[] = [];
|
||||
private readonly actionBarContributorInstances: Map<string, ActionBarContributor[]> = new Map();
|
||||
private instantiationService: IInstantiationService | undefined;
|
||||
|
||||
start(accessor: ServicesAccessor): void {
|
||||
this.instantiationService = accessor.get(IInstantiationService);
|
||||
|
||||
while (this.actionBarContributorConstructors.length > 0) {
|
||||
const entry = this.actionBarContributorConstructors.shift()!;
|
||||
this.createActionBarContributor(entry.scope, entry.ctor);
|
||||
}
|
||||
}
|
||||
|
||||
private createActionBarContributor(scope: string, ctor: IConstructorSignature0<ActionBarContributor>): void {
|
||||
if (this.instantiationService) {
|
||||
const instance = this.instantiationService.createInstance(ctor);
|
||||
let target = this.actionBarContributorInstances.get(scope);
|
||||
if (!target) {
|
||||
target = [];
|
||||
this.actionBarContributorInstances.set(scope, target);
|
||||
}
|
||||
target.push(instance);
|
||||
}
|
||||
}
|
||||
|
||||
private getContributors(scope: string): ActionBarContributor[] {
|
||||
return this.actionBarContributorInstances.get(scope) || [];
|
||||
}
|
||||
|
||||
registerActionBarContributor(scope: string, ctor: IConstructorSignature0<ActionBarContributor>): void {
|
||||
if (!this.instantiationService) {
|
||||
this.actionBarContributorConstructors.push({
|
||||
scope: scope,
|
||||
ctor: ctor
|
||||
});
|
||||
} else {
|
||||
this.createActionBarContributor(scope, ctor);
|
||||
}
|
||||
}
|
||||
|
||||
getActionBarContributors(scope: string): ActionBarContributor[] {
|
||||
return this.getContributors(scope).slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
Registry.add(Extensions.Actionbar, new ActionBarRegistry());
|
||||
251
src/vs/workbench/browser/actions/quickAccessActions.ts
Normal file
251
src/vs/workbench/browser/actions/quickAccessActions.ts
Normal file
@@ -0,0 +1,251 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IQuickInputService, ItemActivation } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { inQuickPickContext, defaultQuickAccessContext, getQuickNavigateHandler } from 'vs/workbench/browser/quickaccess';
|
||||
|
||||
//#region Quick access management commands and keys
|
||||
|
||||
const globalQuickAccessKeybinding = {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_P,
|
||||
secondary: [KeyMod.CtrlCmd | KeyCode.KEY_E],
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_P, secondary: undefined }
|
||||
};
|
||||
|
||||
const QUICKACCESS_ACTION_ID = 'workbench.action.quickOpen';
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
command: { id: QUICKACCESS_ACTION_ID, title: { value: localize('quickOpen', "Go to File..."), original: 'Go to File...' } }
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerKeybindingRule({
|
||||
id: QUICKACCESS_ACTION_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: undefined,
|
||||
primary: globalQuickAccessKeybinding.primary,
|
||||
secondary: globalQuickAccessKeybinding.secondary,
|
||||
mac: globalQuickAccessKeybinding.mac
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.closeQuickOpen',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: inQuickPickContext,
|
||||
primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape],
|
||||
handler: accessor => {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
return quickInputService.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.acceptSelectedQuickOpenItem',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: inQuickPickContext,
|
||||
primary: 0,
|
||||
handler: accessor => {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
return quickInputService.accept();
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.alternativeAcceptSelectedQuickOpenItem',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: inQuickPickContext,
|
||||
primary: 0,
|
||||
handler: accessor => {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
return quickInputService.accept({ ctrlCmd: true, alt: false });
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.focusQuickOpen',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: inQuickPickContext,
|
||||
primary: 0,
|
||||
handler: accessor => {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
quickInputService.focus();
|
||||
}
|
||||
});
|
||||
|
||||
const quickAccessNavigateNextInFilePickerId = 'workbench.action.quickOpenNavigateNextInFilePicker';
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: quickAccessNavigateNextInFilePickerId,
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
handler: getQuickNavigateHandler(quickAccessNavigateNextInFilePickerId, true),
|
||||
when: defaultQuickAccessContext,
|
||||
primary: globalQuickAccessKeybinding.primary,
|
||||
secondary: globalQuickAccessKeybinding.secondary,
|
||||
mac: globalQuickAccessKeybinding.mac
|
||||
});
|
||||
|
||||
const quickAccessNavigatePreviousInFilePickerId = 'workbench.action.quickOpenNavigatePreviousInFilePicker';
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: quickAccessNavigatePreviousInFilePickerId,
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
handler: getQuickNavigateHandler(quickAccessNavigatePreviousInFilePickerId, false),
|
||||
when: defaultQuickAccessContext,
|
||||
primary: globalQuickAccessKeybinding.primary | KeyMod.Shift,
|
||||
secondary: [globalQuickAccessKeybinding.secondary[0] | KeyMod.Shift],
|
||||
mac: {
|
||||
primary: globalQuickAccessKeybinding.mac.primary | KeyMod.Shift,
|
||||
secondary: undefined
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.quickPickManyToggle',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: inQuickPickContext,
|
||||
primary: 0,
|
||||
handler: accessor => {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
quickInputService.toggle();
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.quickInputBack',
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
when: inQuickPickContext,
|
||||
primary: 0,
|
||||
win: { primary: KeyMod.Alt | KeyCode.LeftArrow },
|
||||
mac: { primary: KeyMod.WinCtrl | KeyCode.US_MINUS },
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.US_MINUS },
|
||||
handler: accessor => {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
quickInputService.back();
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: QUICKACCESS_ACTION_ID,
|
||||
handler: async function (accessor: ServicesAccessor, prefix: unknown) {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
|
||||
quickInputService.quickAccess.show(typeof prefix === 'string' ? prefix : undefined);
|
||||
},
|
||||
description: {
|
||||
description: `Quick access`,
|
||||
args: [{
|
||||
name: 'prefix',
|
||||
schema: {
|
||||
'type': 'string'
|
||||
}
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand('workbench.action.quickOpenPreviousEditor', async function (accessor: ServicesAccessor, prefix: string | null = null) {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
|
||||
quickInputService.quickAccess.show('', { itemActivation: ItemActivation.SECOND });
|
||||
});
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Workbench actions
|
||||
|
||||
export class BaseQuickAccessNavigateAction extends Action {
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
private next: boolean,
|
||||
private quickNavigate: boolean,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
const keys = this.keybindingService.lookupKeybindings(this.id);
|
||||
const quickNavigate = this.quickNavigate ? { keybindings: keys } : undefined;
|
||||
|
||||
this.quickInputService.navigate(this.next, quickNavigate);
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickAccessNavigateNextAction extends BaseQuickAccessNavigateAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenNavigateNext';
|
||||
static readonly LABEL = localize('quickNavigateNext', "Navigate Next in Quick Open");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, true, true, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
class QuickAccessNavigatePreviousAction extends BaseQuickAccessNavigateAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenNavigatePrevious';
|
||||
static readonly LABEL = localize('quickNavigatePrevious', "Navigate Previous in Quick Open");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, false, true, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
class QuickAccessSelectNextAction extends BaseQuickAccessNavigateAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenSelectNext';
|
||||
static readonly LABEL = localize('quickSelectNext', "Select Next in Quick Open");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, true, false, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
class QuickAccessSelectPreviousAction extends BaseQuickAccessNavigateAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenSelectPrevious';
|
||||
static readonly LABEL = localize('quickSelectPrevious', "Select Previous in Quick Open");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, false, false, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickAccessSelectNextAction, QuickAccessSelectNextAction.ID, QuickAccessSelectNextAction.LABEL, { primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_N } }, inQuickPickContext, KeybindingWeight.WorkbenchContrib + 50), 'Select Next in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickAccessSelectPreviousAction, QuickAccessSelectPreviousAction.ID, QuickAccessSelectPreviousAction.LABEL, { primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_P } }, inQuickPickContext, KeybindingWeight.WorkbenchContrib + 50), 'Select Previous in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickAccessNavigateNextAction, QuickAccessNavigateNextAction.ID, QuickAccessNavigateNextAction.LABEL), 'Navigate Next in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickAccessNavigatePreviousAction, QuickAccessNavigatePreviousAction.ID, QuickAccessNavigatePreviousAction.LABEL), 'Navigate Previous in Quick Open');
|
||||
|
||||
//#endregion
|
||||
@@ -29,7 +29,7 @@ import { FileKind } from 'vs/platform/files/common/files';
|
||||
import { splitName } from 'vs/base/common/labels';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { inQuickOpenContext, getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen';
|
||||
import { inQuickPickContext, getQuickNavigateHandler } from 'vs/workbench/browser/quickaccess';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
|
||||
export const inRecentFilesPickerContextKey = 'inRecentFilesPicker';
|
||||
@@ -165,7 +165,7 @@ export class OpenRecentAction extends BaseOpenRecentAction {
|
||||
}
|
||||
}
|
||||
|
||||
class QuickOpenRecentAction extends BaseOpenRecentAction {
|
||||
class QuickPickRecentAction extends BaseOpenRecentAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenRecent';
|
||||
static readonly LABEL = nls.localize('quickOpenRecent', "Quick Open Recent...");
|
||||
@@ -270,7 +270,7 @@ const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActio
|
||||
|
||||
const fileCategory = nls.localize('file', "File");
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NewWindowAction, NewWindowAction.ID, NewWindowAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_N }), 'New Window');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenRecentAction, QuickOpenRecentAction.ID, QuickOpenRecentAction.LABEL), 'File: Quick Open Recent...', fileCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickPickRecentAction, QuickPickRecentAction.ID, QuickPickRecentAction.LABEL), 'File: Quick Open Recent...', fileCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', fileCategory);
|
||||
|
||||
const viewCategory = nls.localize('view', "View");
|
||||
@@ -284,23 +284,23 @@ registry.registerWorkbenchAction(SyncActionDescriptor.create(ShowAboutDialogActi
|
||||
|
||||
// --- Commands/Keybindings Registration
|
||||
|
||||
const recentFilesPickerContext = ContextKeyExpr.and(inQuickOpenContext, ContextKeyExpr.has(inRecentFilesPickerContextKey));
|
||||
const recentFilesPickerContext = ContextKeyExpr.and(inQuickPickContext, ContextKeyExpr.has(inRecentFilesPickerContextKey));
|
||||
|
||||
const quickOpenNavigateNextInRecentFilesPickerId = 'workbench.action.quickOpenNavigateNextInRecentFilesPicker';
|
||||
const quickPickNavigateNextInRecentFilesPickerId = 'workbench.action.quickOpenNavigateNextInRecentFilesPicker';
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: quickOpenNavigateNextInRecentFilesPickerId,
|
||||
id: quickPickNavigateNextInRecentFilesPickerId,
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
handler: getQuickNavigateHandler(quickOpenNavigateNextInRecentFilesPickerId, true),
|
||||
handler: getQuickNavigateHandler(quickPickNavigateNextInRecentFilesPickerId, true),
|
||||
when: recentFilesPickerContext,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_R,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R }
|
||||
});
|
||||
|
||||
const quickOpenNavigatePreviousInRecentFilesPicker = 'workbench.action.quickOpenNavigatePreviousInRecentFilesPicker';
|
||||
const quickPickNavigatePreviousInRecentFilesPicker = 'workbench.action.quickOpenNavigatePreviousInRecentFilesPicker';
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: quickOpenNavigatePreviousInRecentFilesPicker,
|
||||
id: quickPickNavigatePreviousInRecentFilesPicker,
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
handler: getQuickNavigateHandler(quickOpenNavigatePreviousInRecentFilesPicker, false),
|
||||
handler: getQuickNavigateHandler(quickPickNavigatePreviousInRecentFilesPicker, false),
|
||||
when: recentFilesPickerContext,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_R,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_R }
|
||||
|
||||
@@ -206,7 +206,12 @@ export class WorkbenchContextKeysHandler extends Disposable {
|
||||
|
||||
if (activeEditorPane) {
|
||||
this.activeEditorContext.set(activeEditorPane.getId());
|
||||
this.activeEditorIsReadonly.set(activeEditorPane.input.isReadonly());
|
||||
try {
|
||||
this.activeEditorIsReadonly.set(activeEditorPane.input.isReadonly());
|
||||
} catch (error) {
|
||||
// TODO@ben for https://github.com/microsoft/vscode/issues/93224
|
||||
throw new Error(`${error.message}: editor id ${activeEditorPane.getId()}`);
|
||||
}
|
||||
} else {
|
||||
this.activeEditorContext.reset();
|
||||
this.activeEditorIsReadonly.reset();
|
||||
|
||||
@@ -223,9 +223,7 @@ body.web {
|
||||
.monaco-workbench [tabindex="-1"]:active,
|
||||
.monaco-workbench select:active,
|
||||
.monaco-workbench input[type="button"]:active,
|
||||
.monaco-workbench input[type="checkbox"]:active,
|
||||
.monaco-workbench .monaco-tree .monaco-tree-row
|
||||
.monaco-workbench .monaco-tree.focused.no-focused-item:active:before {
|
||||
.monaco-workbench input[type="checkbox"]:active {
|
||||
outline: 0 !important; /* fixes some flashing outlines from showing up when clicking */
|
||||
}
|
||||
|
||||
@@ -233,12 +231,6 @@ body.web {
|
||||
border-color: transparent; /* outline is a square, but border has a radius, so we avoid this glitch when focused (https://github.com/Microsoft/vscode/issues/26045) */
|
||||
}
|
||||
|
||||
.monaco-workbench .monaco-tree.focused .monaco-tree-row.focused [tabindex="0"]:focus {
|
||||
outline-width: 1px; /* higher contrast color for focusable elements in a row that shows focus feedback */
|
||||
outline-style: solid;
|
||||
}
|
||||
|
||||
.monaco-workbench .monaco-tree.focused.no-focused-item:focus:before,
|
||||
.monaco-workbench .monaco-list:not(.element-focused):focus:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -267,7 +259,6 @@ body.web {
|
||||
outline: 0 !important; /* outline is not going well with decoration */
|
||||
}
|
||||
|
||||
.monaco-workbench .monaco-tree.focused:focus,
|
||||
.monaco-workbench .monaco-list:focus {
|
||||
outline: 0 !important; /* tree indicates focus not via outline but through the focused item */
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ import { getMenuBarVisibility } from 'vs/platform/windows/common/windows';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
import { getUserDataSyncStore } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
|
||||
interface IPlaceholderViewlet {
|
||||
id: string;
|
||||
@@ -109,7 +111,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IWorkbenchEnvironmentService workbenchEnvironmentService: IWorkbenchEnvironmentService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
|
||||
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService,
|
||||
@IProductService private readonly productService: IProductService
|
||||
) {
|
||||
super(Parts.ACTIVITYBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
|
||||
this.migrateFromOldCachedViewletsValue();
|
||||
@@ -395,13 +398,16 @@ export class ActivitybarPart extends Part implements IActivityBarService {
|
||||
cssClass: 'codicon-settings-gear'
|
||||
});
|
||||
|
||||
const profileAction = new ActivityAction({
|
||||
id: 'workbench.actions.accounts',
|
||||
name: nls.localize('accounts', "Accounts"),
|
||||
cssClass: 'codicon-account'
|
||||
});
|
||||
if (getUserDataSyncStore(this.productService, this.configurationService)) {
|
||||
const profileAction = new ActivityAction({
|
||||
id: 'workbench.actions.accounts',
|
||||
name: nls.localize('accounts', "Accounts"),
|
||||
cssClass: 'codicon-account'
|
||||
});
|
||||
|
||||
this.globalActivityActionBar.push(profileAction);
|
||||
}
|
||||
|
||||
this.globalActivityActionBar.push(profileAction);
|
||||
this.globalActivityActionBar.push(this.globalActivityAction);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,8 @@ import * as strings from 'vs/base/common/strings';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { IActionViewItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IActionViewItem, ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { prepareActions } from 'vs/workbench/browser/actions';
|
||||
import { IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
|
||||
import { Part, IPartOptions } from 'vs/workbench/browser/part';
|
||||
import { Composite, CompositeRegistry } from 'vs/workbench/browser/composite';
|
||||
|
||||
@@ -13,7 +13,7 @@ import { Extensions, IConfigurationRegistry, ConfigurationScope } from 'vs/platf
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { GroupIdentifier } from 'vs/workbench/common/editor';
|
||||
import { GroupIdentifier, IEditorPartOptions } from 'vs/workbench/common/editor';
|
||||
|
||||
export const IBreadcrumbsService = createDecorator<IBreadcrumbsService>('IEditorBreadcrumbsService');
|
||||
|
||||
@@ -72,6 +72,7 @@ export abstract class BreadcrumbsConfig<T> {
|
||||
static readonly SymbolPath = BreadcrumbsConfig._stub<'on' | 'off' | 'last'>('breadcrumbs.symbolPath');
|
||||
static readonly SymbolSortOrder = BreadcrumbsConfig._stub<'position' | 'name' | 'type'>('breadcrumbs.symbolSortOrder');
|
||||
static readonly Icons = BreadcrumbsConfig._stub<boolean>('breadcrumbs.icons');
|
||||
static readonly TitleScrollbarSizing = BreadcrumbsConfig._stub<IEditorPartOptions['titleScrollbarSizing']>('workbench.editor.titleScrollbarSizing');
|
||||
|
||||
static readonly FileExcludes = BreadcrumbsConfig._stub<glob.IExpression>('files.exclude');
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import { FileKind, IFileService, IFileStat } from 'vs/platform/files/common/file
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IListService, WorkbenchListFocusContextKey } from 'vs/platform/list/browser/listService';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { ColorIdentifier, ColorFunction } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { attachBreadcrumbsStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
@@ -38,7 +38,7 @@ import { ResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { BreadcrumbsConfig, IBreadcrumbsService } from 'vs/workbench/browser/parts/editor/breadcrumbs';
|
||||
import { BreadcrumbElement, EditorBreadcrumbsModel, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel';
|
||||
import { BreadcrumbsPicker, createBreadcrumbsPicker } from 'vs/workbench/browser/parts/editor/breadcrumbsPicker';
|
||||
import { SideBySideEditorInput } from 'vs/workbench/common/editor';
|
||||
import { SideBySideEditorInput, IEditorPartOptions } from 'vs/workbench/common/editor';
|
||||
import { ACTIVE_GROUP, ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
@@ -134,6 +134,11 @@ export class BreadcrumbsControl {
|
||||
|
||||
static readonly HEIGHT = 22;
|
||||
|
||||
private static readonly SCROLLBAR_SIZES = {
|
||||
default: 3,
|
||||
large: 8
|
||||
};
|
||||
|
||||
static readonly Payload_Reveal = {};
|
||||
static readonly Payload_RevealAside = {};
|
||||
static readonly Payload_Pick = {};
|
||||
@@ -148,6 +153,7 @@ export class BreadcrumbsControl {
|
||||
|
||||
private readonly _cfUseQuickPick: BreadcrumbsConfig<boolean>;
|
||||
private readonly _cfShowIcons: BreadcrumbsConfig<boolean>;
|
||||
private readonly _cfTitleScrollbarSizing: BreadcrumbsConfig<IEditorPartOptions['titleScrollbarSizing']>;
|
||||
|
||||
readonly domNode: HTMLDivElement;
|
||||
private readonly _widget: BreadcrumbsWidget;
|
||||
@@ -168,7 +174,7 @@ export class BreadcrumbsControl {
|
||||
@IWorkspaceContextService private readonly _workspaceService: IWorkspaceContextService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IThemeService private readonly _themeService: IThemeService,
|
||||
@IQuickOpenService private readonly _quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService private readonly _quickInputService: IQuickInputService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@ITextResourceConfigurationService private readonly _textResourceConfigurationService: ITextResourceConfigurationService,
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
@@ -180,7 +186,12 @@ export class BreadcrumbsControl {
|
||||
dom.addClass(this.domNode, 'breadcrumbs-control');
|
||||
dom.append(container, this.domNode);
|
||||
|
||||
this._widget = new BreadcrumbsWidget(this.domNode);
|
||||
this._cfUseQuickPick = BreadcrumbsConfig.UseQuickPick.bindTo(_configurationService);
|
||||
this._cfShowIcons = BreadcrumbsConfig.Icons.bindTo(_configurationService);
|
||||
this._cfTitleScrollbarSizing = BreadcrumbsConfig.TitleScrollbarSizing.bindTo(_configurationService);
|
||||
|
||||
const sizing = this._cfTitleScrollbarSizing.getValue() ?? 'default';
|
||||
this._widget = new BreadcrumbsWidget(this.domNode, BreadcrumbsControl.SCROLLBAR_SIZES[sizing]);
|
||||
this._widget.onDidSelectItem(this._onSelectEvent, this, this._disposables);
|
||||
this._widget.onDidFocusItem(this._onFocusEvent, this, this._disposables);
|
||||
this._widget.onDidChangeFocus(this._updateCkBreadcrumbsActive, this, this._disposables);
|
||||
@@ -190,9 +201,6 @@ export class BreadcrumbsControl {
|
||||
this._ckBreadcrumbsVisible = BreadcrumbsControl.CK_BreadcrumbsVisible.bindTo(this._contextKeyService);
|
||||
this._ckBreadcrumbsActive = BreadcrumbsControl.CK_BreadcrumbsActive.bindTo(this._contextKeyService);
|
||||
|
||||
this._cfUseQuickPick = BreadcrumbsConfig.UseQuickPick.bindTo(_configurationService);
|
||||
this._cfShowIcons = BreadcrumbsConfig.Icons.bindTo(_configurationService);
|
||||
|
||||
this._disposables.add(breadcrumbsService.register(this._editorGroup.id, this._widget));
|
||||
}
|
||||
|
||||
@@ -277,6 +285,14 @@ export class BreadcrumbsControl {
|
||||
this._breadcrumbsDisposables.add(listener);
|
||||
this._breadcrumbsDisposables.add(configListener);
|
||||
|
||||
const updateScrollbarSizing = () => {
|
||||
const sizing = this._cfTitleScrollbarSizing.getValue() ?? 'default';
|
||||
this._widget.setHorizontalScrollbarSize(BreadcrumbsControl.SCROLLBAR_SIZES[sizing]);
|
||||
};
|
||||
updateScrollbarSizing();
|
||||
const updateScrollbarSizeListener = this._cfTitleScrollbarSizing.onDidChange(updateScrollbarSizing);
|
||||
this._breadcrumbsDisposables.add(updateScrollbarSizeListener);
|
||||
|
||||
// close picker on hide/update
|
||||
this._breadcrumbsDisposables.add({
|
||||
dispose: () => {
|
||||
@@ -343,7 +359,7 @@ export class BreadcrumbsControl {
|
||||
// using quick pick
|
||||
this._widget.setFocused(undefined);
|
||||
this._widget.setSelection(undefined);
|
||||
this._quickOpenService.show(element instanceof TreeElement ? '@' : '');
|
||||
this._quickInputService.quickAccess.show(element instanceof TreeElement ? '@' : '');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import * as nls from 'vs/nls';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { IEditorQuickOpenEntry, IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
|
||||
import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
|
||||
import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, EditorPinnedContext, EditorGroupEditorsCountContext } from 'vs/workbench/common/editor';
|
||||
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
|
||||
@@ -21,15 +19,14 @@ import { SUPPORTED_ENCODINGS } from 'vs/workbench/services/textfile/common/textf
|
||||
import { BinaryResourceDiffEditor } from 'vs/workbench/browser/parts/editor/binaryDiffEditor';
|
||||
import { ChangeEncodingAction, ChangeEOLAction, ChangeModeAction, EditorStatus } from 'vs/workbench/browser/parts/editor/editorStatus';
|
||||
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
|
||||
import { Scope, IActionBarRegistry, Extensions as ActionBarExtensions, ActionBarContributor } from 'vs/workbench/browser/actions';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId, IMenuItem } from 'vs/platform/actions/common/actions';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import {
|
||||
CloseEditorsInOtherGroupsAction, CloseAllEditorsAction, MoveGroupLeftAction, MoveGroupRightAction, SplitEditorAction, JoinTwoGroupsAction, OpenToSideFromQuickOpenAction, RevertAndCloseEditorAction,
|
||||
CloseEditorsInOtherGroupsAction, CloseAllEditorsAction, MoveGroupLeftAction, MoveGroupRightAction, SplitEditorAction, JoinTwoGroupsAction, RevertAndCloseEditorAction,
|
||||
NavigateBetweenGroupsAction, FocusActiveGroupAction, FocusFirstGroupAction, ResetGroupSizesAction, MaximizeGroupAction, MinimizeOtherGroupsAction, FocusPreviousGroup, FocusNextGroup,
|
||||
toEditorQuickOpenEntry, CloseLeftEditorsInGroupAction, OpenNextEditor, OpenPreviousEditor, NavigateBackwardsAction, NavigateForwardAction, NavigateLastAction, ReopenClosedEditorAction,
|
||||
QuickOpenPreviousRecentlyUsedEditorInGroupAction, QuickOpenPreviousEditorFromHistoryAction, ShowAllEditorsByAppearanceAction, ClearEditorHistoryAction, MoveEditorRightInGroupAction, OpenNextEditorInGroup,
|
||||
CloseLeftEditorsInGroupAction, OpenNextEditor, OpenPreviousEditor, NavigateBackwardsAction, NavigateForwardAction, NavigateLastAction, ReopenClosedEditorAction,
|
||||
QuickAccessPreviousRecentlyUsedEditorInGroupAction, QuickAccessPreviousEditorFromHistoryAction, ShowAllEditorsByAppearanceAction, ClearEditorHistoryAction, MoveEditorRightInGroupAction, OpenNextEditorInGroup,
|
||||
OpenPreviousEditorInGroup, OpenNextRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorAction, MoveEditorToPreviousGroupAction,
|
||||
MoveEditorToNextGroupAction, MoveEditorToFirstGroupAction, MoveEditorLeftInGroupAction, ClearRecentFilesAction, OpenLastEditorInGroup,
|
||||
ShowEditorsInActiveGroupByMostRecentlyUsedAction, MoveEditorToLastGroupAction, OpenFirstEditorInGroup, MoveGroupUpAction, MoveGroupDownAction, FocusLastGroupAction, SplitEditorLeftAction, SplitEditorRightAction,
|
||||
@@ -37,16 +34,14 @@ import {
|
||||
JoinAllGroupsAction, FocusLeftGroup, FocusAboveGroup, FocusRightGroup, FocusBelowGroup, EditorLayoutSingleAction, EditorLayoutTwoColumnsAction, EditorLayoutThreeColumnsAction, EditorLayoutTwoByTwoGridAction,
|
||||
EditorLayoutTwoRowsAction, EditorLayoutThreeRowsAction, EditorLayoutTwoColumnsBottomAction, EditorLayoutTwoRowsRightAction, NewEditorGroupLeftAction, NewEditorGroupRightAction,
|
||||
NewEditorGroupAboveAction, NewEditorGroupBelowAction, SplitEditorOrthogonalAction, CloseEditorInAllGroupsAction, NavigateToLastEditLocationAction, ToggleGroupSizesAction, ShowAllEditorsByMostRecentlyUsedAction,
|
||||
QuickOpenPreviousRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorInGroupAction, OpenNextRecentlyUsedEditorInGroupAction, QuickOpenNextRecentlyUsedEditorAction as QuickOpenLeastRecentlyUsedEditorAction,
|
||||
QuickOpenLeastRecentlyUsedEditorInGroupAction
|
||||
QuickAccessPreviousRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorInGroupAction, OpenNextRecentlyUsedEditorInGroupAction, QuickAccessLeastRecentlyUsedEditorAction, QuickAccessLeastRecentlyUsedEditorInGroupAction
|
||||
} from 'vs/workbench/browser/parts/editor/editorActions';
|
||||
import * as editorCommands from 'vs/workbench/browser/parts/editor/editorCommands';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { getQuickNavigateHandler, inQuickOpenContext } from 'vs/workbench/browser/parts/quickopen/quickopen';
|
||||
import { inQuickPickContext, getQuickNavigateHandler } from 'vs/workbench/browser/quickaccess';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { ContextKeyExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { AllEditorsByAppearancePicker, ActiveGroupEditorsByMostRecentlyUsedPicker, AllEditorsByMostRecentlyUsedPicker } from 'vs/workbench/browser/parts/editor/editorPicker';
|
||||
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
import { OpenWorkspaceButtonContribution } from 'vs/workbench/browser/parts/editor/editorWidgets';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
@@ -270,101 +265,10 @@ if (Object.keys(SUPPORTED_ENCODINGS).length > 1) {
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ChangeEncodingAction, ChangeEncodingAction.ID, ChangeEncodingAction.LABEL), 'Change File Encoding');
|
||||
}
|
||||
|
||||
export class QuickOpenActionContributor extends ActionBarContributor {
|
||||
private openToSideActionInstance: OpenToSideFromQuickOpenAction | undefined;
|
||||
|
||||
constructor(@IInstantiationService private readonly instantiationService: IInstantiationService) {
|
||||
super();
|
||||
}
|
||||
|
||||
hasActions(context: unknown): boolean {
|
||||
const entry = this.getEntry(context);
|
||||
|
||||
return !!entry;
|
||||
}
|
||||
|
||||
getActions(context: unknown): ReadonlyArray<IAction> {
|
||||
const actions: Action[] = [];
|
||||
|
||||
const entry = this.getEntry(context);
|
||||
if (entry) {
|
||||
if (!this.openToSideActionInstance) {
|
||||
this.openToSideActionInstance = this.instantiationService.createInstance(OpenToSideFromQuickOpenAction);
|
||||
} else {
|
||||
this.openToSideActionInstance.updateClass();
|
||||
}
|
||||
|
||||
actions.push(this.openToSideActionInstance);
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
private getEntry(context: any): IEditorQuickOpenEntry | null {
|
||||
if (!context || !context.element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return toEditorQuickOpenEntry(context.element);
|
||||
}
|
||||
}
|
||||
|
||||
const actionBarRegistry = Registry.as<IActionBarRegistry>(ActionBarExtensions.Actionbar);
|
||||
actionBarRegistry.registerActionBarContributor(Scope.VIEWER, QuickOpenActionContributor);
|
||||
|
||||
const editorPickerContextKey = 'inEditorsPicker';
|
||||
const editorPickerContext = ContextKeyExpr.and(inQuickOpenContext, ContextKeyExpr.has(editorPickerContextKey));
|
||||
|
||||
Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerQuickOpenHandler(
|
||||
QuickOpenHandlerDescriptor.create(
|
||||
ActiveGroupEditorsByMostRecentlyUsedPicker,
|
||||
ActiveGroupEditorsByMostRecentlyUsedPicker.ID,
|
||||
editorCommands.NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX,
|
||||
editorPickerContextKey,
|
||||
[
|
||||
{
|
||||
prefix: editorCommands.NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX,
|
||||
needsEditor: false,
|
||||
description: nls.localize('groupOnePicker', "Show Editors in Active Group By Most Recently Used")
|
||||
}
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerQuickOpenHandler(
|
||||
QuickOpenHandlerDescriptor.create(
|
||||
AllEditorsByAppearancePicker,
|
||||
AllEditorsByAppearancePicker.ID,
|
||||
editorCommands.NAVIGATE_ALL_EDITORS_BY_APPEARANCE_PREFIX,
|
||||
editorPickerContextKey,
|
||||
[
|
||||
{
|
||||
prefix: editorCommands.NAVIGATE_ALL_EDITORS_BY_APPEARANCE_PREFIX,
|
||||
needsEditor: false,
|
||||
description: nls.localize('allEditorsPicker', "Show All Opened Editors By Appearance")
|
||||
}
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerQuickOpenHandler(
|
||||
QuickOpenHandlerDescriptor.create(
|
||||
AllEditorsByMostRecentlyUsedPicker,
|
||||
AllEditorsByMostRecentlyUsedPicker.ID,
|
||||
editorCommands.NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX,
|
||||
editorPickerContextKey,
|
||||
[
|
||||
{
|
||||
prefix: editorCommands.NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX,
|
||||
needsEditor: false,
|
||||
description: nls.localize('allEditorsPickerByMostRecentlyUsed', "Show All Opened Editors By Most Recently Used")
|
||||
}
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
// Register Editor Quick Access
|
||||
const quickAccessRegistry = Registry.as<IQuickAccessRegistry>(QuickAccessExtensions.Quickaccess);
|
||||
const editorPickerContextKey = 'inEditorsPicker';
|
||||
const editorPickerContext = ContextKeyExpr.and(inQuickPickContext, ContextKeyExpr.has(editorPickerContextKey));
|
||||
|
||||
quickAccessRegistry.registerQuickAccessProvider({
|
||||
ctor: ActiveGroupEditorsByMostRecentlyUsedQuickAccess,
|
||||
@@ -469,29 +373,29 @@ registry.registerWorkbenchAction(SyncActionDescriptor.create(EditorLayoutTwoColu
|
||||
|
||||
// Register Quick Editor Actions including built in quick navigate support for some
|
||||
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenPreviousRecentlyUsedEditorAction, QuickOpenPreviousRecentlyUsedEditorAction.ID, QuickOpenPreviousRecentlyUsedEditorAction.LABEL), 'View: Quick Open Previous Recently Used Editor', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenLeastRecentlyUsedEditorAction, QuickOpenLeastRecentlyUsedEditorAction.ID, QuickOpenLeastRecentlyUsedEditorAction.LABEL), 'View: Quick Open Least Recently Used Editor', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickAccessPreviousRecentlyUsedEditorAction, QuickAccessPreviousRecentlyUsedEditorAction.ID, QuickAccessPreviousRecentlyUsedEditorAction.LABEL), 'View: Quick Open Previous Recently Used Editor', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickAccessLeastRecentlyUsedEditorAction, QuickAccessLeastRecentlyUsedEditorAction.ID, QuickAccessLeastRecentlyUsedEditorAction.LABEL), 'View: Quick Open Least Recently Used Editor', category);
|
||||
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenPreviousRecentlyUsedEditorInGroupAction, QuickOpenPreviousRecentlyUsedEditorInGroupAction.ID, QuickOpenPreviousRecentlyUsedEditorInGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyCode.Tab } }), 'View: Quick Open Previous Recently Used Editor in Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenLeastRecentlyUsedEditorInGroupAction, QuickOpenLeastRecentlyUsedEditorInGroupAction.ID, QuickOpenLeastRecentlyUsedEditorInGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Tab } }), 'View: Quick Open Least Recently Used Editor in Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickAccessPreviousRecentlyUsedEditorInGroupAction, QuickAccessPreviousRecentlyUsedEditorInGroupAction.ID, QuickAccessPreviousRecentlyUsedEditorInGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyCode.Tab } }), 'View: Quick Open Previous Recently Used Editor in Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickAccessLeastRecentlyUsedEditorInGroupAction, QuickAccessLeastRecentlyUsedEditorInGroupAction.ID, QuickAccessLeastRecentlyUsedEditorInGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Tab } }), 'View: Quick Open Least Recently Used Editor in Group', category);
|
||||
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenPreviousEditorFromHistoryAction, QuickOpenPreviousEditorFromHistoryAction.ID, QuickOpenPreviousEditorFromHistoryAction.LABEL), 'Quick Open Previous Editor from History');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickAccessPreviousEditorFromHistoryAction, QuickAccessPreviousEditorFromHistoryAction.ID, QuickAccessPreviousEditorFromHistoryAction.LABEL), 'Quick Open Previous Editor from History');
|
||||
|
||||
const quickOpenNavigateNextInEditorPickerId = 'workbench.action.quickOpenNavigateNextInEditorPicker';
|
||||
const quickAccessNavigateNextInEditorPickerId = 'workbench.action.quickOpenNavigateNextInEditorPicker';
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: quickOpenNavigateNextInEditorPickerId,
|
||||
id: quickAccessNavigateNextInEditorPickerId,
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
handler: getQuickNavigateHandler(quickOpenNavigateNextInEditorPickerId, true),
|
||||
handler: getQuickNavigateHandler(quickAccessNavigateNextInEditorPickerId, true),
|
||||
when: editorPickerContext,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.Tab,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyCode.Tab }
|
||||
});
|
||||
|
||||
const quickOpenNavigatePreviousInEditorPickerId = 'workbench.action.quickOpenNavigatePreviousInEditorPicker';
|
||||
const quickAccessNavigatePreviousInEditorPickerId = 'workbench.action.quickOpenNavigatePreviousInEditorPicker';
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: quickOpenNavigatePreviousInEditorPickerId,
|
||||
id: quickAccessNavigatePreviousInEditorPickerId,
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
handler: getQuickNavigateHandler(quickOpenNavigatePreviousInEditorPickerId, false),
|
||||
handler: getQuickNavigateHandler(quickAccessNavigatePreviousInEditorPickerId, false),
|
||||
when: editorPickerContext,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Tab,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Tab }
|
||||
|
||||
@@ -30,6 +30,7 @@ export const DEFAULT_EDITOR_PART_OPTIONS: IEditorPartOptions = {
|
||||
highlightModifiedTabs: false,
|
||||
tabCloseButton: 'right',
|
||||
tabSizing: 'fit',
|
||||
titleScrollbarSizing: 'default',
|
||||
focusRecentEditorAfterClose: true,
|
||||
showIcons: true,
|
||||
enablePreview: true,
|
||||
|
||||
@@ -5,26 +5,22 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { IEditorInput, EditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection, SaveReason, EditorsOrder, SideBySideEditorInput } from 'vs/workbench/common/editor';
|
||||
import { QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel';
|
||||
import { EditorQuickOpenEntry, EditorQuickOpenEntryGroup, IEditorQuickOpenEntry, QuickOpenAction } from 'vs/workbench/browser/quickopen';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IEditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection, SaveReason, EditorsOrder, SideBySideEditorInput } from 'vs/workbench/common/editor';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { CLOSE_EDITOR_COMMAND_ID, NAVIGATE_ALL_EDITORS_BY_APPEARANCE_PREFIX, MOVE_ACTIVE_EDITOR_COMMAND_ID, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, ActiveEditorMoveArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, mergeAllGroups, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX } from 'vs/workbench/browser/parts/editor/editorCommands';
|
||||
import { CLOSE_EDITOR_COMMAND_ID, MOVE_ACTIVE_EDITOR_COMMAND_ID, ActiveEditorMoveArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, mergeAllGroups } from 'vs/workbench/browser/parts/editor/editorCommands';
|
||||
import { IEditorGroupsService, IEditorGroup, GroupsArrangement, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IFileDialogService, ConfirmResult } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { values } from 'vs/base/common/map';
|
||||
import { ItemActivation } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { ItemActivation, IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { AllEditorsByMostRecentlyUsedQuickAccess, ActiveGroupEditorsByMostRecentlyUsedQuickAccess, AllEditorsByAppearanceQuickAccess } from 'vs/workbench/browser/parts/editor/editorQuickAccess';
|
||||
|
||||
export class ExecuteCommandAction extends Action {
|
||||
|
||||
@@ -390,63 +386,6 @@ export class FocusBelowGroup extends BaseFocusGroupAction {
|
||||
}
|
||||
}
|
||||
|
||||
export class OpenToSideFromQuickOpenAction extends Action {
|
||||
|
||||
static readonly OPEN_TO_SIDE_ID = 'workbench.action.openToSide';
|
||||
static readonly OPEN_TO_SIDE_LABEL = nls.localize('openToSide', "Open to the Side");
|
||||
|
||||
constructor(
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
super(OpenToSideFromQuickOpenAction.OPEN_TO_SIDE_ID, OpenToSideFromQuickOpenAction.OPEN_TO_SIDE_LABEL);
|
||||
|
||||
this.updateClass();
|
||||
}
|
||||
|
||||
updateClass(): void {
|
||||
const preferredDirection = preferredSideBySideGroupDirection(this.configurationService);
|
||||
|
||||
this.class = (preferredDirection === GroupDirection.RIGHT) ? 'codicon-split-horizontal' : 'codicon-split-vertical';
|
||||
}
|
||||
|
||||
async run(context: unknown): Promise<void> {
|
||||
const entry = toEditorQuickOpenEntry(context);
|
||||
if (entry) {
|
||||
const input = entry.getInput();
|
||||
if (input) {
|
||||
if (input instanceof EditorInput) {
|
||||
await this.editorService.openEditor(input, entry.getOptions(), SIDE_GROUP);
|
||||
return;
|
||||
}
|
||||
|
||||
const resourceEditorInput = input as IResourceEditorInput;
|
||||
resourceEditorInput.options = mixin(resourceEditorInput.options, entry.getOptions());
|
||||
|
||||
await this.editorService.openEditor(resourceEditorInput, SIDE_GROUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function toEditorQuickOpenEntry(element: unknown): IEditorQuickOpenEntry | null {
|
||||
|
||||
// QuickOpenEntryGroup
|
||||
if (element instanceof QuickOpenEntryGroup) {
|
||||
const group = element;
|
||||
if (group.getEntry()) {
|
||||
element = group.getEntry();
|
||||
}
|
||||
}
|
||||
|
||||
// EditorQuickOpenEntry or EditorQuickOpenEntryGroup both implement IEditorQuickOpenEntry
|
||||
if (element instanceof EditorQuickOpenEntry || element instanceof EditorQuickOpenEntryGroup) {
|
||||
return element;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export class CloseEditorAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.closeActiveEditor';
|
||||
@@ -1214,56 +1153,68 @@ export class ClearRecentFilesAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class ShowEditorsInActiveGroupByMostRecentlyUsedAction extends QuickOpenAction {
|
||||
export class ShowEditorsInActiveGroupByMostRecentlyUsedAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.showEditorsInActiveGroup';
|
||||
static readonly LABEL = nls.localize('showEditorsInActiveGroup', "Show Editors in Active Group By Most Recently Used");
|
||||
|
||||
constructor(
|
||||
actionId: string,
|
||||
actionLabel: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService
|
||||
) {
|
||||
super(actionId, actionLabel, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, quickOpenService);
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
this.quickInputService.quickAccess.show(ActiveGroupEditorsByMostRecentlyUsedQuickAccess.PREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
export class ShowAllEditorsByAppearanceAction extends QuickOpenAction {
|
||||
export class ShowAllEditorsByAppearanceAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.showAllEditors';
|
||||
static readonly LABEL = nls.localize('showAllEditors', "Show All Editors By Appearance");
|
||||
|
||||
constructor(
|
||||
actionId: string,
|
||||
actionLabel: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService
|
||||
) {
|
||||
super(actionId, actionLabel, NAVIGATE_ALL_EDITORS_BY_APPEARANCE_PREFIX, quickOpenService);
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
this.quickInputService.quickAccess.show(AllEditorsByAppearanceQuickAccess.PREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
export class ShowAllEditorsByMostRecentlyUsedAction extends QuickOpenAction {
|
||||
export class ShowAllEditorsByMostRecentlyUsedAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.showAllEditorsByMostRecentlyUsed';
|
||||
static readonly LABEL = nls.localize('showAllEditorsByMostRecentlyUsed', "Show All Editors By Most Recently Used");
|
||||
|
||||
constructor(
|
||||
actionId: string,
|
||||
actionLabel: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService
|
||||
) {
|
||||
super(actionId, actionLabel, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, quickOpenService);
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
this.quickInputService.quickAccess.show(AllEditorsByMostRecentlyUsedQuickAccess.PREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
export class BaseQuickOpenEditorAction extends Action {
|
||||
export class BaseQuickAccessEditorAction extends Action {
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
private prefix: string,
|
||||
private itemActivation: ItemActivation | undefined,
|
||||
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label);
|
||||
@@ -1272,14 +1223,14 @@ export class BaseQuickOpenEditorAction extends Action {
|
||||
async run(): Promise<void> {
|
||||
const keybindings = this.keybindingService.lookupKeybindings(this.id);
|
||||
|
||||
this.quickOpenService.show(this.prefix, {
|
||||
this.quickInputService.quickAccess.show(this.prefix, {
|
||||
quickNavigateConfiguration: { keybindings },
|
||||
autoFocus: this.itemActivation === ItemActivation.LAST ? { autoFocusLastEntry: true } : undefined
|
||||
itemActivation: this.itemActivation
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickOpenPreviousRecentlyUsedEditorAction extends BaseQuickOpenEditorAction {
|
||||
export class QuickAccessPreviousRecentlyUsedEditorAction extends BaseQuickAccessEditorAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenPreviousRecentlyUsedEditor';
|
||||
static readonly LABEL = nls.localize('quickOpenPreviousRecentlyUsedEditor', "Quick Open Previous Recently Used Editor");
|
||||
@@ -1287,14 +1238,14 @@ export class QuickOpenPreviousRecentlyUsedEditorAction extends BaseQuickOpenEdit
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, undefined, quickOpenService, keybindingService);
|
||||
super(id, label, AllEditorsByMostRecentlyUsedQuickAccess.PREFIX, undefined, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickOpenNextRecentlyUsedEditorAction extends BaseQuickOpenEditorAction {
|
||||
export class QuickAccessLeastRecentlyUsedEditorAction extends BaseQuickAccessEditorAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenLeastRecentlyUsedEditor';
|
||||
static readonly LABEL = nls.localize('quickOpenLeastRecentlyUsedEditor', "Quick Open Least Recently Used Editor");
|
||||
@@ -1302,14 +1253,14 @@ export class QuickOpenNextRecentlyUsedEditorAction extends BaseQuickOpenEditorAc
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, undefined, quickOpenService, keybindingService);
|
||||
super(id, label, AllEditorsByMostRecentlyUsedQuickAccess.PREFIX, undefined, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickOpenPreviousRecentlyUsedEditorInGroupAction extends BaseQuickOpenEditorAction {
|
||||
export class QuickAccessPreviousRecentlyUsedEditorInGroupAction extends BaseQuickAccessEditorAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenPreviousRecentlyUsedEditorInGroup';
|
||||
static readonly LABEL = nls.localize('quickOpenPreviousRecentlyUsedEditorInGroup', "Quick Open Previous Recently Used Editor in Group");
|
||||
@@ -1317,14 +1268,14 @@ export class QuickOpenPreviousRecentlyUsedEditorInGroupAction extends BaseQuickO
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, undefined, quickOpenService, keybindingService);
|
||||
super(id, label, ActiveGroupEditorsByMostRecentlyUsedQuickAccess.PREFIX, undefined, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickOpenLeastRecentlyUsedEditorInGroupAction extends BaseQuickOpenEditorAction {
|
||||
export class QuickAccessLeastRecentlyUsedEditorInGroupAction extends BaseQuickAccessEditorAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenLeastRecentlyUsedEditorInGroup';
|
||||
static readonly LABEL = nls.localize('quickOpenLeastRecentlyUsedEditorInGroup', "Quick Open Least Recently Used Editor in Group");
|
||||
@@ -1332,14 +1283,14 @@ export class QuickOpenLeastRecentlyUsedEditorInGroupAction extends BaseQuickOpen
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, ItemActivation.LAST, quickOpenService, keybindingService);
|
||||
super(id, label, ActiveGroupEditorsByMostRecentlyUsedQuickAccess.PREFIX, ItemActivation.LAST, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickOpenPreviousEditorFromHistoryAction extends Action {
|
||||
export class QuickAccessPreviousEditorFromHistoryAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.openPreviousEditorFromHistory';
|
||||
static readonly LABEL = nls.localize('navigateEditorHistoryByInput', "Quick Open Previous Editor from History");
|
||||
@@ -1347,7 +1298,7 @@ export class QuickOpenPreviousEditorFromHistoryAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label);
|
||||
@@ -1356,7 +1307,7 @@ export class QuickOpenPreviousEditorFromHistoryAction extends Action {
|
||||
async run(): Promise<void> {
|
||||
const keybindings = this.keybindingService.lookupKeybindings(this.id);
|
||||
|
||||
this.quickOpenService.show(undefined, { quickNavigateConfiguration: { keybindings } });
|
||||
this.quickInputService.quickAccess.show('', { quickNavigateConfiguration: { keybindings } });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor';
|
||||
import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IListService } from 'vs/platform/list/browser/listService';
|
||||
import { List } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { distinct, coalesce } from 'vs/base/common/arrays';
|
||||
@@ -22,6 +22,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands';
|
||||
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { ActiveGroupEditorsByMostRecentlyUsedQuickAccess } from 'vs/workbench/browser/parts/editor/editorQuickAccess';
|
||||
|
||||
export const CLOSE_SAVED_EDITORS_COMMAND_ID = 'workbench.action.closeUnmodifiedEditors';
|
||||
export const CLOSE_EDITORS_IN_GROUP_COMMAND_ID = 'workbench.action.closeEditorsInGroup';
|
||||
@@ -46,10 +47,6 @@ export const SPLIT_EDITOR_DOWN = 'workbench.action.splitEditorDown';
|
||||
export const SPLIT_EDITOR_LEFT = 'workbench.action.splitEditorLeft';
|
||||
export const SPLIT_EDITOR_RIGHT = 'workbench.action.splitEditorRight';
|
||||
|
||||
export const NAVIGATE_ALL_EDITORS_BY_APPEARANCE_PREFIX = 'edt ';
|
||||
export const NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX = 'edt mru ';
|
||||
export const NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX = 'edt active ';
|
||||
|
||||
export const OPEN_EDITOR_AT_INDEX_COMMAND_ID = 'workbench.action.openEditorAtIndex';
|
||||
|
||||
export interface ActiveEditorMoveArguments {
|
||||
@@ -652,7 +649,7 @@ function registerCloseEditorCommands() {
|
||||
primary: undefined,
|
||||
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
|
||||
const commandsContext = getCommandsContext(resourceOrContext, context);
|
||||
if (commandsContext && typeof commandsContext.groupId === 'number') {
|
||||
@@ -662,7 +659,7 @@ function registerCloseEditorCommands() {
|
||||
}
|
||||
}
|
||||
|
||||
return quickOpenService.show(NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX);
|
||||
return quickInputService.quickAccess.show(ActiveGroupEditorsByMostRecentlyUsedQuickAccess.PREFIX);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ export interface IOpenEditorResult {
|
||||
|
||||
export class EditorControl extends Disposable {
|
||||
|
||||
get minimumWidth() { return this._activeEditorPane ? this._activeEditorPane.minimumWidth : DEFAULT_EDITOR_MIN_DIMENSIONS.width; }
|
||||
get minimumHeight() { return this._activeEditorPane ? this._activeEditorPane.minimumHeight : DEFAULT_EDITOR_MIN_DIMENSIONS.height; }
|
||||
get maximumWidth() { return this._activeEditorPane ? this._activeEditorPane.maximumWidth : DEFAULT_EDITOR_MAX_DIMENSIONS.width; }
|
||||
get maximumHeight() { return this._activeEditorPane ? this._activeEditorPane.maximumHeight : DEFAULT_EDITOR_MAX_DIMENSIONS.height; }
|
||||
get minimumWidth() { return this._activeEditorPane?.minimumWidth ?? DEFAULT_EDITOR_MIN_DIMENSIONS.width; }
|
||||
get minimumHeight() { return this._activeEditorPane?.minimumHeight ?? DEFAULT_EDITOR_MIN_DIMENSIONS.height; }
|
||||
get maximumWidth() { return this._activeEditorPane?.maximumWidth ?? DEFAULT_EDITOR_MAX_DIMENSIONS.width; }
|
||||
get maximumHeight() { return this._activeEditorPane?.maximumHeight ?? DEFAULT_EDITOR_MAX_DIMENSIONS.height; }
|
||||
|
||||
private readonly _onDidFocus = this._register(new Emitter<void>());
|
||||
readonly onDidFocus = this._onDidFocus.event;
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/editorpicker';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';
|
||||
import { IAutoFocus, Mode, IEntryRunContext, IQuickNavigateConfiguration, IModel } from 'vs/base/parts/quickopen/common/quickOpen';
|
||||
import { QuickOpenModel, QuickOpenEntry, QuickOpenEntryGroup, QuickOpenItemAccessor } from 'vs/base/parts/quickopen/browser/quickOpenModel';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { QuickOpenHandler } from 'vs/workbench/browser/quickopen';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService, IEditorGroup, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { toResource, SideBySideEditor, IEditorInput, EditorsOrder } from 'vs/workbench/common/editor';
|
||||
import { compareItemsByScore, scoreItem, ScorerCache, prepareQuery } from 'vs/base/common/fuzzyScorer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
export class EditorPickerEntry extends QuickOpenEntryGroup {
|
||||
|
||||
constructor(
|
||||
private editor: IEditorInput,
|
||||
public readonly group: IEditorGroup,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IModelService private readonly modelService: IModelService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
getLabelOptions(): IIconLabelValueOptions {
|
||||
return {
|
||||
extraClasses: getIconClasses(this.modelService, this.modeService, this.getResource()),
|
||||
italic: !this.group.isPinned(this.editor)
|
||||
};
|
||||
}
|
||||
|
||||
getLabel(): string {
|
||||
return this.editor.getName();
|
||||
}
|
||||
|
||||
getIcon(): string {
|
||||
return this.editor.isDirty() && !this.editor.isSaving() ? 'codicon codicon-circle-filled' : '';
|
||||
}
|
||||
|
||||
getResource() {
|
||||
return toResource(this.editor, { supportSideBySide: SideBySideEditor.MASTER });
|
||||
}
|
||||
|
||||
getAriaLabel(): string {
|
||||
return nls.localize('entryAriaLabel', "{0}, editor group picker", this.getLabel());
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return this.editor.getDescription();
|
||||
}
|
||||
|
||||
run(mode: Mode, context: IEntryRunContext): boolean {
|
||||
if (mode === Mode.OPEN) {
|
||||
return this.runOpen(context);
|
||||
}
|
||||
|
||||
return super.run(mode, context);
|
||||
}
|
||||
|
||||
private runOpen(context: IEntryRunContext): boolean {
|
||||
this.group.openEditor(this.editor);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class BaseEditorPicker extends QuickOpenHandler {
|
||||
private scorerCache: ScorerCache;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService protected instantiationService: IInstantiationService,
|
||||
@IEditorService protected editorService: IEditorService,
|
||||
@IEditorGroupsService protected editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.scorerCache = Object.create(null);
|
||||
}
|
||||
|
||||
getResults(searchValue: string, token: CancellationToken): Promise<QuickOpenModel | null> {
|
||||
const editorEntries = this.getEditorEntries();
|
||||
if (!editorEntries.length) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
// Prepare search for scoring
|
||||
const query = prepareQuery(searchValue);
|
||||
|
||||
const entries = editorEntries.filter(e => {
|
||||
if (!query.value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const itemScore = scoreItem(e, query, true, QuickOpenItemAccessor, this.scorerCache);
|
||||
if (!itemScore.score) {
|
||||
return false;
|
||||
}
|
||||
|
||||
e.setHighlights(itemScore.labelMatch || [], itemScore.descriptionMatch);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// Sorting
|
||||
if (query.value) {
|
||||
const groups = this.editorGroupService.getGroups(GroupsOrder.GRID_APPEARANCE);
|
||||
entries.sort((e1, e2) => {
|
||||
if (e1.group !== e2.group) {
|
||||
return groups.indexOf(e1.group) - groups.indexOf(e2.group); // older groups first
|
||||
}
|
||||
|
||||
return compareItemsByScore(e1, e2, query, true, QuickOpenItemAccessor, this.scorerCache);
|
||||
});
|
||||
}
|
||||
|
||||
// Grouping (for more than one group)
|
||||
if (this.editorGroupService.count > 1) {
|
||||
let lastGroup: IEditorGroup;
|
||||
entries.forEach(e => {
|
||||
if (!lastGroup || lastGroup !== e.group) {
|
||||
e.setGroupLabel(e.group.label);
|
||||
e.setShowBorder(!!lastGroup);
|
||||
lastGroup = e.group;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve(new QuickOpenModel(entries));
|
||||
}
|
||||
|
||||
onClose(canceled: boolean): void {
|
||||
this.scorerCache = Object.create(null);
|
||||
}
|
||||
|
||||
protected abstract count(): number;
|
||||
|
||||
protected abstract getEditorEntries(): EditorPickerEntry[];
|
||||
|
||||
getAutoFocus(searchValue: string, context: { model: IModel<QuickOpenEntry>, quickNavigateConfiguration?: IQuickNavigateConfiguration }): IAutoFocus {
|
||||
if (searchValue || !context.quickNavigateConfiguration) {
|
||||
return {
|
||||
autoFocusFirstEntry: true
|
||||
};
|
||||
}
|
||||
|
||||
const isShiftNavigate = (context.quickNavigateConfiguration && context.quickNavigateConfiguration.keybindings.some(k => {
|
||||
const [firstPart, chordPart] = k.getParts();
|
||||
if (chordPart) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return firstPart.shiftKey;
|
||||
}));
|
||||
|
||||
if (isShiftNavigate) {
|
||||
return {
|
||||
autoFocusLastEntry: true
|
||||
};
|
||||
}
|
||||
|
||||
const editors = this.count();
|
||||
return {
|
||||
autoFocusFirstEntry: editors === 1,
|
||||
autoFocusSecondEntry: editors > 1
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class ActiveGroupEditorsByMostRecentlyUsedPicker extends BaseEditorPicker {
|
||||
|
||||
static readonly ID = 'workbench.picker.activeGroupEditorsByMostRecentlyUsed';
|
||||
|
||||
protected count(): number {
|
||||
return this.group.count;
|
||||
}
|
||||
|
||||
protected getEditorEntries(): EditorPickerEntry[] {
|
||||
return this.group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).map(editor => this.instantiationService.createInstance(EditorPickerEntry, editor, this.group));
|
||||
}
|
||||
|
||||
private get group(): IEditorGroup {
|
||||
return this.editorGroupService.activeGroup;
|
||||
}
|
||||
|
||||
getEmptyLabel(searchString: string): string {
|
||||
if (searchString) {
|
||||
return nls.localize('noResultsFoundInGroup', "No matching opened editor found in active editor group");
|
||||
}
|
||||
|
||||
return nls.localize('noOpenedEditors', "List of opened editors is currently empty in active editor group");
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class BaseAllEditorsPicker extends BaseEditorPicker {
|
||||
|
||||
constructor(
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IEditorService editorService: IEditorService,
|
||||
@IEditorGroupsService editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(instantiationService, editorService, editorGroupService);
|
||||
}
|
||||
|
||||
protected count(): number {
|
||||
return this.editorService.count;
|
||||
}
|
||||
|
||||
getEmptyLabel(searchString: string): string {
|
||||
if (searchString) {
|
||||
return nls.localize('noResultsFound', "No matching opened editor found");
|
||||
}
|
||||
|
||||
return nls.localize('noOpenedEditorsAllGroups', "List of opened editors is currently empty");
|
||||
}
|
||||
|
||||
getAutoFocus(searchValue: string, context: { model: IModel<QuickOpenEntry>, quickNavigateConfiguration?: IQuickNavigateConfiguration }): IAutoFocus {
|
||||
if (searchValue) {
|
||||
return {
|
||||
autoFocusFirstEntry: true
|
||||
};
|
||||
}
|
||||
|
||||
return super.getAutoFocus(searchValue, context);
|
||||
}
|
||||
}
|
||||
|
||||
export class AllEditorsByAppearancePicker extends BaseAllEditorsPicker {
|
||||
|
||||
static readonly ID = 'workbench.picker.editorsByAppearance';
|
||||
|
||||
protected getEditorEntries(): EditorPickerEntry[] {
|
||||
const entries: EditorPickerEntry[] = [];
|
||||
|
||||
for (const group of this.editorGroupService.getGroups(GroupsOrder.GRID_APPEARANCE)) {
|
||||
for (const editor of group.getEditors(EditorsOrder.SEQUENTIAL)) {
|
||||
entries.push(this.instantiationService.createInstance(EditorPickerEntry, editor, group));
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
|
||||
export class AllEditorsByMostRecentlyUsedPicker extends BaseAllEditorsPicker {
|
||||
|
||||
static readonly ID = 'workbench.picker.editorsByMostRecentlyUsed';
|
||||
|
||||
protected getEditorEntries(): EditorPickerEntry[] {
|
||||
const entries: EditorPickerEntry[] = [];
|
||||
|
||||
for (const { editor, groupId } of this.editorService.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) {
|
||||
entries.push(this.instantiationService.createInstance(EditorPickerEntry, editor, this.editorGroupService.getGroup(groupId)!));
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
@@ -127,10 +127,6 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
|
||||
iconClasses: getIconClasses(this.modelService, this.modeService, resource),
|
||||
italic: !this.editorGroupService.getGroup(groupId)?.isPinned(editor),
|
||||
buttons: (() => {
|
||||
if (this.pickState.isQuickNavigating) {
|
||||
return undefined; // no actions when quick navigating
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
iconClass: isDirty ? 'dirty-editor codicon-circle-filled' : 'codicon-close',
|
||||
|
||||
@@ -1212,7 +1212,7 @@ export class ChangeModeAction extends Action {
|
||||
|
||||
this.configurationService.updateValue(FILES_ASSOCIATIONS_CONFIG, currentAssociations, target);
|
||||
}
|
||||
}, 50 /* quick open is sensitive to being opened so soon after another */);
|
||||
}, 50 /* quick input is sensitive to being opened so soon after another */);
|
||||
}
|
||||
|
||||
private getFakeResource(lang: string): URI | undefined {
|
||||
@@ -1347,7 +1347,7 @@ export class ChangeEncodingAction extends Action {
|
||||
return;
|
||||
}
|
||||
|
||||
await timeout(50); // quick open is sensitive to being opened so soon after another
|
||||
await timeout(50); // quick input is sensitive to being opened so soon after another
|
||||
|
||||
const resource = toResource(activeEditorPane.input, { supportSideBySide: SideBySideEditor.MASTER });
|
||||
if (!resource || (!this.fileService.canHandleResource(resource) && resource.scheme !== Schemas.untitled)) {
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry.editor-preview {
|
||||
font-style: italic;
|
||||
}
|
||||
@@ -88,8 +88,8 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
private onTitleLabelClick(e: MouseEvent): void {
|
||||
EventHelper.stop(e, false);
|
||||
|
||||
// delayed to let the onTitleClick() come first which can cause a focus change which can close quick open
|
||||
setTimeout(() => this.quickOpenService.show());
|
||||
// delayed to let the onTitleClick() come first which can cause a focus change which can close quick access
|
||||
setTimeout(() => this.quickInputService.quickAccess.show());
|
||||
}
|
||||
|
||||
private onTitleDoubleClick(e: MouseEvent): void {
|
||||
@@ -111,10 +111,10 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
}
|
||||
} else {
|
||||
// TODO@rebornix
|
||||
// gesture tap should open the quick open
|
||||
// gesture tap should open the quick access
|
||||
// editorGroupView will focus on the editor again when there are mouse/pointer/touch down events
|
||||
// we need to wait a bit as `GesureEvent.Tap` is generated from `touchstart` and then `touchend` evnets, which are not an atom event.
|
||||
setTimeout(() => this.quickOpenService.show(), 50);
|
||||
setTimeout(() => this.quickInputService.quickAccess.show(), 50);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IMenuService } from 'vs/platform/actions/common/actions';
|
||||
import { TitleControl } from 'vs/workbench/browser/parts/editor/titleControl';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IDisposable, dispose, DisposableStore, combinedDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
@@ -61,6 +61,11 @@ type AugmentedLabel = IEditorInputLabel & { editor: IEditorInput };
|
||||
|
||||
export class TabsTitleControl extends TitleControl {
|
||||
|
||||
private static readonly SCROLLBAR_SIZES = {
|
||||
default: 3,
|
||||
large: 10
|
||||
};
|
||||
|
||||
private titleContainer: HTMLElement | undefined;
|
||||
private tabsContainer: HTMLElement | undefined;
|
||||
private editorToolbarContainer: HTMLElement | undefined;
|
||||
@@ -89,7 +94,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IMenuService menuService: IMenuService,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@@ -97,7 +102,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
@IEditorService private readonly editorService: EditorServiceImpl,
|
||||
@IRemotePathService private readonly remotePathService: IRemotePathService
|
||||
) {
|
||||
super(parent, accessor, group, contextMenuService, instantiationService, contextKeyService, keybindingService, telemetryService, notificationService, menuService, quickOpenService, themeService, extensionService, configurationService, fileService);
|
||||
super(parent, accessor, group, contextMenuService, instantiationService, contextKeyService, keybindingService, telemetryService, notificationService, menuService, quickInputService, themeService, extensionService, configurationService, fileService);
|
||||
|
||||
this.tabResourceLabels = this._register(this.instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER));
|
||||
this.closeOneEditorAction = this._register(this.instantiationService.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL));
|
||||
@@ -108,6 +113,16 @@ export class TabsTitleControl extends TitleControl {
|
||||
(async () => this.path = await this.remotePathService.path)();
|
||||
}
|
||||
|
||||
protected registerListeners(): void {
|
||||
super.registerListeners();
|
||||
|
||||
this._register(this.accessor.onDidEditorPartOptionsChange(e => {
|
||||
if (e.oldPartOptions.titleScrollbarSizing !== e.newPartOptions.titleScrollbarSizing) {
|
||||
this.updateTabsScrollbarSizing();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
protected create(parent: HTMLElement): void {
|
||||
this.titleContainer = parent;
|
||||
|
||||
@@ -148,10 +163,10 @@ export class TabsTitleControl extends TitleControl {
|
||||
private createTabsScrollbar(scrollable: HTMLElement): ScrollableElement {
|
||||
const tabsScrollbar = new ScrollableElement(scrollable, {
|
||||
horizontal: ScrollbarVisibility.Auto,
|
||||
horizontalScrollbarSize: this.getTabsScrollbarSizing(),
|
||||
vertical: ScrollbarVisibility.Hidden,
|
||||
scrollYToX: true,
|
||||
useShadows: false,
|
||||
horizontalScrollbarSize: 3
|
||||
useShadows: false
|
||||
});
|
||||
|
||||
tabsScrollbar.onScroll(e => {
|
||||
@@ -161,6 +176,20 @@ export class TabsTitleControl extends TitleControl {
|
||||
return tabsScrollbar;
|
||||
}
|
||||
|
||||
private updateTabsScrollbarSizing(): void {
|
||||
this.tabsScrollbar?.updateOptions({
|
||||
horizontalScrollbarSize: this.getTabsScrollbarSizing()
|
||||
});
|
||||
}
|
||||
|
||||
private getTabsScrollbarSizing(): number {
|
||||
if (this.accessor.partOptions.titleScrollbarSizing !== 'large') {
|
||||
return TabsTitleControl.SCROLLBAR_SIZES.default;
|
||||
}
|
||||
|
||||
return TabsTitleControl.SCROLLBAR_SIZES.large;
|
||||
}
|
||||
|
||||
private updateBreadcrumbsControl(): void {
|
||||
if (this.breadcrumbsControl && this.breadcrumbsControl.update()) {
|
||||
// relayout when we have a breadcrumbs and when update changed
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { applyDragImage, DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { addDisposableListener, Dimension, EventType } from 'vs/base/browser/dom';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { ActionsOrientation, IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionsOrientation, IActionViewItem, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
@@ -23,11 +23,10 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { listActiveSelectionBackground, listActiveSelectionForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant, Themable } from 'vs/platform/theme/common/themeService';
|
||||
import { prepareActions } from 'vs/workbench/browser/actions';
|
||||
import { DraggedEditorGroupIdentifier, DraggedEditorIdentifier, fillResourceDataTransfers, LocalSelectionTransfer } from 'vs/workbench/browser/dnd';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs';
|
||||
@@ -77,7 +76,7 @@ export abstract class TitleControl extends Themable {
|
||||
// {{SQL CARBON EDIT}} -- need to make the notification service protected
|
||||
@INotificationService protected readonly notificationService: INotificationService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IQuickOpenService protected quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService protected quickInputService: IQuickInputService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IConfigurationService protected configurationService: IConfigurationService,
|
||||
@@ -94,7 +93,7 @@ export abstract class TitleControl extends Themable {
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
protected registerListeners(): void {
|
||||
|
||||
// Update actions toolbar when extension register that may contribute them
|
||||
this._register(this.extensionService.onDidRegisterExtensions(() => this.updateEditorActionsToolbar()));
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.none,
|
||||
.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.none {
|
||||
width: 16px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.dirty {
|
||||
width: 14px;
|
||||
height: 18px;
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { RemoveFromEditorHistoryAction } from 'vs/workbench/browser/parts/quickopen/quickOpenController';
|
||||
import { QuickOpenSelectNextAction, QuickOpenSelectPreviousAction, inQuickOpenContext, getQuickNavigateHandler, QuickOpenNavigateNextAction, QuickOpenNavigatePreviousAction, defaultQuickOpenContext, QUICKOPEN_ACTION_ID, QUICKOPEN_ACION_LABEL } from 'vs/workbench/browser/parts/quickopen/quickopen';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.closeQuickOpen',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: inQuickOpenContext,
|
||||
primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape],
|
||||
handler: accessor => {
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
quickOpenService.close();
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
return quickInputService.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.acceptSelectedQuickOpenItem',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: inQuickOpenContext,
|
||||
primary: 0,
|
||||
handler: accessor => {
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
quickOpenService.accept();
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
return quickInputService.accept();
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.alternativeAcceptSelectedQuickOpenItem',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: inQuickOpenContext,
|
||||
primary: 0,
|
||||
handler: accessor => {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
return quickInputService.accept({ ctrlCmd: true, alt: false });
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.focusQuickOpen',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: inQuickOpenContext,
|
||||
primary: 0,
|
||||
handler: accessor => {
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
quickOpenService.focus();
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
quickInputService.focus();
|
||||
}
|
||||
});
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
|
||||
const globalQuickOpenKeybinding = { primary: KeyMod.CtrlCmd | KeyCode.KEY_P, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_E], mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_P, secondary: undefined } };
|
||||
|
||||
KeybindingsRegistry.registerKeybindingRule({
|
||||
id: QUICKOPEN_ACTION_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: undefined,
|
||||
primary: globalQuickOpenKeybinding.primary,
|
||||
secondary: globalQuickOpenKeybinding.secondary,
|
||||
mac: globalQuickOpenKeybinding.mac
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
command: { id: QUICKOPEN_ACTION_ID, title: { value: QUICKOPEN_ACION_LABEL, original: 'Go to File...' } }
|
||||
});
|
||||
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenSelectNextAction, QuickOpenSelectNextAction.ID, QuickOpenSelectNextAction.LABEL, { primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_N } }, inQuickOpenContext, KeybindingWeight.WorkbenchContrib + 50), 'Select Next in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenSelectPreviousAction, QuickOpenSelectPreviousAction.ID, QuickOpenSelectPreviousAction.LABEL, { primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_P } }, inQuickOpenContext, KeybindingWeight.WorkbenchContrib + 50), 'Select Previous in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenNavigateNextAction, QuickOpenNavigateNextAction.ID, QuickOpenNavigateNextAction.LABEL), 'Navigate Next in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenNavigatePreviousAction, QuickOpenNavigatePreviousAction.ID, QuickOpenNavigatePreviousAction.LABEL), 'Navigate Previous in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(RemoveFromEditorHistoryAction, RemoveFromEditorHistoryAction.ID, RemoveFromEditorHistoryAction.LABEL), 'Remove From History');
|
||||
|
||||
const quickOpenNavigateNextInFilePickerId = 'workbench.action.quickOpenNavigateNextInFilePicker';
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: quickOpenNavigateNextInFilePickerId,
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
handler: getQuickNavigateHandler(quickOpenNavigateNextInFilePickerId, true),
|
||||
when: defaultQuickOpenContext,
|
||||
primary: globalQuickOpenKeybinding.primary,
|
||||
secondary: globalQuickOpenKeybinding.secondary,
|
||||
mac: globalQuickOpenKeybinding.mac
|
||||
});
|
||||
|
||||
const quickOpenNavigatePreviousInFilePickerId = 'workbench.action.quickOpenNavigatePreviousInFilePicker';
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: quickOpenNavigatePreviousInFilePickerId,
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
handler: getQuickNavigateHandler(quickOpenNavigatePreviousInFilePickerId, false),
|
||||
when: defaultQuickOpenContext,
|
||||
primary: globalQuickOpenKeybinding.primary | KeyMod.Shift,
|
||||
secondary: [globalQuickOpenKeybinding.secondary[0] | KeyMod.Shift],
|
||||
mac: {
|
||||
primary: globalQuickOpenKeybinding.mac.primary | KeyMod.Shift,
|
||||
secondary: undefined
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.quickPickManyToggle',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: inQuickOpenContext,
|
||||
primary: 0,
|
||||
handler: accessor => {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
quickInputService.toggle();
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.quickInputBack',
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
when: inQuickOpenContext,
|
||||
primary: 0,
|
||||
win: { primary: KeyMod.Alt | KeyCode.LeftArrow },
|
||||
mac: { primary: KeyMod.WinCtrl | KeyCode.US_MINUS },
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.US_MINUS },
|
||||
handler: accessor => {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
quickInputService.back();
|
||||
}
|
||||
});
|
||||
@@ -1,910 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/quickopen';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';
|
||||
import { Mode, IEntryRunContext, IAutoFocus, IQuickNavigateConfiguration, IModel } from 'vs/base/parts/quickopen/common/quickOpen';
|
||||
import { QuickOpenEntry, QuickOpenModel, QuickOpenEntryGroup, QuickOpenItemAccessorClass } from 'vs/base/parts/quickopen/browser/quickOpenModel';
|
||||
import { QuickOpenWidget, HideReason } from 'vs/base/parts/quickopen/browser/quickOpenWidget';
|
||||
import { ContributableActionProvider } from 'vs/workbench/browser/actions';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { EditorInput, IWorkbenchEditorConfiguration, IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { Component } from 'vs/workbench/common/component';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { QuickOpenHandler, QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions, EditorQuickOpenEntry, CLOSE_ON_FOCUS_LOST_CONFIG, SEARCH_EDITOR_HISTORY, PRESERVE_INPUT_CONFIG, ENABLE_EXPERIMENTAL_VERSION_CONFIG } from 'vs/workbench/browser/quickopen';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { IQuickOpenService, IShowOptions } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { quickInputBackground, quickInputForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { attachQuickOpenStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { scoreItem, ScorerCache, compareItemsByScore, prepareQuery } from 'vs/base/common/fuzzyScorer';
|
||||
import { WorkbenchTree } from 'vs/platform/list/browser/listService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { Dimension, addClass } from 'vs/base/browser/dom';
|
||||
import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { IQuickInputService, IQuickPickItem, ItemActivation } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
||||
|
||||
const HELP_PREFIX = '?';
|
||||
|
||||
type ValueCallback<T = any> = (value: T | Promise<T>) => void;
|
||||
|
||||
export class QuickOpenController extends Component implements IQuickOpenService {
|
||||
|
||||
private static readonly MAX_SHORT_RESPONSE_TIME = 500;
|
||||
private static readonly ID = 'workbench.component.quickopen';
|
||||
|
||||
_serviceBrand: undefined;
|
||||
|
||||
private readonly _onShow: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onShow: Event<void> = this._onShow.event;
|
||||
|
||||
private readonly _onHide: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onHide: Event<void> = this._onHide.event;
|
||||
|
||||
private preserveInput: boolean | undefined;
|
||||
private isQuickOpen: boolean | undefined;
|
||||
private lastInputValue: string | undefined;
|
||||
private lastSubmittedInputValue: string | undefined;
|
||||
private quickOpenWidget: QuickOpenWidget | undefined;
|
||||
private mapResolvedHandlersToPrefix: Map<string, Promise<QuickOpenHandler>> = new Map();
|
||||
private mapContextKeyToContext: Map<string, IContextKey<boolean>> = new Map();
|
||||
private handlerOnOpenCalled: Set<string> = new Set();
|
||||
private promisesToCompleteOnHide: ValueCallback[] = [];
|
||||
private previousActiveHandlerDescriptor: QuickOpenHandlerDescriptor | null | undefined;
|
||||
private actionProvider = new ContributableActionProvider();
|
||||
private closeOnFocusLost: boolean | undefined;
|
||||
private searchInEditorHistory: boolean | undefined;
|
||||
private editorHistoryHandler: EditorHistoryHandler;
|
||||
private pendingGetResultsInvocation: CancellationTokenSource | null = null;
|
||||
|
||||
private get useNewExperimentalVersion() {
|
||||
return this.configurationService.getValue(ENABLE_EXPERIMENTAL_VERSION_CONFIG) === true;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService
|
||||
) {
|
||||
super(QuickOpenController.ID, themeService, storageService);
|
||||
|
||||
this.editorHistoryHandler = this.instantiationService.createInstance(EditorHistoryHandler);
|
||||
|
||||
this.updateConfiguration();
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(this.configurationService.onDidChangeConfiguration(() => this.updateConfiguration()));
|
||||
this._register(this.layoutService.onPartVisibilityChange(() => this.positionQuickOpenWidget()));
|
||||
this._register(browser.onDidChangeZoomLevel(() => this.positionQuickOpenWidget()));
|
||||
this._register(this.layoutService.onLayout(dimension => this.layout(dimension)));
|
||||
}
|
||||
|
||||
private updateConfiguration(): void {
|
||||
if (this.environmentService.args['sticky-quickopen']) {
|
||||
this.closeOnFocusLost = false;
|
||||
} else {
|
||||
this.closeOnFocusLost = this.configurationService.getValue(CLOSE_ON_FOCUS_LOST_CONFIG);
|
||||
}
|
||||
this.preserveInput = this.configurationService.getValue(PRESERVE_INPUT_CONFIG);
|
||||
|
||||
this.searchInEditorHistory = this.configurationService.getValue(SEARCH_EDITOR_HISTORY);
|
||||
}
|
||||
|
||||
navigate(next: boolean, quickNavigate?: IQuickNavigateConfiguration): void {
|
||||
if (this.useNewExperimentalVersion) {
|
||||
// already handled
|
||||
} else {
|
||||
if (this.quickOpenWidget) {
|
||||
this.quickOpenWidget.navigate(next, quickNavigate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
accept(): void {
|
||||
if (this.useNewExperimentalVersion) {
|
||||
// already handled
|
||||
} else {
|
||||
if (this.quickOpenWidget && this.quickOpenWidget.isVisible()) {
|
||||
this.quickOpenWidget.accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
if (this.useNewExperimentalVersion) {
|
||||
// already handled
|
||||
} else {
|
||||
if (this.quickOpenWidget && this.quickOpenWidget.isVisible()) {
|
||||
this.quickOpenWidget.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(): void {
|
||||
if (this.useNewExperimentalVersion) {
|
||||
// already handled
|
||||
} else {
|
||||
if (this.quickOpenWidget && this.quickOpenWidget.isVisible()) {
|
||||
this.quickOpenWidget.hide(HideReason.CANCELED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private emitQuickOpenVisibilityChange(isVisible: boolean): void {
|
||||
if (isVisible) {
|
||||
this._onShow.fire();
|
||||
} else {
|
||||
this._onHide.fire();
|
||||
}
|
||||
}
|
||||
|
||||
show(prefix?: string, options?: IShowOptions): Promise<void> {
|
||||
if (this.useNewExperimentalVersion) {
|
||||
this.quickInputService.quickAccess.show(prefix, {
|
||||
quickNavigateConfiguration: options?.quickNavigateConfiguration,
|
||||
itemActivation: (() => {
|
||||
if (options?.autoFocus?.autoFocusSecondEntry) {
|
||||
return ItemActivation.SECOND;
|
||||
}
|
||||
|
||||
if (options?.autoFocus?.autoFocusLastEntry) {
|
||||
return ItemActivation.LAST;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
})()
|
||||
});
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let quickNavigateConfiguration = options ? options.quickNavigateConfiguration : undefined;
|
||||
let inputSelection = options ? options.inputSelection : undefined;
|
||||
let autoFocus = options ? options.autoFocus : undefined;
|
||||
|
||||
const promiseCompletedOnHide = new Promise<void>(c => {
|
||||
this.promisesToCompleteOnHide.push(c);
|
||||
});
|
||||
|
||||
// Telemetry: log that quick open is shown and log the mode
|
||||
const registry = Registry.as<IQuickOpenRegistry>(Extensions.Quickopen);
|
||||
const handlerDescriptor = (prefix ? registry.getQuickOpenHandler(prefix) : undefined) || registry.getDefaultQuickOpenHandler();
|
||||
|
||||
// Trigger onOpen
|
||||
this.resolveHandler(handlerDescriptor);
|
||||
|
||||
// Create upon first open
|
||||
if (!this.quickOpenWidget) {
|
||||
const quickOpenWidget: QuickOpenWidget = this.quickOpenWidget = this._register(new QuickOpenWidget(
|
||||
this.layoutService.container,
|
||||
{
|
||||
onOk: () => this.onOk(),
|
||||
onCancel: () => { /* ignore */ },
|
||||
onType: (value: string) => this.onType(quickOpenWidget, value || ''),
|
||||
onShow: () => this.handleOnShow(),
|
||||
onHide: (reason) => this.handleOnHide(reason),
|
||||
onFocusLost: () => !this.closeOnFocusLost
|
||||
}, {
|
||||
inputPlaceHolder: this.hasHandler(HELP_PREFIX) ? nls.localize('quickOpenInput', "Type '?' to get help on the actions you can take from here") : '',
|
||||
keyboardSupport: false,
|
||||
treeCreator: (container, config, opts) => this.instantiationService.createInstance(WorkbenchTree, container, config, opts)
|
||||
}));
|
||||
this._register(attachQuickOpenStyler(this.quickOpenWidget, this.themeService, { background: quickInputBackground, foreground: quickInputForeground }));
|
||||
|
||||
const quickOpenContainer = this.quickOpenWidget.create();
|
||||
addClass(quickOpenContainer, 'show-file-icons');
|
||||
this.positionQuickOpenWidget();
|
||||
}
|
||||
|
||||
// Layout
|
||||
this.quickOpenWidget.layout(this.layoutService.dimension);
|
||||
|
||||
// Show quick open with prefix or editor history
|
||||
if (!this.quickOpenWidget.isVisible() || quickNavigateConfiguration) {
|
||||
if (prefix) {
|
||||
this.quickOpenWidget.show(prefix, { quickNavigateConfiguration, inputSelection, autoFocus });
|
||||
} else {
|
||||
const editorHistory = this.getEditorHistoryWithGroupLabel();
|
||||
if (editorHistory.getEntries().length < 2) {
|
||||
quickNavigateConfiguration = undefined; // If no entries can be shown, default to normal quick open mode
|
||||
}
|
||||
|
||||
// Compute auto focus
|
||||
if (!autoFocus) {
|
||||
if (!quickNavigateConfiguration) {
|
||||
autoFocus = { autoFocusFirstEntry: true };
|
||||
} else {
|
||||
const autoFocusFirstEntry = this.editorGroupService.activeGroup.count === 0;
|
||||
autoFocus = { autoFocusFirstEntry, autoFocusSecondEntry: !autoFocusFirstEntry };
|
||||
}
|
||||
}
|
||||
|
||||
// Update context
|
||||
const registry = Registry.as<IQuickOpenRegistry>(Extensions.Quickopen);
|
||||
this.setQuickOpenContextKey(registry.getDefaultQuickOpenHandler().contextKey);
|
||||
if (this.preserveInput) {
|
||||
this.quickOpenWidget.show(editorHistory, { value: this.lastSubmittedInputValue, quickNavigateConfiguration, autoFocus, inputSelection });
|
||||
} else {
|
||||
this.quickOpenWidget.show(editorHistory, { quickNavigateConfiguration, autoFocus, inputSelection });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise reset the widget to the prefix that is passed in
|
||||
else {
|
||||
this.quickOpenWidget.show(prefix || '', { inputSelection });
|
||||
}
|
||||
|
||||
return promiseCompletedOnHide;
|
||||
}
|
||||
|
||||
private positionQuickOpenWidget(): void {
|
||||
if (this.quickOpenWidget) {
|
||||
this.quickOpenWidget.getElement().style.top = `${this.layoutService.offset?.top ?? 0}px`;
|
||||
}
|
||||
}
|
||||
|
||||
private handleOnShow(): void {
|
||||
this.emitQuickOpenVisibilityChange(true);
|
||||
}
|
||||
|
||||
private handleOnHide(reason: HideReason): void {
|
||||
|
||||
// Clear state
|
||||
this.previousActiveHandlerDescriptor = null;
|
||||
|
||||
// Cancel pending results calls
|
||||
this.cancelPendingGetResultsInvocation();
|
||||
|
||||
// Pass to handlers
|
||||
this.mapResolvedHandlersToPrefix.forEach((promise, prefix) => {
|
||||
promise.then(handler => {
|
||||
this.handlerOnOpenCalled.delete(prefix);
|
||||
|
||||
handler.onClose(reason === HideReason.CANCELED); // Don't check if onOpen was called to preserve old behaviour for now
|
||||
});
|
||||
});
|
||||
|
||||
// Complete promises that are waiting
|
||||
while (this.promisesToCompleteOnHide.length) {
|
||||
const callback = this.promisesToCompleteOnHide.pop();
|
||||
if (callback) {
|
||||
callback(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (reason !== HideReason.FOCUS_LOST) {
|
||||
this.editorGroupService.activeGroup.focus(); // focus back to editor group unless user clicked somewhere else
|
||||
}
|
||||
|
||||
// Reset context keys
|
||||
this.resetQuickOpenContextKeys();
|
||||
|
||||
// Events
|
||||
this.emitQuickOpenVisibilityChange(false);
|
||||
}
|
||||
|
||||
private cancelPendingGetResultsInvocation(): void {
|
||||
if (this.pendingGetResultsInvocation) {
|
||||
this.pendingGetResultsInvocation.cancel();
|
||||
this.pendingGetResultsInvocation.dispose();
|
||||
this.pendingGetResultsInvocation = null;
|
||||
}
|
||||
}
|
||||
|
||||
private resetQuickOpenContextKeys(): void {
|
||||
this.mapContextKeyToContext.forEach(context => context.reset());
|
||||
}
|
||||
|
||||
private setQuickOpenContextKey(id?: string): void {
|
||||
let key: IContextKey<boolean> | undefined;
|
||||
if (id) {
|
||||
key = this.mapContextKeyToContext.get(id);
|
||||
if (!key) {
|
||||
key = new RawContextKey<boolean>(id, false).bindTo(this.contextKeyService);
|
||||
this.mapContextKeyToContext.set(id, key);
|
||||
}
|
||||
}
|
||||
|
||||
if (key?.get()) {
|
||||
return; // already active context
|
||||
}
|
||||
|
||||
this.resetQuickOpenContextKeys();
|
||||
|
||||
if (key) {
|
||||
key.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
private hasHandler(prefix: string): boolean {
|
||||
return !!Registry.as<IQuickOpenRegistry>(Extensions.Quickopen).getQuickOpenHandler(prefix);
|
||||
}
|
||||
|
||||
private getEditorHistoryWithGroupLabel(): QuickOpenModel {
|
||||
const entries: QuickOpenEntry[] = this.editorHistoryHandler.getResults();
|
||||
|
||||
// Apply label to first entry
|
||||
if (entries.length > 0) {
|
||||
entries[0] = new EditorHistoryEntryGroup(entries[0], nls.localize('historyMatches', "recently opened"), false);
|
||||
}
|
||||
|
||||
return new QuickOpenModel(entries, this.actionProvider);
|
||||
}
|
||||
|
||||
private onOk(): void {
|
||||
if (this.isQuickOpen) {
|
||||
this.lastSubmittedInputValue = this.lastInputValue;
|
||||
}
|
||||
}
|
||||
|
||||
private onType(quickOpenWidget: QuickOpenWidget, value: string): void {
|
||||
|
||||
// cancel any pending get results invocation and create new
|
||||
this.cancelPendingGetResultsInvocation();
|
||||
const pendingResultsInvocationTokenSource = new CancellationTokenSource();
|
||||
const pendingResultsInvocationToken = pendingResultsInvocationTokenSource.token;
|
||||
this.pendingGetResultsInvocation = pendingResultsInvocationTokenSource;
|
||||
|
||||
// look for a handler
|
||||
const registry = Registry.as<IQuickOpenRegistry>(Extensions.Quickopen);
|
||||
const handlerDescriptor = registry.getQuickOpenHandler(value);
|
||||
const defaultHandlerDescriptor = registry.getDefaultQuickOpenHandler();
|
||||
const instantProgress = handlerDescriptor?.instantProgress;
|
||||
const contextKey = handlerDescriptor ? handlerDescriptor.contextKey : defaultHandlerDescriptor.contextKey;
|
||||
|
||||
// Reset Progress
|
||||
if (!instantProgress) {
|
||||
quickOpenWidget.getProgressBar().stop().hide();
|
||||
}
|
||||
|
||||
// Reset Extra Class
|
||||
quickOpenWidget.setExtraClass(null);
|
||||
|
||||
// Update context
|
||||
this.setQuickOpenContextKey(contextKey);
|
||||
|
||||
// Remove leading and trailing whitespace
|
||||
const trimmedValue = strings.trim(value);
|
||||
|
||||
// If no value provided, default to editor history
|
||||
if (!trimmedValue) {
|
||||
|
||||
// Trigger onOpen
|
||||
this.resolveHandler(handlerDescriptor || defaultHandlerDescriptor);
|
||||
|
||||
quickOpenWidget.setInput(this.getEditorHistoryWithGroupLabel(), { autoFocusFirstEntry: true });
|
||||
|
||||
// If quickOpen entered empty we have to clear the prefill-cache
|
||||
this.lastInputValue = '';
|
||||
this.isQuickOpen = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let resultPromise: Promise<void>;
|
||||
let resultPromiseDone = false;
|
||||
|
||||
if (handlerDescriptor) {
|
||||
this.isQuickOpen = false;
|
||||
resultPromise = this.handleSpecificHandler(quickOpenWidget, handlerDescriptor, value, pendingResultsInvocationToken);
|
||||
}
|
||||
|
||||
// Otherwise handle default handlers if no specific handler present
|
||||
else {
|
||||
this.isQuickOpen = true;
|
||||
// Cache the value for prefilling the quickOpen next time is opened
|
||||
this.lastInputValue = trimmedValue;
|
||||
resultPromise = this.handleDefaultHandler(quickOpenWidget, defaultHandlerDescriptor, value, pendingResultsInvocationToken);
|
||||
}
|
||||
|
||||
// Remember as the active one
|
||||
this.previousActiveHandlerDescriptor = handlerDescriptor;
|
||||
|
||||
// Progress if task takes a long time
|
||||
setTimeout(() => {
|
||||
if (!resultPromiseDone && !pendingResultsInvocationToken.isCancellationRequested) {
|
||||
quickOpenWidget.getProgressBar().infinite().show();
|
||||
}
|
||||
}, instantProgress ? 0 : 800);
|
||||
|
||||
// Promise done handling
|
||||
resultPromise.then(() => {
|
||||
resultPromiseDone = true;
|
||||
|
||||
if (!pendingResultsInvocationToken.isCancellationRequested) {
|
||||
quickOpenWidget.getProgressBar().hide();
|
||||
}
|
||||
|
||||
pendingResultsInvocationTokenSource.dispose();
|
||||
}, (error: any) => {
|
||||
resultPromiseDone = true;
|
||||
|
||||
pendingResultsInvocationTokenSource.dispose();
|
||||
|
||||
errors.onUnexpectedError(error);
|
||||
this.notificationService.error(types.isString(error) ? new Error(error) : error);
|
||||
});
|
||||
}
|
||||
|
||||
private async handleDefaultHandler(quickOpenWidget: QuickOpenWidget, handler: QuickOpenHandlerDescriptor, value: string, token: CancellationToken): Promise<void> {
|
||||
|
||||
// Fill in history results if matching and we are configured to search in history
|
||||
let matchingHistoryEntries: QuickOpenEntry[];
|
||||
if (value && !this.searchInEditorHistory) {
|
||||
matchingHistoryEntries = [];
|
||||
} else {
|
||||
matchingHistoryEntries = this.editorHistoryHandler.getResults(value, token);
|
||||
}
|
||||
|
||||
if (matchingHistoryEntries.length > 0) {
|
||||
matchingHistoryEntries[0] = new EditorHistoryEntryGroup(matchingHistoryEntries[0], nls.localize('historyMatches', "recently opened"), false);
|
||||
}
|
||||
|
||||
// Resolve
|
||||
const resolvedHandler = await this.resolveHandler(handler);
|
||||
|
||||
const quickOpenModel = new QuickOpenModel(matchingHistoryEntries, this.actionProvider);
|
||||
|
||||
let inputSet = false;
|
||||
|
||||
// If we have matching entries from history we want to show them directly and not wait for the other results to come in
|
||||
// This also applies when we used to have entries from a previous run and now there are no more history results matching
|
||||
const previousInput = quickOpenWidget.getInput();
|
||||
const wasShowingHistory = previousInput?.entries?.some(e => e instanceof EditorHistoryEntry || e instanceof EditorHistoryEntryGroup);
|
||||
if (wasShowingHistory || matchingHistoryEntries.length > 0) {
|
||||
(async () => {
|
||||
if (resolvedHandler.hasShortResponseTime()) {
|
||||
await timeout(QuickOpenController.MAX_SHORT_RESPONSE_TIME);
|
||||
}
|
||||
|
||||
if (!token.isCancellationRequested && !inputSet) {
|
||||
quickOpenWidget.setInput(quickOpenModel, { autoFocusFirstEntry: true });
|
||||
inputSet = true;
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
// Get results
|
||||
const result = await resolvedHandler.getResults(value, token);
|
||||
if (!token.isCancellationRequested) {
|
||||
|
||||
// now is the time to show the input if we did not have set it before
|
||||
if (!inputSet) {
|
||||
quickOpenWidget.setInput(quickOpenModel, { autoFocusFirstEntry: true });
|
||||
inputSet = true;
|
||||
}
|
||||
|
||||
// merge history and default handler results
|
||||
const handlerResults = result?.entries || [];
|
||||
this.mergeResults(quickOpenWidget, quickOpenModel, handlerResults, types.withNullAsUndefined(resolvedHandler.getGroupLabel()));
|
||||
}
|
||||
}
|
||||
|
||||
private mergeResults(quickOpenWidget: QuickOpenWidget, quickOpenModel: QuickOpenModel, handlerResults: QuickOpenEntry[], groupLabel: string | undefined): void {
|
||||
|
||||
// Remove results already showing by checking for a "resource" property
|
||||
const mapEntryToResource = this.mapEntriesToResource(quickOpenModel);
|
||||
const additionalHandlerResults: QuickOpenEntry[] = [];
|
||||
for (const result of handlerResults) {
|
||||
const resource = result.getResource();
|
||||
|
||||
if (!result.mergeWithEditorHistory() || !resource || !mapEntryToResource[resource.toString()]) {
|
||||
additionalHandlerResults.push(result);
|
||||
}
|
||||
}
|
||||
|
||||
// Show additional handler results below any existing results
|
||||
if (additionalHandlerResults.length > 0) {
|
||||
const autoFocusFirstEntry = (quickOpenModel.getEntries().length === 0); // the user might have selected another entry meanwhile in local history (see https://github.com/Microsoft/vscode/issues/20828)
|
||||
const useTopBorder = quickOpenModel.getEntries().length > 0;
|
||||
additionalHandlerResults[0] = new QuickOpenEntryGroup(additionalHandlerResults[0], groupLabel, useTopBorder);
|
||||
quickOpenModel.addEntries(additionalHandlerResults);
|
||||
quickOpenWidget.refresh(quickOpenModel, { autoFocusFirstEntry });
|
||||
}
|
||||
|
||||
// Otherwise if no results are present (even from histoy) indicate this to the user
|
||||
else if (quickOpenModel.getEntries().length === 0) {
|
||||
quickOpenModel.addEntries([new PlaceholderQuickOpenEntry(nls.localize('noResultsFound1', "No results found"))]);
|
||||
quickOpenWidget.refresh(quickOpenModel, { autoFocusFirstEntry: true });
|
||||
}
|
||||
}
|
||||
|
||||
private async handleSpecificHandler(quickOpenWidget: QuickOpenWidget, handlerDescriptor: QuickOpenHandlerDescriptor, value: string, token: CancellationToken): Promise<void> {
|
||||
const resolvedHandler = await this.resolveHandler(handlerDescriptor);
|
||||
|
||||
// Remove handler prefix from search value
|
||||
value = value.substr(handlerDescriptor.prefix.length);
|
||||
|
||||
// Return early if the handler can not run in the current environment and inform the user
|
||||
const canRun = resolvedHandler.canRun();
|
||||
if (types.isUndefinedOrNull(canRun) || (typeof canRun === 'boolean' && !canRun) || typeof canRun === 'string') {
|
||||
const placeHolderLabel = (typeof canRun === 'string') ? canRun : nls.localize('canNotRunPlaceholder', "This quick open handler can not be used in the current context");
|
||||
|
||||
const model = new QuickOpenModel([new PlaceholderQuickOpenEntry(placeHolderLabel)], this.actionProvider);
|
||||
this.showModel(quickOpenWidget, model, resolvedHandler.getAutoFocus(value, { model, quickNavigateConfiguration: quickOpenWidget.getQuickNavigateConfiguration() }), types.withNullAsUndefined(resolvedHandler.getAriaLabel()));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Support extra class from handler
|
||||
const extraClass = resolvedHandler.getClass();
|
||||
if (extraClass) {
|
||||
quickOpenWidget.setExtraClass(extraClass);
|
||||
}
|
||||
|
||||
// When handlers change, clear the result list first before loading the new results
|
||||
if (this.previousActiveHandlerDescriptor !== handlerDescriptor) {
|
||||
this.clearModel(quickOpenWidget);
|
||||
}
|
||||
|
||||
// Receive Results from Handler and apply
|
||||
const result = await resolvedHandler.getResults(value, token);
|
||||
if (!token.isCancellationRequested) {
|
||||
if (!result || !result.entries.length) {
|
||||
const model = new QuickOpenModel([new PlaceholderQuickOpenEntry(resolvedHandler.getEmptyLabel(value))]);
|
||||
this.showModel(quickOpenWidget, model, resolvedHandler.getAutoFocus(value, { model, quickNavigateConfiguration: quickOpenWidget.getQuickNavigateConfiguration() }), types.withNullAsUndefined(resolvedHandler.getAriaLabel()));
|
||||
} else {
|
||||
this.showModel(quickOpenWidget, result, resolvedHandler.getAutoFocus(value, { model: result, quickNavigateConfiguration: quickOpenWidget.getQuickNavigateConfiguration() }), types.withNullAsUndefined(resolvedHandler.getAriaLabel()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private showModel(quickOpenWidget: QuickOpenWidget, model: IModel<any>, autoFocus?: IAutoFocus, ariaLabel?: string): void {
|
||||
|
||||
// If the given model is already set in the widget, refresh and return early
|
||||
if (quickOpenWidget.getInput() === model) {
|
||||
quickOpenWidget.refresh(model, autoFocus);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise just set it
|
||||
quickOpenWidget.setInput(model, autoFocus, ariaLabel);
|
||||
}
|
||||
|
||||
private clearModel(quickOpenWidget: QuickOpenWidget): void {
|
||||
this.showModel(quickOpenWidget, new QuickOpenModel(), undefined);
|
||||
}
|
||||
|
||||
private mapEntriesToResource(model: QuickOpenModel): { [resource: string]: QuickOpenEntry; } {
|
||||
const entries = model.getEntries();
|
||||
const mapEntryToPath: { [path: string]: QuickOpenEntry; } = {};
|
||||
entries.forEach((entry: QuickOpenEntry) => {
|
||||
const resource = entry.getResource();
|
||||
if (resource) {
|
||||
mapEntryToPath[resource.toString()] = entry;
|
||||
}
|
||||
});
|
||||
|
||||
return mapEntryToPath;
|
||||
}
|
||||
|
||||
private async resolveHandler(handler: QuickOpenHandlerDescriptor): Promise<QuickOpenHandler> {
|
||||
let result = this.doResolveHandler(handler);
|
||||
|
||||
const id = handler.getId();
|
||||
if (!this.handlerOnOpenCalled.has(id)) {
|
||||
const original = result;
|
||||
this.handlerOnOpenCalled.add(id);
|
||||
result = original.then(resolved => {
|
||||
this.mapResolvedHandlersToPrefix.set(id, original);
|
||||
resolved.onOpen();
|
||||
|
||||
return resolved;
|
||||
});
|
||||
|
||||
this.mapResolvedHandlersToPrefix.set(id, result);
|
||||
}
|
||||
|
||||
try {
|
||||
return await result;
|
||||
} catch (error) {
|
||||
this.mapResolvedHandlersToPrefix.delete(id);
|
||||
|
||||
throw new Error(`Unable to instantiate quick open handler ${handler.getId()}: ${JSON.stringify(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
private doResolveHandler(handler: QuickOpenHandlerDescriptor): Promise<QuickOpenHandler> {
|
||||
const id = handler.getId();
|
||||
|
||||
// Return Cached
|
||||
if (this.mapResolvedHandlersToPrefix.has(id)) {
|
||||
return this.mapResolvedHandlersToPrefix.get(id)!;
|
||||
}
|
||||
|
||||
// Otherwise load and create
|
||||
const result = Promise.resolve(handler.instantiate(this.instantiationService));
|
||||
this.mapResolvedHandlersToPrefix.set(id, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): void {
|
||||
if (this.quickOpenWidget) {
|
||||
this.quickOpenWidget.layout(dimension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlaceholderQuickOpenEntry extends QuickOpenEntryGroup {
|
||||
private placeHolderLabel: string;
|
||||
|
||||
constructor(placeHolderLabel: string) {
|
||||
super();
|
||||
|
||||
this.placeHolderLabel = placeHolderLabel;
|
||||
}
|
||||
|
||||
getLabel(): string {
|
||||
return this.placeHolderLabel;
|
||||
}
|
||||
}
|
||||
|
||||
class EditorHistoryHandler {
|
||||
private scorerCache: ScorerCache;
|
||||
|
||||
constructor(
|
||||
@IHistoryService private readonly historyService: IHistoryService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IFileService private readonly fileService: IFileService
|
||||
) {
|
||||
this.scorerCache = Object.create(null);
|
||||
}
|
||||
|
||||
getResults(searchValue?: string, token?: CancellationToken): QuickOpenEntry[] {
|
||||
|
||||
// Massage search for scoring
|
||||
const query = prepareQuery(searchValue || '');
|
||||
|
||||
// Just return all if we are not searching
|
||||
const history = this.historyService.getHistory();
|
||||
if (!query.value) {
|
||||
return history.map(input => this.instantiationService.createInstance(EditorHistoryEntry, input));
|
||||
}
|
||||
|
||||
// Otherwise filter by search value and sort by score. Include matches on description
|
||||
// in case the user is explicitly including path separators.
|
||||
const accessor = query.containsPathSeparator ? MatchOnDescription : DoNotMatchOnDescription;
|
||||
return history
|
||||
|
||||
// For now, only support to match on inputs that provide resource information
|
||||
.filter(input => {
|
||||
let resource: URI | undefined;
|
||||
if (input instanceof EditorInput) {
|
||||
resource = resourceForEditorHistory(input, this.fileService);
|
||||
} else {
|
||||
resource = (input as IResourceEditorInput).resource;
|
||||
}
|
||||
|
||||
return !!resource;
|
||||
})
|
||||
|
||||
// Conver to quick open entries
|
||||
.map(input => this.instantiationService.createInstance(EditorHistoryEntry, input))
|
||||
|
||||
// Make sure the search value is matching
|
||||
.filter(e => {
|
||||
const itemScore = scoreItem(e, query, false, accessor, this.scorerCache);
|
||||
if (!itemScore.score) {
|
||||
return false;
|
||||
}
|
||||
|
||||
e.setHighlights(itemScore.labelMatch || [], itemScore.descriptionMatch);
|
||||
|
||||
return true;
|
||||
})
|
||||
|
||||
// Sort by score and provide a fallback sorter that keeps the
|
||||
// recency of items in case the score for items is the same
|
||||
.sort((e1, e2) => compareItemsByScore(e1, e2, query, false, accessor, this.scorerCache));
|
||||
}
|
||||
}
|
||||
|
||||
class EditorHistoryItemAccessorClass extends QuickOpenItemAccessorClass {
|
||||
|
||||
constructor(private allowMatchOnDescription: boolean) {
|
||||
super();
|
||||
}
|
||||
|
||||
getItemDescription(entry: QuickOpenEntry): string | undefined {
|
||||
return this.allowMatchOnDescription ? entry.getDescription() : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const MatchOnDescription = new EditorHistoryItemAccessorClass(true);
|
||||
const DoNotMatchOnDescription = new EditorHistoryItemAccessorClass(false);
|
||||
|
||||
export class EditorHistoryEntryGroup extends QuickOpenEntryGroup {
|
||||
// Marker class
|
||||
}
|
||||
|
||||
export class EditorHistoryEntry extends EditorQuickOpenEntry {
|
||||
private input: IEditorInput | IResourceEditorInput;
|
||||
private resource: URI | undefined;
|
||||
private label: string;
|
||||
private description?: string;
|
||||
private icon: string;
|
||||
|
||||
constructor(
|
||||
input: IEditorInput | IResourceEditorInput,
|
||||
@IEditorService editorService: IEditorService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@ITextFileService private readonly textFileService: ITextFileService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@ILabelService labelService: ILabelService,
|
||||
@IFileService fileService: IFileService,
|
||||
@IFilesConfigurationService private readonly filesConfigurationService: IFilesConfigurationService
|
||||
) {
|
||||
super(editorService);
|
||||
|
||||
this.input = input;
|
||||
|
||||
if (input instanceof EditorInput) {
|
||||
this.resource = resourceForEditorHistory(input, fileService);
|
||||
this.label = input.getName();
|
||||
this.description = input.getDescription();
|
||||
this.icon = this.getDirtyIndicatorForEditor(input);
|
||||
} else {
|
||||
const resourceEditorInput = input as IResourceEditorInput;
|
||||
this.resource = resourceEditorInput.resource;
|
||||
this.label = resources.basenameOrAuthority(resourceEditorInput.resource);
|
||||
this.description = labelService.getUriLabel(resources.dirname(this.resource), { relative: true });
|
||||
this.icon = this.getDirtyIndicatorForEditor(resourceEditorInput);
|
||||
}
|
||||
}
|
||||
|
||||
private getDirtyIndicatorForEditor(input: EditorInput | IResourceEditorInput): string {
|
||||
let signalDirty = false;
|
||||
if (input instanceof EditorInput) {
|
||||
signalDirty = input.isDirty() && !input.isSaving();
|
||||
} else {
|
||||
signalDirty = this.textFileService.isDirty(input.resource) && this.filesConfigurationService.getAutoSaveMode() !== AutoSaveMode.AFTER_SHORT_DELAY;
|
||||
}
|
||||
|
||||
return signalDirty ? 'codicon codicon-circle-filled' : '';
|
||||
}
|
||||
|
||||
getIcon(): string {
|
||||
return this.icon;
|
||||
}
|
||||
|
||||
getLabel(): string {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
getLabelOptions(): IIconLabelValueOptions {
|
||||
return {
|
||||
extraClasses: getIconClasses(this.modelService, this.modeService, this.resource)
|
||||
};
|
||||
}
|
||||
|
||||
getAriaLabel(): string {
|
||||
return nls.localize('entryAriaLabel', "{0}, recently opened", this.getLabel());
|
||||
}
|
||||
|
||||
getDescription(): string | undefined {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
getResource(): URI | undefined {
|
||||
return this.resource;
|
||||
}
|
||||
|
||||
getInput(): IEditorInput | IResourceEditorInput {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
run(mode: Mode, context: IEntryRunContext): boolean {
|
||||
if (mode === Mode.OPEN) {
|
||||
const sideBySide = !context.quickNavigateConfiguration && (context.keymods.alt || context.keymods.ctrlCmd);
|
||||
const pinned = !this.configurationService.getValue<IWorkbenchEditorConfiguration>().workbench.editor.enablePreviewFromQuickOpen || context.keymods.alt;
|
||||
|
||||
if (this.input instanceof EditorInput) {
|
||||
this.editorService.openEditor(this.input, { pinned }, sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
|
||||
} else {
|
||||
this.editorService.openEditor({ resource: (this.input as IResourceEditorInput).resource, options: { pinned } }, sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.run(mode, context);
|
||||
}
|
||||
}
|
||||
|
||||
function resourceForEditorHistory(input: EditorInput, fileService: IFileService): URI | undefined {
|
||||
const resource = input ? input.resource : undefined;
|
||||
|
||||
// For the editor history we only prefer resources that are either untitled or
|
||||
// can be handled by the file service which indicates they are editable resources.
|
||||
if (resource && (fileService.canHandleResource(resource) || resource.scheme === Schemas.untitled)) {
|
||||
return resource;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export class RemoveFromEditorHistoryAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.removeFromEditorHistory';
|
||||
static readonly LABEL = nls.localize('removeFromEditorHistory', "Remove From History");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IHistoryService private readonly historyService: IHistoryService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
async run(): Promise<any> {
|
||||
interface IHistoryPickEntry extends IQuickPickItem {
|
||||
input: IEditorInput | IResourceEditorInput;
|
||||
}
|
||||
|
||||
const history = this.historyService.getHistory();
|
||||
const picks: IHistoryPickEntry[] = history.map(h => {
|
||||
const entry = this.instantiationService.createInstance(EditorHistoryEntry, h);
|
||||
|
||||
return <IHistoryPickEntry>{
|
||||
input: h,
|
||||
iconClasses: getIconClasses(this.modelService, this.modeService, entry.getResource()),
|
||||
label: entry.getLabel(),
|
||||
description: entry.getDescription()
|
||||
};
|
||||
});
|
||||
|
||||
const pick = await this.quickInputService.pick(picks, { placeHolder: nls.localize('pickHistory', "Select an editor entry to remove from history"), matchOnDescription: true });
|
||||
if (pick) {
|
||||
this.historyService.remove(pick.input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IQuickOpenService, QuickOpenController, true);
|
||||
@@ -1,205 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ContextKeyExpr, RawContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
|
||||
const inQuickOpenKey = 'inQuickOpen';
|
||||
export const InQuickOpenContextKey = new RawContextKey<boolean>(inQuickOpenKey, false);
|
||||
export const inQuickOpenContext = ContextKeyExpr.has(inQuickOpenKey);
|
||||
export const defaultQuickOpenContextKey = 'inFilesPicker';
|
||||
export const defaultQuickOpenContext = ContextKeyExpr.and(inQuickOpenContext, ContextKeyExpr.has(defaultQuickOpenContextKey));
|
||||
|
||||
export const QUICKOPEN_ACTION_ID = 'workbench.action.quickOpen';
|
||||
export const QUICKOPEN_ACION_LABEL = nls.localize('quickOpen', "Go to File...");
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: QUICKOPEN_ACTION_ID,
|
||||
handler: async function (accessor: ServicesAccessor, prefix: string | null = null) {
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
|
||||
await quickOpenService.show(typeof prefix === 'string' ? prefix : undefined);
|
||||
},
|
||||
description: {
|
||||
description: `Quick open`,
|
||||
args: [{
|
||||
name: 'prefix',
|
||||
schema: {
|
||||
'type': 'string'
|
||||
}
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
||||
export const QUICKOPEN_FOCUS_SECONDARY_ACTION_ID = 'workbench.action.quickOpenPreviousEditor';
|
||||
CommandsRegistry.registerCommand(QUICKOPEN_FOCUS_SECONDARY_ACTION_ID, async function (accessor: ServicesAccessor, prefix: string | null = null) {
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
|
||||
await quickOpenService.show(undefined, { autoFocus: { autoFocusSecondEntry: true } });
|
||||
});
|
||||
|
||||
export class BaseQuickOpenNavigateAction extends Action {
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
private next: boolean,
|
||||
private quickNavigate: boolean,
|
||||
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
const keys = this.keybindingService.lookupKeybindings(this.id);
|
||||
const quickNavigate = this.quickNavigate ? { keybindings: keys } : undefined;
|
||||
|
||||
this.quickOpenService.navigate(this.next, quickNavigate);
|
||||
this.quickInputService.navigate(this.next, quickNavigate);
|
||||
}
|
||||
}
|
||||
|
||||
export function getQuickNavigateHandler(id: string, next?: boolean): ICommandHandler {
|
||||
return accessor => {
|
||||
const keybindingService = accessor.get(IKeybindingService);
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
|
||||
const keys = keybindingService.lookupKeybindings(id);
|
||||
const quickNavigate = { keybindings: keys };
|
||||
|
||||
quickOpenService.navigate(!!next, quickNavigate);
|
||||
quickInputService.navigate(!!next, quickNavigate);
|
||||
};
|
||||
}
|
||||
|
||||
export class QuickOpenNavigateNextAction extends BaseQuickOpenNavigateAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenNavigateNext';
|
||||
static readonly LABEL = nls.localize('quickNavigateNext', "Navigate Next in Quick Open");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, true, true, quickOpenService, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickOpenNavigatePreviousAction extends BaseQuickOpenNavigateAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenNavigatePrevious';
|
||||
static readonly LABEL = nls.localize('quickNavigatePrevious', "Navigate Previous in Quick Open");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, false, true, quickOpenService, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickOpenSelectNextAction extends BaseQuickOpenNavigateAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenSelectNext';
|
||||
static readonly LABEL = nls.localize('quickSelectNext', "Select Next in Quick Open");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, true, false, quickOpenService, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickOpenSelectPreviousAction extends BaseQuickOpenNavigateAction {
|
||||
|
||||
static readonly ID = 'workbench.action.quickOpenSelectPrevious';
|
||||
static readonly LABEL = nls.localize('quickSelectPrevious', "Select Previous in Quick Open");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@IKeybindingService keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label, false, false, quickOpenService, quickInputService, keybindingService);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO@Ben delete eventually when quick open is implemented using quick input
|
||||
export class LegacyQuickInputQuickOpenController extends Disposable {
|
||||
|
||||
private readonly inQuickOpenWidgets: Record<string, boolean> = Object.create(null);
|
||||
private readonly inQuickOpenContext = InQuickOpenContextKey.bindTo(this.contextKeyService);
|
||||
|
||||
constructor(
|
||||
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(this.quickOpenService.onShow(() => this.inQuickOpen('quickOpen', true)));
|
||||
this._register(this.quickOpenService.onHide(() => this.inQuickOpen('quickOpen', false)));
|
||||
|
||||
this._register(this.quickOpenService.onShow(() => this.quickInputService.hide(true)));
|
||||
|
||||
this._register(this.quickInputService.onShow(() => {
|
||||
this.quickOpenService.close();
|
||||
this.inQuickOpen('quickInput', true);
|
||||
}));
|
||||
|
||||
this._register(this.quickInputService.onHide(() => {
|
||||
this.inQuickOpen('quickInput', false);
|
||||
}));
|
||||
}
|
||||
|
||||
private inQuickOpen(widget: 'quickInput' | 'quickOpen', open: boolean) {
|
||||
if (open) {
|
||||
this.inQuickOpenWidgets[widget] = true;
|
||||
} else {
|
||||
delete this.inQuickOpenWidgets[widget];
|
||||
}
|
||||
|
||||
if (Object.keys(this.inQuickOpenWidgets).length) {
|
||||
if (!this.inQuickOpenContext.get()) {
|
||||
this.inQuickOpenContext.set(true);
|
||||
}
|
||||
} else {
|
||||
if (this.inQuickOpenContext.get()) {
|
||||
this.inQuickOpenContext.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(LegacyQuickInputQuickOpenController, LifecyclePhase.Ready);
|
||||
@@ -26,7 +26,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { MenuBar } from 'vs/base/browser/ui/menu/menubar';
|
||||
import { MenuBar, IMenuBarOptions } from 'vs/base/browser/ui/menu/menubar';
|
||||
import { SubmenuAction, Direction } from 'vs/base/browser/ui/menu/menu';
|
||||
import { attachMenuStyler } from 'vs/platform/theme/common/styler';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
@@ -510,30 +510,11 @@ export class CustomMenubarControl extends MenubarControl {
|
||||
}
|
||||
|
||||
if (firstTime) {
|
||||
const webActions = [];
|
||||
const webMenu = this.menuService.createMenu(MenuId.WebMenuActions, this.contextKeyService);
|
||||
for (const groups of webMenu.getActions()) {
|
||||
const [, actions] = groups;
|
||||
for (const action of actions) {
|
||||
action.label = mnemonicMenuLabel(this.calculateActionLabel(action));
|
||||
webActions.push(action);
|
||||
}
|
||||
}
|
||||
|
||||
this.menubar = this._register(new MenuBar(
|
||||
this.container, {
|
||||
enableMnemonics: this.currentEnableMenuBarMnemonics,
|
||||
disableAltFocus: this.currentDisableMenuBarAltFocus,
|
||||
visibility: this.currentMenubarVisibility,
|
||||
getKeybinding: (action) => this.keybindingService.lookupKeybinding(action.id),
|
||||
compactMode: this.currentCompactMenuMode
|
||||
}, webActions.length > 0 ? webActions : undefined));
|
||||
this.menubar = this._register(new MenuBar(this.container, this.getMenuBarOptions()));
|
||||
|
||||
this.accessibilityService.alwaysUnderlineAccessKeys().then(val => {
|
||||
this.alwaysOnMnemonics = val;
|
||||
if (this.menubar) {
|
||||
this.menubar.update({ enableMnemonics: this.currentEnableMenuBarMnemonics, disableAltFocus: this.currentDisableMenuBarAltFocus, visibility: this.currentMenubarVisibility, getKeybinding: (action) => this.keybindingService.lookupKeybinding(action.id), alwaysOnMnemonics: this.alwaysOnMnemonics, compactMode: this.currentCompactMenuMode });
|
||||
}
|
||||
this.menubar?.update(this.getMenuBarOptions());
|
||||
});
|
||||
|
||||
this._register(this.menubar.onFocusStateChange(focused => {
|
||||
@@ -559,9 +540,7 @@ export class CustomMenubarControl extends MenubarControl {
|
||||
|
||||
this._register(attachMenuStyler(this.menubar, this.themeService));
|
||||
} else {
|
||||
if (this.menubar) {
|
||||
this.menubar.update({ enableMnemonics: this.currentEnableMenuBarMnemonics, disableAltFocus: this.currentDisableMenuBarAltFocus, visibility: this.currentMenubarVisibility, getKeybinding: (action) => this.keybindingService.lookupKeybinding(action.id), alwaysOnMnemonics: this.alwaysOnMnemonics, compactMode: this.currentCompactMenuMode });
|
||||
}
|
||||
this.menubar?.update(this.getMenuBarOptions());
|
||||
}
|
||||
|
||||
// Update the menu actions
|
||||
@@ -632,6 +611,35 @@ export class CustomMenubarControl extends MenubarControl {
|
||||
}
|
||||
}
|
||||
|
||||
private getMenuBarOptions(): IMenuBarOptions {
|
||||
return {
|
||||
enableMnemonics: this.currentEnableMenuBarMnemonics,
|
||||
disableAltFocus: this.currentDisableMenuBarAltFocus,
|
||||
visibility: this.currentMenubarVisibility,
|
||||
getKeybinding: (action) => this.keybindingService.lookupKeybinding(action.id),
|
||||
alwaysOnMnemonics: this.alwaysOnMnemonics,
|
||||
compactMode: this.currentCompactMenuMode,
|
||||
getCompactMenuActions: () => {
|
||||
if (!isWeb) {
|
||||
return []; // only for web
|
||||
}
|
||||
|
||||
const webNavigationActions: IAction[] = [];
|
||||
const webNavigationMenu = this.menuService.createMenu(MenuId.MenubarWebNavigationMenu, this.contextKeyService);
|
||||
for (const groups of webNavigationMenu.getActions()) {
|
||||
const [, actions] = groups;
|
||||
for (const action of actions) {
|
||||
action.label = mnemonicMenuLabel(this.calculateActionLabel(action));
|
||||
webNavigationActions.push(action);
|
||||
}
|
||||
}
|
||||
webNavigationMenu.dispose();
|
||||
|
||||
return webNavigationActions;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected onDidChangeWindowFocus(hasFocus: boolean): void {
|
||||
super.onDidChangeWindowFocus(hasFocus);
|
||||
|
||||
@@ -694,8 +702,6 @@ export class CustomMenubarControl extends MenubarControl {
|
||||
this.container.style.height = `${dimension.height}px`;
|
||||
}
|
||||
|
||||
if (this.menubar) {
|
||||
this.menubar.update({ enableMnemonics: this.currentEnableMenuBarMnemonics, disableAltFocus: this.currentDisableMenuBarAltFocus, visibility: this.currentMenubarVisibility, getKeybinding: (action) => this.keybindingService.lookupKeybinding(action.id), alwaysOnMnemonics: this.alwaysOnMnemonics, compactMode: this.currentCompactMenuMode });
|
||||
}
|
||||
this.menubar?.update(this.getMenuBarOptions());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,28 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* File icon themeable OLD tree style */
|
||||
.file-icon-themable-tree .monaco-tree-row .content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.file-icon-themable-tree .monaco-tree-row .content::before {
|
||||
background-size: 16px;
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
padding-right: 6px;
|
||||
width: 16px;
|
||||
height: 22px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
.file-icon-themable-tree.align-icons-and-twisties .monaco-tree-row:not(.has-children) .content::before,
|
||||
.file-icon-themable-tree.hide-arrows .monaco-tree-row .content::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* File icons in trees */
|
||||
|
||||
.file-icon-themable-tree.align-icons-and-twisties .monaco-tl-twistie:not(.force-twistie):not(.collapsible),
|
||||
|
||||
@@ -13,9 +13,8 @@ import { append, $, trackFocus, toggleClass, EventType, isAncestor, Dimension, a
|
||||
import { IDisposable, combinedDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { firstIndex } from 'vs/base/common/arrays';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IActionViewItem, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IActionViewItem, ActionsOrientation, Separator, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { prepareActions } from 'vs/workbench/browser/actions';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
|
||||
@@ -3,20 +3,16 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IViewDescriptor, IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IThemeService, IFileIconTheme } from 'vs/platform/theme/common/themeService';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ViewPaneContainer, ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService';
|
||||
import { ITreeConfiguration, ITreeOptions } from 'vs/base/parts/tree/browser/tree';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
@@ -145,30 +141,3 @@ export abstract class FilterViewPaneContainer extends ViewPaneContainer {
|
||||
|
||||
abstract getTitle(): string;
|
||||
}
|
||||
|
||||
export class FileIconThemableWorkbenchTree extends WorkbenchTree {
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
configuration: ITreeConfiguration,
|
||||
options: ITreeOptions,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IListService listService: IListService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IInstantiationService instantiationService: IInstantiationService
|
||||
) {
|
||||
super(container, configuration, { ...options, ...{ showTwistie: false, twistiePixels: 12 } }, contextKeyService, listService, themeService, instantiationService, configurationService);
|
||||
|
||||
DOM.addClass(container, 'file-icon-themable-tree');
|
||||
DOM.addClass(container, 'show-file-icons');
|
||||
|
||||
const onFileIconThemeChange = (fileIconTheme: IFileIconTheme) => {
|
||||
DOM.toggleClass(container, 'align-icons-and-twisties', fileIconTheme.hasFileIcons && !fileIconTheme.hasFolderIcons);
|
||||
DOM.toggleClass(container, 'hide-arrows', fileIconTheme.hidesExplorerArrows === true);
|
||||
};
|
||||
|
||||
this.disposables.push(themeService.onDidFileIconThemeChange(onFileIconThemeChange));
|
||||
onFileIconThemeChange(themeService.getFileIconTheme());
|
||||
}
|
||||
}
|
||||
|
||||
41
src/vs/workbench/browser/quickaccess.ts
Normal file
41
src/vs/workbench/browser/quickaccess.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ICommandHandler } from 'vs/platform/commands/common/commands';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
|
||||
export const inQuickPickContextKeyValue = 'inQuickOpen';
|
||||
export const InQuickPickContextKey = new RawContextKey<boolean>(inQuickPickContextKeyValue, false);
|
||||
export const inQuickPickContext = ContextKeyExpr.has(inQuickPickContextKeyValue);
|
||||
|
||||
export const defaultQuickAccessContextKeyValue = 'inFilesPicker';
|
||||
export const defaultQuickAccessContext = ContextKeyExpr.and(inQuickPickContext, ContextKeyExpr.has(defaultQuickAccessContextKeyValue));
|
||||
|
||||
export interface IWorkbenchQuickAccessConfiguration {
|
||||
workbench: {
|
||||
commandPalette: {
|
||||
history: number;
|
||||
preserveInput: boolean;
|
||||
},
|
||||
quickOpen: {
|
||||
enableExperimentalNewVersion: boolean;
|
||||
preserveInput: boolean;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getQuickNavigateHandler(id: string, next?: boolean): ICommandHandler {
|
||||
return accessor => {
|
||||
const keybindingService = accessor.get(IKeybindingService);
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
|
||||
const keys = keybindingService.lookupKeybindings(id);
|
||||
const quickNavigate = { keybindings: keys };
|
||||
|
||||
quickInputService.navigate(!!next, quickNavigate);
|
||||
};
|
||||
}
|
||||
@@ -1,339 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { mixin, assign } from 'vs/base/common/objects';
|
||||
import { first } from 'vs/base/common/arrays';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
import { isString, assertIsDefined, withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Mode, IEntryRunContext, IAutoFocus, IModel, IQuickNavigateConfiguration } from 'vs/base/parts/quickopen/common/quickOpen';
|
||||
import { QuickOpenEntry, QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel';
|
||||
import { EditorOptions, EditorInput, IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { IResourceEditorInput, IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IConstructorSignature0, IInstantiationService, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
export const CLOSE_ON_FOCUS_LOST_CONFIG = 'workbench.quickOpen.closeOnFocusLost';
|
||||
export const PRESERVE_INPUT_CONFIG = 'workbench.quickOpen.preserveInput';
|
||||
export const ENABLE_EXPERIMENTAL_VERSION_CONFIG = 'workbench.quickOpen.enableExperimentalNewVersion';
|
||||
export const SEARCH_EDITOR_HISTORY = 'search.quickOpen.includeHistory';
|
||||
|
||||
export interface IWorkbenchQuickOpenConfiguration {
|
||||
workbench: {
|
||||
commandPalette: {
|
||||
history: number;
|
||||
preserveInput: boolean;
|
||||
},
|
||||
quickOpen: {
|
||||
enableExperimentalNewVersion: boolean;
|
||||
preserveInput: boolean;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class QuickOpenHandler {
|
||||
|
||||
/**
|
||||
* A quick open handler returns results for a given input string. The resolved promise
|
||||
* returns an instance of quick open model. It is up to the handler to keep and reuse an
|
||||
* instance of the same model across multiple calls. This helps in situations where the user is
|
||||
* narrowing down a search and the model is just filtering some items out.
|
||||
*
|
||||
* As such, returning the same model instance across multiple searches will yield best
|
||||
* results in terms of performance when many items are shown.
|
||||
*/
|
||||
getResults(searchValue: string, token: CancellationToken): Promise<IModel<any> | null> {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ARIA label to apply when this quick open handler is active in quick open.
|
||||
*/
|
||||
getAriaLabel(): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra CSS class name to add to the quick open widget to do custom styling of entries.
|
||||
*/
|
||||
getClass(): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the handler can run in the current environment. Return a string if the handler cannot run but has
|
||||
* a good message to show in this case.
|
||||
*/
|
||||
canRun(): boolean | string {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hints to the outside that this quick open handler typically returns results fast.
|
||||
*/
|
||||
hasShortResponseTime(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the handler wishes the quick open widget to automatically select the first result entry or an entry
|
||||
* based on a specific prefix match.
|
||||
*/
|
||||
getAutoFocus(searchValue: string, context: { model: IModel<QuickOpenEntry>, quickNavigateConfiguration?: IQuickNavigateConfiguration }): IAutoFocus {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates to the handler that the quick open widget has been opened.
|
||||
*/
|
||||
onOpen(): void {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates to the handler that the quick open widget has been closed. Allows to free up any resources as needed.
|
||||
* The parameter canceled indicates if the quick open widget was closed with an entry being run or not.
|
||||
*/
|
||||
onClose(canceled: boolean): void {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to return a label that will be placed to the side of the results from this handler or null if none.
|
||||
*/
|
||||
getGroupLabel(): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to return a label that will be used when there are no results found
|
||||
*/
|
||||
getEmptyLabel(searchString: string): string {
|
||||
if (searchString.length > 0) {
|
||||
return localize('noResultsMatching', "No results matching");
|
||||
}
|
||||
return localize('noResultsFound2', "No results found");
|
||||
}
|
||||
}
|
||||
|
||||
export interface QuickOpenHandlerHelpEntry {
|
||||
prefix: string;
|
||||
description: string;
|
||||
needsEditor: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A lightweight descriptor of a quick open handler.
|
||||
*/
|
||||
export class QuickOpenHandlerDescriptor {
|
||||
prefix: string;
|
||||
description?: string;
|
||||
contextKey?: string;
|
||||
helpEntries?: QuickOpenHandlerHelpEntry[];
|
||||
instantProgress: boolean;
|
||||
|
||||
private id: string;
|
||||
private ctor: IConstructorSignature0<QuickOpenHandler>;
|
||||
|
||||
public static create<Services extends BrandedService[]>(ctor: { new(...services: Services): QuickOpenHandler }, id: string, prefix: string, contextKey: string | undefined, description: string, instantProgress?: boolean): QuickOpenHandlerDescriptor;
|
||||
public static create<Services extends BrandedService[]>(ctor: { new(...services: Services): QuickOpenHandler }, id: string, prefix: string, contextKey: string | undefined, helpEntries: QuickOpenHandlerHelpEntry[], instantProgress?: boolean): QuickOpenHandlerDescriptor;
|
||||
public static create<Services extends BrandedService[]>(ctor: { new(...services: Services): QuickOpenHandler }, id: string, prefix: string, contextKey: string | undefined, param: string | QuickOpenHandlerHelpEntry[], instantProgress: boolean = false): QuickOpenHandlerDescriptor {
|
||||
return new QuickOpenHandlerDescriptor(ctor as IConstructorSignature0<QuickOpenHandler>, id, prefix, contextKey, param, instantProgress);
|
||||
}
|
||||
|
||||
private constructor(ctor: IConstructorSignature0<QuickOpenHandler>, id: string, prefix: string, contextKey: string | undefined, param: string | QuickOpenHandlerHelpEntry[], instantProgress: boolean = false) {
|
||||
this.ctor = ctor;
|
||||
this.id = id;
|
||||
this.prefix = prefix;
|
||||
this.contextKey = contextKey;
|
||||
this.instantProgress = instantProgress;
|
||||
|
||||
if (isString(param)) {
|
||||
this.description = param;
|
||||
} else {
|
||||
this.helpEntries = param;
|
||||
}
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
instantiate(instantiationService: IInstantiationService): QuickOpenHandler {
|
||||
return instantiationService.createInstance(this.ctor);
|
||||
}
|
||||
}
|
||||
|
||||
export const Extensions = {
|
||||
Quickopen: 'workbench.contributions.quickopen'
|
||||
};
|
||||
|
||||
export interface IQuickOpenRegistry {
|
||||
|
||||
/**
|
||||
* Registers a quick open handler to the platform.
|
||||
*/
|
||||
registerQuickOpenHandler(descriptor: QuickOpenHandlerDescriptor): void;
|
||||
|
||||
/**
|
||||
* Registers a default quick open handler to fallback to.
|
||||
*/
|
||||
registerDefaultQuickOpenHandler(descriptor: QuickOpenHandlerDescriptor): void;
|
||||
|
||||
/**
|
||||
* Get all registered quick open handlers
|
||||
*/
|
||||
getQuickOpenHandlers(): QuickOpenHandlerDescriptor[];
|
||||
|
||||
/**
|
||||
* Get a specific quick open handler for a given prefix.
|
||||
*/
|
||||
getQuickOpenHandler(prefix: string): QuickOpenHandlerDescriptor | null;
|
||||
|
||||
/**
|
||||
* Returns the default quick open handler.
|
||||
*/
|
||||
getDefaultQuickOpenHandler(): QuickOpenHandlerDescriptor;
|
||||
}
|
||||
|
||||
class QuickOpenRegistry implements IQuickOpenRegistry {
|
||||
private handlers: QuickOpenHandlerDescriptor[] = [];
|
||||
private defaultHandler: QuickOpenHandlerDescriptor | undefined;
|
||||
|
||||
registerQuickOpenHandler(descriptor: QuickOpenHandlerDescriptor): void {
|
||||
this.handlers.push(descriptor);
|
||||
|
||||
// sort the handlers by decreasing prefix length, such that longer
|
||||
// prefixes take priority: 'ext' vs 'ext install' - the latter should win
|
||||
this.handlers.sort((h1, h2) => h2.prefix.length - h1.prefix.length);
|
||||
}
|
||||
|
||||
registerDefaultQuickOpenHandler(descriptor: QuickOpenHandlerDescriptor): void {
|
||||
this.defaultHandler = descriptor;
|
||||
}
|
||||
|
||||
getQuickOpenHandlers(): QuickOpenHandlerDescriptor[] {
|
||||
return this.handlers.slice(0);
|
||||
}
|
||||
|
||||
getQuickOpenHandler(text: string): QuickOpenHandlerDescriptor | null {
|
||||
return text ? (first<QuickOpenHandlerDescriptor>(this.handlers, h => startsWith(text, h.prefix)) || null) : null;
|
||||
}
|
||||
|
||||
getDefaultQuickOpenHandler(): QuickOpenHandlerDescriptor {
|
||||
return assertIsDefined(this.defaultHandler);
|
||||
}
|
||||
}
|
||||
|
||||
Registry.add(Extensions.Quickopen, new QuickOpenRegistry());
|
||||
|
||||
export interface IEditorQuickOpenEntry {
|
||||
|
||||
/**
|
||||
* The editor input used for this entry when opening.
|
||||
*/
|
||||
getInput(): IResourceEditorInput | IEditorInput | undefined;
|
||||
|
||||
/**
|
||||
* The editor options used for this entry when opening.
|
||||
*/
|
||||
getOptions(): IEditorOptions | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* A subclass of quick open entry that will open an editor with input and options when running.
|
||||
*/
|
||||
export class EditorQuickOpenEntry extends QuickOpenEntry implements IEditorQuickOpenEntry {
|
||||
|
||||
constructor(private _editorService: IEditorService) {
|
||||
super();
|
||||
}
|
||||
|
||||
get editorService() {
|
||||
return this._editorService;
|
||||
}
|
||||
|
||||
getInput(): IResourceEditorInput | IEditorInput | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getOptions(): IEditorOptions | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
run(mode: Mode, context: IEntryRunContext): boolean {
|
||||
const hideWidget = (mode === Mode.OPEN);
|
||||
|
||||
if (mode === Mode.OPEN || mode === Mode.OPEN_IN_BACKGROUND) {
|
||||
const sideBySide = context.keymods.ctrlCmd;
|
||||
|
||||
let openOptions: IEditorOptions | undefined;
|
||||
if (mode === Mode.OPEN_IN_BACKGROUND) {
|
||||
openOptions = { pinned: true, preserveFocus: true };
|
||||
} else if (context.keymods.alt) {
|
||||
openOptions = { pinned: true };
|
||||
}
|
||||
|
||||
const input = this.getInput();
|
||||
if (input instanceof EditorInput) {
|
||||
let opts = this.getOptions();
|
||||
if (opts) {
|
||||
opts = mixin(opts, openOptions, true);
|
||||
} else if (openOptions) {
|
||||
opts = EditorOptions.create(openOptions);
|
||||
}
|
||||
|
||||
this.editorService.openEditor(input, withNullAsUndefined(opts), sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
|
||||
} else {
|
||||
const resourceEditorInput = <IResourceEditorInput>input;
|
||||
|
||||
if (openOptions) {
|
||||
resourceEditorInput.options = assign(resourceEditorInput.options || Object.create(null), openOptions);
|
||||
}
|
||||
|
||||
this.editorService.openEditor(resourceEditorInput, sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
|
||||
}
|
||||
}
|
||||
|
||||
return hideWidget;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A subclass of quick open entry group that provides access to editor input and options.
|
||||
*/
|
||||
export class EditorQuickOpenEntryGroup extends QuickOpenEntryGroup implements IEditorQuickOpenEntry {
|
||||
|
||||
getInput(): IEditorInput | IResourceEditorInput | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getOptions(): IEditorOptions | undefined {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickOpenAction extends Action {
|
||||
private prefix: string;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
prefix: string,
|
||||
@IQuickOpenService protected readonly quickOpenService: IQuickOpenService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
this.quickOpenService.show(this.prefix);
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,6 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||
const listHighlightForegroundColor = theme.getColor(listHighlightForeground);
|
||||
if (listHighlightForegroundColor) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench .monaco-tree .monaco-tree-row .monaco-highlighted-label .highlight,
|
||||
.monaco-workbench .monaco-list .monaco-list-row .monaco-highlighted-label .highlight {
|
||||
color: ${listHighlightForegroundColor};
|
||||
}
|
||||
@@ -115,7 +114,6 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||
.monaco-workbench [tabindex="-1"]:focus,
|
||||
.monaco-workbench .synthetic-focus,
|
||||
.monaco-workbench select:focus,
|
||||
.monaco-workbench .monaco-tree.focused.no-focused-item:focus:before,
|
||||
.monaco-workbench .monaco-list:not(.element-focused):focus:before,
|
||||
.monaco-workbench input[type="button"]:focus,
|
||||
.monaco-workbench input[type="text"]:focus,
|
||||
@@ -143,11 +141,6 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||
outline-width: 1px;
|
||||
}
|
||||
|
||||
.hc-black .monaco-tree.focused.no-focused-item:focus:before {
|
||||
outline-width: 1px;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.hc-black .synthetic-focus input {
|
||||
background: transparent; /* Search input focus fix when in high contrast */
|
||||
}
|
||||
|
||||
@@ -17,6 +17,16 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
|
||||
registry.registerConfiguration({
|
||||
...workbenchConfigurationNodeBase,
|
||||
'properties': {
|
||||
'workbench.editor.titleScrollbarSizing': {
|
||||
type: 'string',
|
||||
enum: ['default', 'large'],
|
||||
enumDescriptions: [
|
||||
nls.localize('workbench.editor.titleScrollbarSizing.default', "The default size."),
|
||||
nls.localize('workbench.editor.titleScrollbarSizing.large', "Increases the size, so it can be grabed more easily with the mouse")
|
||||
],
|
||||
description: nls.localize('tabScrollbarHeight', "Controls the height of the scrollbars used for tabs and breadcrumbs in the editor title area."),
|
||||
default: 'default',
|
||||
},
|
||||
'workbench.editor.showTabs': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('showEditorTabs', "Controls whether opened editors should show in tabs or not."),
|
||||
@@ -179,11 +189,6 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
|
||||
'description': nls.localize('workbench.quickOpen.preserveInput', "Controls whether the last typed input to Quick Open should be restored when opening it the next time."),
|
||||
'default': false
|
||||
},
|
||||
'workbench.quickOpen.enableExperimentalNewVersion': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('workbench.quickOpen.enableExperimentalNewVersion', "Will use the new quick open implementation for testing purposes."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.settings.openDefaultSettings': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('openDefaultSettings', "Controls whether opening settings also opens an editor showing all default settings."),
|
||||
|
||||
@@ -16,7 +16,6 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { isWindows, isLinux, isWeb, isNative, isMacintosh } from 'vs/base/common/platform';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { IEditorInputFactoryRegistry, Extensions as EditorExtensions } from 'vs/workbench/common/editor';
|
||||
import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions';
|
||||
import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions';
|
||||
import { Position, Parts, IWorkbenchLayoutService, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IStorageService, WillSaveStateReason, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
@@ -217,7 +216,6 @@ export class Workbench extends Layout {
|
||||
}
|
||||
|
||||
private startRegistries(accessor: ServicesAccessor): void {
|
||||
Registry.as<IActionBarRegistry>(ActionBarExtensions.Actionbar).start(accessor);
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).start(accessor);
|
||||
Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor);
|
||||
Registry.as<ILanguageAssociationRegistry>(LanguageExtensions.LanguageAssociations).start(accessor);
|
||||
|
||||
Reference in New Issue
Block a user