Merge from vscode 073a24de05773f2261f89172987002dc0ae2f1cd (#9711)

This commit is contained in:
Anthony Dresser
2020-03-24 00:24:15 -07:00
committed by GitHub
parent 29741d684e
commit 89ef1b0c2e
226 changed files with 6161 additions and 3288 deletions

View File

@@ -41,7 +41,7 @@ class InspectContextKeysAction extends Action {
super(id, label);
}
run(): Promise<void> {
async run(): Promise<void> {
const disposables = new DisposableStore();
const stylesheet = createStyleSheet();
@@ -85,8 +85,6 @@ class InspectContextKeysAction extends Action {
dispose(disposables);
}, null, disposables);
return Promise.resolve();
}
}

View File

@@ -31,13 +31,11 @@ class KeybindingsReferenceAction extends Action {
super(id, label);
}
run(): Promise<void> {
async run(): Promise<void> {
const url = isLinux ? this.productService.keyboardShortcutsUrlLinux : isMacintosh ? this.productService.keyboardShortcutsUrlMac : this.productService.keyboardShortcutsUrlWin;
if (url) {
this.openerService.open(URI.parse(url));
}
return Promise.resolve();
}
}
@@ -56,12 +54,10 @@ class OpenDocumentationUrlAction extends Action {
super(id, label);
}
run(): Promise<void> {
async run(): Promise<void> {
if (this.productService.documentationUrl) {
this.openerService.open(URI.parse(this.productService.documentationUrl));
}
return Promise.resolve();
}
}
@@ -80,12 +76,10 @@ class OpenIntroductoryVideosUrlAction extends Action {
super(id, label);
}
run(): Promise<void> {
async run(): Promise<void> {
if (this.productService.introductoryVideosUrl) {
this.openerService.open(URI.parse(this.productService.introductoryVideosUrl));
}
return Promise.resolve();
}
}
@@ -104,12 +98,10 @@ class OpenTipsAndTricksUrlAction extends Action {
super(id, label);
}
run(): Promise<void> {
async run(): Promise<void> {
if (this.productService.tipsAndTricksUrl) {
this.openerService.open(URI.parse(this.productService.tipsAndTricksUrl));
}
return Promise.resolve();
}
}
@@ -151,12 +143,10 @@ class OpenTwitterUrlAction extends Action {
super(id, label);
}
run(): Promise<void> {
async run(): Promise<void> {
if (this.productService.twitterUrl) {
this.openerService.open(URI.parse(this.productService.twitterUrl));
}
return Promise.resolve();
}
}
@@ -175,12 +165,10 @@ class OpenRequestFeatureUrlAction extends Action {
super(id, label);
}
run(): Promise<void> {
async run(): Promise<void> {
if (this.productService.requestFeatureUrl) {
this.openerService.open(URI.parse(this.productService.requestFeatureUrl));
}
return Promise.resolve();
}
}
@@ -199,7 +187,7 @@ class OpenLicenseUrlAction extends Action {
super(id, label);
}
run(): Promise<void> {
async run(): Promise<void> {
if (this.productService.licenseUrl) {
if (language) {
const queryArgChar = this.productService.licenseUrl.indexOf('?') > 0 ? '&' : '?';
@@ -208,8 +196,6 @@ class OpenLicenseUrlAction extends Action {
this.openerService.open(URI.parse(this.productService.licenseUrl));
}
}
return Promise.resolve();
}
}
@@ -228,7 +214,7 @@ class OpenPrivacyStatementUrlAction extends Action {
super(id, label);
}
run(): Promise<void> {
async run(): Promise<void> {
if (this.productService.privacyStatementUrl) {
if (language) {
const queryArgChar = this.productService.privacyStatementUrl.indexOf('?') > 0 ? '&' : '?';
@@ -237,8 +223,6 @@ class OpenPrivacyStatementUrlAction extends Action {
this.openerService.open(URI.parse(this.productService.privacyStatementUrl));
}
}
return Promise.resolve();
}
}

View File

@@ -645,9 +645,8 @@ export class IncreaseViewSizeAction extends BaseResizeViewAction {
super(id, label, layoutService);
}
run(): Promise<boolean> {
async run(): Promise<void> {
this.resizePart(BaseResizeViewAction.RESIZE_INCREMENT);
return Promise.resolve(true);
}
}
@@ -665,9 +664,8 @@ export class DecreaseViewSizeAction extends BaseResizeViewAction {
super(id, label, layoutService);
}
run(): Promise<boolean> {
async run(): Promise<void> {
this.resizePart(-BaseResizeViewAction.RESIZE_INCREMENT);
return Promise.resolve(true);
}
}

View File

@@ -36,7 +36,7 @@ export const inRecentFilesPickerContextKey = 'inRecentFilesPicker';
abstract class BaseOpenRecentAction extends Action {
private removeFromRecentlyOpened: IQuickInputButton = {
private readonly removeFromRecentlyOpened: IQuickInputButton = {
iconClass: 'codicon-close',
tooltip: nls.localize('remove', "Remove from Recently Opened")
};
@@ -124,7 +124,7 @@ abstract class BaseOpenRecentAction extends Action {
const pick = await this.quickInputService.pick(picks, {
contextKey: inRecentFilesPickerContextKey,
activeItem: [...workspacePicks, ...filePicks][autoFocusSecondEntry ? 1 : 0],
placeHolder: isMacintosh ? nls.localize('openRecentPlaceHolderMac', "Select to open (hold Cmd-key to open in new window)") : nls.localize('openRecentPlaceHolder', "Select to open (hold Ctrl-key to open in new window)"),
placeHolder: isMacintosh ? nls.localize('openRecentPlaceHolderMac', "Select to open (hold Cmd-key to force new window or Alt-key for same window)") : nls.localize('openRecentPlaceHolder', "Select to open (hold Ctrl-key to force new window or Alt-key for same window)"),
matchOnDescription: true,
onKeyMods: mods => keyMods = mods,
quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : undefined,
@@ -135,7 +135,7 @@ abstract class BaseOpenRecentAction extends Action {
});
if (pick) {
return this.hostService.openWindow([pick.openable], { forceNewWindow: keyMods?.ctrlCmd });
return this.hostService.openWindow([pick.openable], { forceNewWindow: keyMods?.ctrlCmd, forceReuseWindow: keyMods?.alt });
}
}
}

View File

@@ -112,11 +112,10 @@ export class CloseWorkspaceAction extends Action {
super(id, label);
}
run(): Promise<void> {
async run(): Promise<void> {
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
this.notificationService.info(nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close."));
return Promise.resolve(undefined);
return;
}
return this.hostService.openWindow({ forceReuseWindow: true, remoteAuthority: this.environmentService.configuration.remoteAuthority });

View File

@@ -645,15 +645,19 @@ export class CompositeDragAndDropObserver extends Disposable {
}
return this._register(disposableStore);
}
registerDraggable(element: HTMLElement, type: ViewType, id: string, callbacks: ICompositeDragAndDropObserverCallbacks): IDisposable {
registerDraggable(element: HTMLElement, draggedItemProvider: () => { type: ViewType, id: string }, callbacks: ICompositeDragAndDropObserverCallbacks): IDisposable {
element.draggable = true;
const disposableStore = new DisposableStore();
disposableStore.add(addDisposableListener(element, EventType.DRAG_START, e => {
const { id, type } = draggedItemProvider();
this.writeDragData(id, type);
this._onDragStart.fire({ eventData: e, dragAndDropData: this.readDragData(type)! });
}));
disposableStore.add(new DragAndDropObserver(element, {
onDragEnd: e => {
const { id, type } = draggedItemProvider();
const data = this.readDragData(type);
if (data && data.getData().id === id) {
this.transferData.clearData(type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype);
@@ -666,6 +670,7 @@ export class CompositeDragAndDropObserver extends Disposable {
this._onDragEnd.fire({ eventData: e, dragAndDropData: data! });
},
onDragEnter: e => {
if (callbacks.onDragEnter) {
const data = this.readDragData('composite') || this.readDragData('view');
if (!data) {

View File

@@ -364,8 +364,8 @@ class ResourceLabelWidget extends IconLabel {
}
setResource(label: IResourceLabelProps, options: IResourceLabelOptions = Object.create(null)): void {
/*const resource = toResource(this.label); {{SQL CARBON EDIT}} we don't want to special case untitled files
const isMasterDetail = this.label?.resource && !URI.isUri(this.label.resource);
/*const resource = toResource(label); {{SQL CARBON EDIT}} we don't want to special case untitled files
const isMasterDetail = label?.resource && !URI.isUri(label.resource);
if (!isMasterDetail && resource?.scheme === Schemas.untitled) {
// Untitled labels are very dynamic because they may change

View File

@@ -424,11 +424,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
if (!this.state.fullscreen && !this.state.maximized && (activeBorder || inactiveBorder)) {
windowBorder = true;
// If one color is missing, just fallback to the other one
const borderColor = this.state.hasFocus
? activeBorder ?? inactiveBorder
: inactiveBorder ?? activeBorder;
this.container.style.setProperty('--window-border-color', borderColor ? borderColor.toString() : 'transparent');
// If the inactive color is missing, fallback to the active one
const borderColor = this.state.hasFocus ? activeBorder : inactiveBorder ?? activeBorder;
this.container.style.setProperty('--window-border-color', borderColor?.toString() ?? 'transparent');
}
if (windowBorder === this.state.windowBorder) {

View File

@@ -134,6 +134,61 @@ export class ToggleViewletAction extends Action {
}
}
export class AccountsActionViewItem extends ActivityActionViewItem {
constructor(
action: ActivityAction,
colors: (theme: IColorTheme) => ICompositeBarColors,
@IThemeService themeService: IThemeService,
@IContextMenuService protected contextMenuService: IContextMenuService,
@IMenuService protected menuService: IMenuService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
) {
super(action, { draggable: false, colors, icon: true }, themeService);
}
render(container: HTMLElement): void {
super.render(container);
// Context menus are triggered on mouse down so that an item can be picked
// and executed with releasing the mouse over it
this._register(DOM.addDisposableListener(this.container, DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => {
DOM.EventHelper.stop(e, true);
this.showContextMenu();
}));
this._register(DOM.addDisposableListener(this.container, DOM.EventType.KEY_UP, (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
DOM.EventHelper.stop(e, true);
this.showContextMenu();
}
}));
this._register(DOM.addDisposableListener(this.container, TouchEventType.Tap, (e: GestureEvent) => {
DOM.EventHelper.stop(e, true);
this.showContextMenu();
}));
}
private showContextMenu(): void {
const accountsActions: IAction[] = [];
const accountsMenu = this.menuService.createMenu(MenuId.AccountsContext, this.contextKeyService);
const actionsDisposable = createAndFillInActionBarActions(accountsMenu, undefined, { primary: [], secondary: accountsActions });
const containerPosition = DOM.getDomNodePagePosition(this.container);
const location = { x: containerPosition.left + containerPosition.width / 2, y: containerPosition.top };
this.contextMenuService.showContextMenu({
getAnchor: () => location,
getActions: () => accountsActions,
onHide: () => {
accountsMenu.dispose();
dispose(actionsDisposable);
}
});
}
}
export class GlobalActivityActionViewItem extends ActivityActionViewItem {
constructor(
@@ -231,7 +286,7 @@ class SwitchSideBarViewAction extends Action {
const activeViewlet = this.viewletService.getActiveViewlet();
if (!activeViewlet) {
return Promise.resolve();
return;
}
let targetViewletId: string | undefined;
for (let i = 0; i < pinnedViewletIds.length; i++) {

View File

@@ -9,7 +9,7 @@ import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/acti
import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity';
import { Registry } from 'vs/platform/registry/common/platform';
import { Part } from 'vs/workbench/browser/part';
import { GlobalActivityActionViewItem, ViewletActivityAction, ToggleViewletAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewletActivityAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
import { GlobalActivityActionViewItem, ViewletActivityAction, ToggleViewletAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewletActivityAction, AccountsActionViewItem } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IBadge, NumberBadge } from 'vs/workbench/services/activity/common/activity';
import { IWorkbenchLayoutService, Parts, Position as SideBarPosition } from 'vs/workbench/services/layout/browser/layoutService';
@@ -354,7 +354,17 @@ export class ActivitybarPart extends Part implements IActivityBarService {
private createGlobalActivityActionBar(container: HTMLElement): void {
this.globalActivityActionBar = this._register(new ActionBar(container, {
actionViewItemProvider: action => this.instantiationService.createInstance(GlobalActivityActionViewItem, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme)),
actionViewItemProvider: action => {
if (action.id === 'workbench.actions.manage') {
return this.instantiationService.createInstance(GlobalActivityActionViewItem, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme));
}
if (action.id === 'workbench.actions.accounts') {
return this.instantiationService.createInstance(AccountsActionViewItem, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme));
}
throw new Error(`No view item for action '${action.id}'`);
},
orientation: ActionsOrientation.VERTICAL,
ariaLabel: nls.localize('manage', "Manage"),
animated: false
@@ -366,6 +376,13 @@ 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'
});
this.globalActivityActionBar.push(profileAction);
this.globalActivityActionBar.push(this.globalActivityAction);
}

View File

@@ -9,8 +9,8 @@
margin-bottom: 4px;
}
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::before,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::after {
.monaco-workbench .activitybar > .content .composite-bar > .monaco-action-bar .action-item::before,
.monaco-workbench .activitybar > .content .composite-bar > .monaco-action-bar .action-item::after {
position: absolute;
content: '';
width: 48px;
@@ -23,25 +23,32 @@
transition-delay: 100ms;
}
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::before {
.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item::before {
margin-top: -3px;
margin-bottom: 1px;
}
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::after {
/* Override top element since it would be cut off */
.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item:first-of-type::before {
margin-top: 0px;
margin-bottom: 0px;
}
.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item::after {
margin-top: 1px;
margin-bottom: -3px;
}
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.top::before,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.top::after,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.bottom::before,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.bottom::after {
.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.top::before,
.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.top::after,
.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.bottom::before,
.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.bottom::after {
transition-delay: 0s;
}
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.top::before,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.bottom::after {
.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.top::before,
.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.bottom::after,
.monaco-workbench .activitybar > .content.dragged-over > .composite-bar > .monaco-action-bar .action-item:last-of-type::after {
opacity: 1;
}

View File

@@ -12,12 +12,12 @@ import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ActionBar, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { CompositeActionViewItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionViewItem, ActivityAction, ICompositeBar, ICompositeBarColors } from 'vs/workbench/browser/parts/compositeBarActions';
import { Dimension, $, addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom';
import { Dimension, $, addDisposableListener, EventType, EventHelper, toggleClass, isAncestor } from 'vs/base/browser/dom';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { Widget } from 'vs/base/browser/ui/widget';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';
import { IColorTheme } from 'vs/platform/theme/common/themeService';
import { Emitter } from 'vs/base/common/event';
import { Registry } from 'vs/platform/registry/common/platform';
import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
@@ -187,7 +187,6 @@ export class CompositeBar extends Widget implements ICompositeBar {
constructor(
items: ICompositeBarItem[],
private options: ICompositeBarOptions,
@IThemeService private readonly themeService: IThemeService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IContextMenuService private readonly contextMenuService: IContextMenuService
) {
@@ -215,8 +214,6 @@ export class CompositeBar extends Widget implements ICompositeBar {
create(parent: HTMLElement): HTMLElement {
const actionBarDiv = parent.appendChild($('.composite-bar'));
const excessDiv = parent.appendChild($('.composite-bar-excess'));
this.compositeSwitcherBar = this._register(new ActionBar(actionBarDiv, {
actionViewItemProvider: (action: IAction) => {
if (action instanceof CompositeOverflowActivityAction) {
@@ -242,23 +239,26 @@ export class CompositeBar extends Widget implements ICompositeBar {
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e)));
// Register a drop target on the whole bar to prevent forbidden feedback
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(parent, {}));
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(parent, {
onDragOver: (e: IDraggedCompositeData) => {
// don't add feedback if this is over the composite bar actions
if (e.eventData.target && isAncestor(e.eventData.target as HTMLElement, actionBarDiv)) {
toggleClass(parent, 'dragged-over', false);
return;
}
// Allow to drop at the end to move composites to the end
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(excessDiv, {
onDragEnter: (e: IDraggedCompositeData) => {
const pinnedItems = this.getPinnedComposites();
const validDropTarget = this.options.dndHandler.onDragEnter(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData);
this.updateFromDragging(excessDiv, validDropTarget);
const validDropTarget = this.options.dndHandler.onDragOver(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData);
toggleClass(parent, 'dragged-over', validDropTarget);
},
onDragLeave: (e: IDraggedCompositeData) => {
this.updateFromDragging(excessDiv, false);
toggleClass(parent, 'dragged-over', false);
},
onDrop: (e: IDraggedCompositeData) => {
const pinnedItems = this.getPinnedComposites();
this.options.dndHandler.drop(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData, false);
this.updateFromDragging(excessDiv, false);
toggleClass(parent, 'dragged-over', false);
}
}));
@@ -364,13 +364,6 @@ export class CompositeBar extends Widget implements ICompositeBar {
}
}
private updateFromDragging(element: HTMLElement, isDragging: boolean): void {
const theme = this.themeService.getColorTheme();
const dragBackground = this.options.colors(theme).dragAndDropBackground;
element.style.backgroundColor = isDragging && dragBackground ? dragBackground.toString() : '';
}
private resetActiveComposite(compositeId: string) {
const defaultCompositeId = this.options.getDefaultCompositeId();

View File

@@ -518,7 +518,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
let insertDropBefore: boolean | undefined = undefined;
// Allow to drag
this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(this.container, 'composite', this.activity.id, {
this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(this.container, () => { return { type: 'composite', id: this.activity.id }; }, {
onDragOver: e => {
const isValidMove = e.dragAndDropData.getData().id !== this.activity.id && this.dndHandler.onDragOver(e.dragAndDropData, this.activity.id, e.eventData);
insertDropBefore = this.updateFromDragging(container, isValidMove, e.eventData);
@@ -533,6 +533,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
},
onDrop: e => {
dom.EventHelper.stop(e.eventData, true);
this.dndHandler.drop(e.dragAndDropData, this.activity.id, e.eventData, !!insertDropBefore);
insertDropBefore = this.updateFromDragging(container, false, e.eventData);
},
@@ -554,9 +555,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
// Activate on drag over to reveal targets
[this.badge, this.label].forEach(b => this._register(new DelayedDragHandler(b, () => {
if (!(this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype) ||
this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) &&
!this.getAction().checked) {
if (!this.getAction().checked) {
this.getAction().run();
}
})));

View File

@@ -292,11 +292,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
localize('closeGroupAction', "Close"),
'codicon-close',
true,
() => {
this.accessor.removeGroup(this);
return Promise.resolve(true);
}));
async () => this.accessor.removeGroup(this)));
const keybinding = this.keybindingService.lookupKeybinding(removeGroupAction.id);
containerToolbar.push(removeGroupAction, { icon: true, label: false, keybinding: keybinding ? keybinding.getLabel() : undefined });
@@ -807,7 +803,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Guard against invalid inputs
if (!editor) {
return Promise.resolve(null);
return null;
}
// Editor opening event allows for prevention
@@ -822,13 +818,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
return withUndefinedAsNull(await this.doOpenEditor(editor, options));
}
private doOpenEditor(editor: EditorInput, options?: EditorOptions): Promise<IEditorPane | undefined> {
private async doOpenEditor(editor: EditorInput, options?: EditorOptions): Promise<IEditorPane | undefined> {
// Guard against invalid inputs. Disposed inputs
// should never open because they emit no events
// e.g. to indicate dirty changes.
if (editor.isDisposed()) {
return Promise.resolve(undefined);
return undefined; // {{SQL CARBON EDIT}} strict-null-checks
}
// Determine options

View File

@@ -5,7 +5,7 @@
import 'vs/css!./media/editorquickaccess';
import { localize } from 'vs/nls';
import { IQuickPickSeparator, quickPickItemScorerAccessor, IQuickPickItemWithResource } from 'vs/platform/quickinput/common/quickInput';
import { IQuickPickSeparator, quickPickItemScorerAccessor, IQuickPickItemWithResource, IQuickPick } from 'vs/platform/quickinput/common/quickInput';
import { PickerQuickAccessProvider, IPickerQuickAccessItem, TriggerAction } from 'vs/platform/quickinput/browser/pickerQuickAccess';
import { IEditorGroupsService, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService';
import { EditorsOrder, IEditorIdentifier, toResource, SideBySideEditor } from 'vs/workbench/common/editor';
@@ -13,12 +13,31 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { prepareQuery, scoreItem, compareItemsByScore } from 'vs/base/common/fuzzyScorer';
import { prepareQuery, scoreItem, compareItemsByScore, ScorerCache } from 'vs/base/common/fuzzyScorer';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IDisposable } from 'vs/base/common/lifecycle';
interface IEditorQuickPickItem extends IQuickPickItemWithResource, IEditorIdentifier, IPickerQuickAccessItem { }
export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessProvider<IEditorQuickPickItem> {
private readonly pickState = new class {
scorerCache: ScorerCache = Object.create(null);
isQuickNavigating: boolean | undefined = undefined;
reset(isQuickNavigating: boolean): void {
// Caches
if (!isQuickNavigating) {
this.scorerCache = Object.create(null);
}
// Other
this.isQuickNavigating = isQuickNavigating;
}
};
constructor(
prefix: string,
@IEditorGroupsService protected readonly editorGroupService: IEditorGroupsService,
@@ -29,9 +48,17 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
super(prefix, { canAcceptInBackground: true });
}
provide(picker: IQuickPick<IEditorQuickPickItem>, token: CancellationToken): IDisposable {
// Reset the pick state for this run
this.pickState.reset(!!picker.quickNavigate);
// Start picker
return super.provide(picker, token);
}
protected getPicks(filter: string): Array<IEditorQuickPickItem | IQuickPickSeparator> {
const query = prepareQuery(filter);
const scorerCache = Object.create(null);
// Filtering
const filteredEditorEntries = this.doGetEditorPickItems().filter(entry => {
@@ -40,7 +67,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
}
// Score on label and description
const itemScore = scoreItem(entry, query, true, quickPickItemScorerAccessor, scorerCache);
const itemScore = scoreItem(entry, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache);
if (!itemScore.score) {
return false;
}
@@ -59,7 +86,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
return groups.indexOf(entryA.groupId) - groups.indexOf(entryB.groupId); // older groups first
}
return compareItemsByScore(entryA, entryB, query, true, quickPickItemScorerAccessor, scorerCache);
return compareItemsByScore(entryA, entryB, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache);
});
}
@@ -99,17 +126,30 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
description: editor.getDescription(),
iconClasses: getIconClasses(this.modelService, this.modeService, resource),
italic: !this.editorGroupService.getGroup(groupId)?.isPinned(editor),
buttons: [
{
iconClass: isDirty ? 'dirty-editor codicon-circle-filled' : 'codicon-close',
tooltip: localize('closeEditor', "Close Editor"),
alwaysVisible: isDirty
buttons: (() => {
if (this.pickState.isQuickNavigating) {
return undefined; // no actions when quick navigating
}
],
trigger: async () => {
await this.editorGroupService.getGroup(groupId)?.closeEditor(editor, { preserveFocus: true });
return TriggerAction.REFRESH_PICKER;
return [
{
iconClass: isDirty ? 'dirty-editor codicon-circle-filled' : 'codicon-close',
tooltip: localize('closeEditor', "Close Editor"),
alwaysVisible: isDirty
}
];
})(),
trigger: async () => {
const group = this.editorGroupService.getGroup(groupId);
if (group) {
await group.closeEditor(editor, { preserveFocus: true });
if (!group.isOpened(editor)) {
return TriggerAction.REMOVE_ITEM;
}
}
return TriggerAction.NO_ACTION;
},
accept: (keyMods, event) => this.editorGroupService.getGroup(groupId)?.openEditor(editor, { preserveFocus: event.inBackground }),
};

View File

@@ -457,7 +457,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
const props: IStatusbarEntry = {
text,
tooltip: nls.localize('gotoLine', "Go to Line"),
tooltip: nls.localize('gotoLine', "Go to Line/Column"),
command: 'workbench.action.gotoLine'
};

View File

@@ -110,7 +110,7 @@ export class NoTabsTitleControl extends TitleControl {
}
}
} else {
// @rebornix
// TODO@rebornix
// gesture tap should open the quick open
// 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.

View File

@@ -207,13 +207,13 @@ export class TabsTitleControl extends TitleControl {
EventHelper.stop(e);
this.group.openEditor(this.editorService.createEditorInput({
forceUntitled: true,
options: {
this.group.openEditor(
this.editorService.createEditorInput({ forceUntitled: true }),
{
pinned: true, // untitled is always pinned
index: this.group.count // always at the end
}
}));
);
}));
});

View File

@@ -107,6 +107,11 @@
margin-left: 9px;
}
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item:last-of-type::after {
margin-right: -10px;
margin-left: 8px;
}
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.right::before,
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.left::after,
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.left::before,
@@ -115,7 +120,8 @@
}
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.left::before,
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.right::after {
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.right::after,
.monaco-workbench .part.panel > .composite.title.dragged-over > .panel-switcher-container > .monaco-action-bar .action-item:last-of-type::after {
opacity: 1;
}

View File

@@ -39,6 +39,17 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
}
});
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,

View File

@@ -724,7 +724,7 @@ class EditorHistoryHandler {
// 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, () => -1));
.sort((e1, e2) => compareItemsByScore(e1, e2, query, false, accessor, this.scorerCache));
}
}

View File

@@ -21,8 +21,8 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Event, Emitter } from 'vs/base/common/event';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { IThemeService, IColorTheme, ICssStyleCollector, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry';
import { SIDE_BAR_TITLE_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND, SIDE_BAR_BORDER, SIDE_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { EventType, addDisposableListener, trackFocus } from 'vs/base/browser/dom';
@@ -33,7 +33,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { LayoutPriority } from 'vs/base/browser/ui/grid/grid';
import { assertIsDefined } from 'vs/base/common/types';
import { LocalSelectionTransfer, DraggedViewIdentifier, DraggedCompositeIdentifier } from 'vs/workbench/browser/dnd';
import { CompositeDragAndDropObserver } from 'vs/workbench/browser/dnd';
export class SidebarPart extends CompositePart<Viewlet> implements IViewletService {
@@ -165,28 +165,18 @@ export class SidebarPart extends CompositePart<Viewlet> implements IViewletServi
}));
this.titleLabelElement!.draggable = true;
this._register(addDisposableListener(this.titleLabelElement!, EventType.DRAG_START, e => {
const activeViewlet = this.getActiveViewlet();
if (activeViewlet) {
const visibleViews = activeViewlet.getViewPaneContainer().views.filter(v => v.isVisible());
if (visibleViews.length === 1) {
LocalSelectionTransfer.getInstance<DraggedViewIdentifier>().setData([new DraggedViewIdentifier(visibleViews[0].id)], DraggedViewIdentifier.prototype);
} else {
LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier>().setData([new DraggedCompositeIdentifier(activeViewlet.getId())], DraggedCompositeIdentifier.prototype);
}
}
}));
this._register(addDisposableListener(this.titleLabelElement!, EventType.DRAG_END, e => {
if (LocalSelectionTransfer.getInstance<DraggedViewIdentifier>().hasData(DraggedViewIdentifier.prototype)) {
LocalSelectionTransfer.getInstance<DraggedViewIdentifier>().clearData(DraggedViewIdentifier.prototype);
const draggedItemProvider = (): { type: 'view' | 'composite', id: string } => {
const activeViewlet = this.getActiveViewlet()!;
const visibleViews = activeViewlet.getViewPaneContainer().views.filter(v => v.isVisible());
if (visibleViews.length === 1) {
return { type: 'view', id: visibleViews[0].id };
} else {
return { type: 'composite', id: activeViewlet.getId() };
}
};
if (LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier>().hasData(DraggedCompositeIdentifier.prototype)) {
LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier>().clearData(DraggedCompositeIdentifier.prototype);
}
}));
this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(this.titleLabelElement!, draggedItemProvider, {}));
return titleArea;
}
@@ -343,6 +333,23 @@ class FocusSideBarAction extends Action {
}
}
registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => {
// Sidebar Background: since views can host editors, we apply a background rule if the sidebar background
// color is different from the editor background color. This is a bit of a hack though. The better way
// would be to have a way to push the background color onto each editor widget itself somehow.
const sidebarBackground = theme.getColor(SIDE_BAR_BACKGROUND);
if (sidebarBackground && sidebarBackground !== theme.getColor(editorBackground)) {
collector.addRule(`
.monaco-workbench .part.sidebar > .content .monaco-editor,
.monaco-workbench .part.sidebar > .content .monaco-editor .margin,
.monaco-workbench .part.sidebar > .content .monaco-editor .monaco-editor-background {
background-color: ${sidebarBackground};
}
`);
}
});
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusSideBarAction, FocusSideBarAction.ID, FocusSideBarAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.KEY_0

View File

@@ -609,7 +609,6 @@ export class TreeView extends Disposable implements ITreeView {
return tree.expand(element, false);
}));
}
return Promise.resolve(undefined);
}
setSelection(items: ITreeItem[]): void {
@@ -625,11 +624,10 @@ export class TreeView extends Disposable implements ITreeView {
}
}
reveal(item: ITreeItem): Promise<void> {
async reveal(item: ITreeItem): Promise<void> {
if (this.tree) {
return Promise.resolve(this.tree.reveal(item));
return this.tree.reveal(item);
}
return Promise.resolve();
}
private refreshing: boolean = false;
@@ -689,11 +687,11 @@ class TreeDataSource implements IAsyncDataSource<ITreeItem, ITreeItem> {
return !!this.treeView.dataProvider && (element.collapsibleState !== TreeItemCollapsibleState.None);
}
getChildren(element: ITreeItem): ITreeItem[] | Promise<ITreeItem[]> {
async getChildren(element: ITreeItem): Promise<ITreeItem[]> {
if (this.treeView.dataProvider) {
return this.withProgress(this.treeView.dataProvider.getChildren(element));
}
return Promise.resolve([]);
return [];
}
}

View File

@@ -23,7 +23,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService, Themable } from 'vs/platform/theme/common/themeService';
import { PaneView, IPaneViewOptions, IPaneOptions, Pane } from 'vs/base/browser/ui/splitview/paneview';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewContainersRegistry, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor } from 'vs/workbench/common/views';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
@@ -209,8 +209,6 @@ export abstract class ViewPane extends Pane implements IView {
this.title = options.title;
this.showActionsAlways = !!options.showActionsAlways;
this.focusedViewContextKey = FocusedViewContext.bindTo(contextKeyService);
this._preventCollapse = this.viewDescriptorService.getViewLocation(this.id) === ViewContainerLocation.Panel;
this._expanded = this._preventCollapse || this._expanded;
this.menuActions = this._register(instantiationService.createInstance(ViewMenuActions, this.id, options.titleMenuId || MenuId.ViewTitle, MenuId.ViewTitleContext));
this._register(this.menuActions.onDidChangeTitle(() => this.updateActions()));
@@ -275,9 +273,7 @@ export abstract class ViewPane extends Pane implements IView {
protected renderHeader(container: HTMLElement): void {
this.headerContainer = container;
if (!this._preventCollapse) {
this.renderTwisties(container);
}
this.renderTwisties(container);
this.renderHeaderTitle(container, this.title);
@@ -788,7 +784,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
create(parent: HTMLElement): void {
const options = this.options as IPaneViewOptions;
options.orientation = this.viewDescriptorService.getViewContainerLocation(this.viewContainer) === ViewContainerLocation.Panel ? Orientation.HORIZONTAL : Orientation.VERTICAL;
options.orientation = this.orientation;
this.paneview = this._register(new PaneView(parent, this.options));
this._register(this.paneview.onDidDrop(({ from, to }) => this.movePane(from as ViewPane, to as ViewPane)));
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, (e: MouseEvent) => this.showContextMenu(new StandardMouseEvent(e))));
@@ -919,8 +915,20 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
}
}
private get orientation(): Orientation {
if (this.viewDescriptorService.getViewContainerLocation(this.viewContainer) === ViewContainerLocation.Sidebar) {
return Orientation.VERTICAL;
} else {
return this.layoutService.getPanelPosition() === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL;
}
}
layout(dimension: Dimension): void {
if (this.paneview) {
if (this.paneview.orientation !== this.orientation) {
this.paneview.flipOrientation(dimension.height, dimension.width);
}
this.paneview.layout(dimension.height, dimension.width);
}
@@ -1142,7 +1150,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
let overlay: ViewPaneDropOverlay | undefined;
this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(pane.draggableElement, 'view', pane.id, {}));
this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(pane.draggableElement, () => { return { type: 'view', id: pane.id }; }, {}));
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(pane.dropTargetElement, {
onDragEnter: (e) => {

View File

@@ -32,6 +32,7 @@ export interface IWorkbenchQuickOpenConfiguration {
},
quickOpen: {
enableExperimentalNewVersion: boolean;
preserveInput: boolean;
}
};
}
@@ -325,19 +326,14 @@ export class QuickOpenAction extends Action {
id: string,
label: string,
prefix: string,
@IQuickOpenService private readonly quickOpenService: IQuickOpenService
@IQuickOpenService protected readonly quickOpenService: IQuickOpenService
) {
super(id, label);
this.prefix = prefix;
this.enabled = !!this.quickOpenService;
}
run(): Promise<void> {
// Show with prefix
async run(): Promise<void> {
this.quickOpenService.show(this.prefix);
return Promise.resolve(undefined);
}
}

View File

@@ -194,10 +194,6 @@ export class ShowViewletAction extends Action {
export class CollapseAction extends Action {
constructor(tree: AsyncDataTree<any, any, any> | AbstractTree<any, any, any>, enabled: boolean, clazz?: string) {
super('workbench.action.collapse', nls.localize('collapse', "Collapse All"), clazz, enabled, () => {
tree.collapseAll();
return Promise.resolve(undefined);
});
super('workbench.action.collapse', nls.localize('collapse', "Collapse All"), clazz, enabled, async () => tree.collapseAll());
}
}

View File

@@ -182,7 +182,7 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
'workbench.quickOpen.enableExperimentalNewVersion': {
'type': 'boolean',
'description': nls.localize('workbench.quickOpen.enableExperimentalNewVersion', "Will use the new quick open implementation for testing purposes."),
'default': false
'default': true
},
'workbench.settings.openDefaultSettings': {
'type': 'boolean',