Merge from vscode fcf3346a8e9f5ee1e00674461d9e2c2292a14ee3 (#12295)

* Merge from vscode fcf3346a8e9f5ee1e00674461d9e2c2292a14ee3

* Fix test build break

* Update distro

* Fix build errors

* Update distro

* Update REH build file

* Update build task names for REL

* Fix product build yaml

* Fix product REH task name

* Fix type in task name

* Update linux build step

* Update windows build tasks

* Turn off server publish

* Disable REH

* Fix typo

* Bump distro

* Update vscode tests

* Bump distro

* Fix type in disto

* Bump distro

* Turn off docker build

* Remove docker step from release

Co-authored-by: ADS Merger <andresse@microsoft.com>
Co-authored-by: Karl Burtram <karlb@microsoft.com>
This commit is contained in:
Christopher Suh
2020-10-03 14:42:05 -04:00
committed by GitHub
parent 58d02b76db
commit 6ff1e3866b
687 changed files with 10507 additions and 9104 deletions

View File

@@ -610,7 +610,12 @@ export class MoveViewAction extends Action {
return new Promise((resolve, reject) => {
quickPick.onDidAccept(() => {
const viewId = quickPick.selectedItems[0];
resolve(viewId.id);
if (viewId.id) {
resolve(viewId.id);
} else {
reject();
}
quickPick.hide();
});

View File

@@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext } from 'vs/platform/contextkey/common/contextkeys';
import { ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, TEXT_DIFF_EDITOR_ID, SplitEditorsVertically, InEditorZenModeContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorIsReadonlyContext, EditorAreaVisibleContext, DirtyWorkingCopiesContext, ActiveEditorAvailableEditorIdsContext } from 'vs/workbench/common/editor';
import { ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, TEXT_DIFF_EDITOR_ID, SplitEditorsVertically, InEditorZenModeContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext } from 'vs/workbench/common/editor';
import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -21,14 +21,12 @@ import { PanelPositionContext } from 'vs/workbench/common/panel';
import { getRemoteName } from 'vs/platform/remote/common/remoteHosts';
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
export const RemoteNameContext = new RawContextKey<string>('remoteName', '');
export const RemoteConnectionState = new RawContextKey<'' | 'initializing' | 'disconnected' | 'connected'>('remoteConnectionState', '');
export const WorkbenchStateContext = new RawContextKey<string>('workbenchState', undefined);
export const WorkspaceFolderCountContext = new RawContextKey<number>('workspaceFolderCount', 0);
export const RemoteFileDialogContext = new RawContextKey<boolean>('remoteFileDialogVisible', false);
export const DirtyWorkingCopiesContext = new RawContextKey<boolean>('dirtyWorkingCopies', false);
export const RemoteNameContext = new RawContextKey<string>('remoteName', '');
export const IsFullscreenContext = new RawContextKey<boolean>('isFullscreen', false);
@@ -89,7 +87,7 @@ export class WorkbenchContextKeysHandler extends Disposable {
// Editors
this.activeEditorContext = ActiveEditorContext.bindTo(this.contextKeyService);
this.activeEditorIsReadonly = ActiveEditorIsReadonlyContext.bindTo(this.contextKeyService);
this.activeEditorIsReadonly = ActiveEditorReadonlyContext.bindTo(this.contextKeyService);
this.activeEditorAvailableEditorIds = ActiveEditorAvailableEditorIdsContext.bindTo(this.contextKeyService);
this.editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService);
this.textCompareEditorVisibleContext = TextCompareEditorVisibleContext.bindTo(this.contextKeyService);

View File

@@ -13,12 +13,12 @@ import { IBadge, NumberBadge } from 'vs/workbench/services/activity/common/activ
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
import { ToggleActivityBarVisibilityAction, ToggleMenuBarAction } from 'vs/workbench/browser/actions/layoutActions';
import { ToggleActivityBarVisibilityAction, ToggleMenuBarAction, ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/layoutActions';
import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeService';
import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BORDER } from 'vs/workbench/common/theme';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar';
import { Dimension, addClass, removeNode, createCSSRule, asCSSUrl, toggleClass, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { Dimension, createCSSRule, asCSSUrl, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { URI, UriComponents } from 'vs/base/common/uri';
@@ -181,6 +181,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
actions.push(toggleAccountsVisibilityAction);
actions.push(new Separator());
actions.push(this.instantiationService.createInstance(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.getLabel(this.layoutService)));
actions.push(new Action(
ToggleActivityBarVisibilityAction.ID,
nls.localize('hideActivitBar', "Hide Activity Bar"),
@@ -406,7 +407,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
if (this.menuBarContainer) {
removeNode(this.menuBarContainer);
this.menuBarContainer.remove();
this.menuBarContainer = undefined;
this.registerKeyboardNavigationListeners();
}
@@ -414,7 +415,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
private installMenubar() {
this.menuBarContainer = document.createElement('div');
addClass(this.menuBarContainer, 'menubar');
this.menuBarContainer.classList.add('menubar');
const content = assertIsDefined(this.content);
content.prepend(this.menuBarContainer);
@@ -430,7 +431,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.element = parent;
this.content = document.createElement('div');
addClass(this.content, 'content');
this.content.classList.add('content');
parent.appendChild(this.content);
// Home action bar
@@ -456,7 +457,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
// Global action bar
this.globalActivitiesContainer = document.createElement('div');
addClass(this.globalActivitiesContainer, 'global-activity');
this.globalActivitiesContainer.classList.add('global-activity');
this.content.appendChild(this.globalActivitiesContainer);
this.createGlobalActivityActionBar(this.globalActivitiesContainer);
@@ -537,7 +538,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.homeBarContainer = document.createElement('div');
this.homeBarContainer.setAttribute('aria-label', nls.localize('homeIndicator', "Home"));
this.homeBarContainer.setAttribute('role', 'toolbar');
addClass(this.homeBarContainer, 'home-bar');
this.homeBarContainer.classList.add('home-bar');
this.homeBar = this._register(new ActionBar(this.homeBarContainer, {
orientation: ActionsOrientation.VERTICAL,
@@ -549,7 +550,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}));
const homeBarIconBadge = document.createElement('div');
addClass(homeBarIconBadge, 'home-bar-icon-badge');
homeBarIconBadge.classList.add('home-bar-icon-badge');
this.homeBarContainer.appendChild(homeBarIconBadge);
this.homeBar.push(this._register(this.instantiationService.createInstance(HomeAction, href, title, icon)));
@@ -565,7 +566,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
container.style.backgroundColor = background;
const borderColor = this.getColor(ACTIVITY_BAR_BORDER) || this.getColor(contrastBorder) || '';
toggleClass(container, 'bordered', !!borderColor);
container.classList.toggle('bordered', !!borderColor);
container.style.borderColor = borderColor ? borderColor : '';
}

View File

@@ -12,7 +12,7 @@ import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ActionBar, ActionsOrientation } 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, toggleClass, isAncestor } from 'vs/base/browser/dom';
import { Dimension, $, addDisposableListener, EventType, EventHelper, 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';
@@ -285,8 +285,8 @@ export class CompositeBar extends Widget implements ICompositeBar {
}
private updateFromDragging(element: HTMLElement, showFeedback: boolean, front: boolean): Before2D | undefined {
toggleClass(element, 'dragged-over-head', showFeedback && front);
toggleClass(element, 'dragged-over-tail', showFeedback && !front);
element.classList.toggle('dragged-over-head', showFeedback && front);
element.classList.toggle('dragged-over-tail', showFeedback && !front);
if (!showFeedback) {
return undefined;

View File

@@ -205,7 +205,7 @@ export class ActivityActionViewItem extends BaseActionViewItem {
// Try hard to prevent keyboard only focus feedback when using mouse
this._register(dom.addDisposableListener(this.container, dom.EventType.MOUSE_DOWN, () => {
dom.addClass(this.container, 'clicked');
this.container.classList.add('clicked');
}));
this._register(dom.addDisposableListener(this.container, dom.EventType.MOUSE_UP, () => {
@@ -214,7 +214,7 @@ export class ActivityActionViewItem extends BaseActionViewItem {
}
this.mouseUpTimeout = setTimeout(() => {
dom.removeClass(this.container, 'clicked');
this.container.classList.remove('clicked');
}, 800); // delayed to prevent focus feedback from showing on mouse up
}));
@@ -328,7 +328,7 @@ export class ActivityActionViewItem extends BaseActionViewItem {
if (this.options.icon && !this.activity.iconUrl) {
// Only apply codicon class to activity bar icon items without iconUrl
dom.addClass(this.label, 'codicon');
this.label.classList.add('codicon');
}
if (!this.options.icon) {
@@ -588,10 +588,10 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
const left = forceLeft || (preferLeft && !lastClasses.horizontal) || (!forceRight && lastClasses.horizontal === 'left');
const right = forceRight || (!preferLeft && !lastClasses.horizontal) || (!forceLeft && lastClasses.horizontal === 'right');
dom.toggleClass(element, 'top', showFeedback && top);
dom.toggleClass(element, 'bottom', showFeedback && bottom);
dom.toggleClass(element, 'left', showFeedback && left);
dom.toggleClass(element, 'right', showFeedback && right);
element.classList.toggle('top', showFeedback && top);
element.classList.toggle('bottom', showFeedback && bottom);
element.classList.toggle('left', showFeedback && left);
element.classList.toggle('right', showFeedback && right);
if (!showFeedback) {
return undefined;
@@ -646,11 +646,11 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
protected updateChecked(): void {
if (this.getAction().checked) {
dom.addClass(this.container, 'checked');
this.container.classList.add('checked');
this.container.setAttribute('aria-label', nls.localize('compositeActive', "{0} active", this.container.title));
this.container.setAttribute('aria-expanded', 'true');
} else {
dom.removeClass(this.container, 'checked');
this.container.classList.remove('checked');
this.container.setAttribute('aria-label', this.container.title);
this.container.setAttribute('aria-expanded', 'false');
}
@@ -663,9 +663,9 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
}
if (this.getAction().enabled) {
dom.removeClass(this.element, 'disabled');
this.element.classList.remove('disabled');
} else {
dom.addClass(this.element, 'disabled');
this.element.classList.add('disabled');
}
}

View File

@@ -7,7 +7,6 @@ import 'vs/css!./media/compositepart';
import * as nls from 'vs/nls';
import { defaultGenerator } from 'vs/base/common/idGenerator';
import { IDisposable, dispose, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
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';
@@ -29,7 +28,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachProgressBarStyler } from 'vs/platform/theme/common/styler';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { Dimension, append, $, addClass, hide, show, addClasses } from 'vs/base/browser/dom';
import { Dimension, append, $, hide, show, addClasses } from 'vs/base/browser/dom';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types';
@@ -384,7 +383,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
// Title Area Container
const titleArea = append(parent, $('.composite'));
addClass(titleArea, 'title');
titleArea.classList.add('title');
// Left Title Label
this.titleLabel = this.createTitleLabel(titleArea);
@@ -413,8 +412,8 @@ export abstract class CompositePart<T extends Composite> extends Part {
const $this = this;
return {
updateTitle: (id, title, keybinding) => {
titleLabel.innerHTML = strings.escape(title);
updateTitle: (_id, title, keybinding) => {
titleLabel.innerText = title;
titleLabel.title = keybinding ? nls.localize('titleTooltip', "{0} ({1})", title, keybinding) : title;
},

View File

@@ -7,7 +7,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import * as nls from 'vs/nls';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, EditorPinnedContext, EditorGroupEditorsCountContext, EditorStickyContext, ActiveEditorAvailableEditorIdsContext } from 'vs/workbench/common/editor';
import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, ActiveEditorPinnedContext, EditorGroupEditorsCountContext, ActiveEditorStickyContext, ActiveEditorAvailableEditorIdsContext, MultipleEditorGroupsContext, ActiveEditorDirtyContext } from 'vs/workbench/common/editor';
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
@@ -53,6 +53,7 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess';
import { ActiveGroupEditorsByMostRecentlyUsedQuickAccess, AllEditorsByAppearanceQuickAccess, AllEditorsByMostRecentlyUsedQuickAccess } from 'vs/workbench/browser/parts/editor/editorQuickAccess';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
// Register String Editor
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
@@ -113,7 +114,8 @@ class UntitledTextEditorInputFactory implements IEditorInputFactory {
constructor(
@IFilesConfigurationService private readonly filesConfigurationService: IFilesConfigurationService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IPathService private readonly pathService: IPathService
) { }
canSerialize(editorInput: EditorInput): boolean {
@@ -129,7 +131,7 @@ class UntitledTextEditorInputFactory implements IEditorInputFactory {
let resource = untitledTextEditorInput.resource;
if (untitledTextEditorInput.model.hasAssociatedFilePath) {
resource = toLocalResource(resource, this.environmentService.configuration.remoteAuthority); // untitled with associated file path use the local schema
resource = toLocalResource(resource, this.environmentService.configuration.remoteAuthority, this.pathService.defaultUriScheme); // untitled with associated file path use the local schema
}
// Mode: only remember mode if it is either specific (not text)
@@ -447,9 +449,9 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCo
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: nls.localize('closeAllSaved', "Close Saved") }, group: '1_close', order: 40 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeAll', "Close All") }, group: '1_close', order: 50 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: ReopenResourcesAction.ID, title: ReopenResourcesAction.LABEL }, group: '1_open', order: 10, when: ActiveEditorAvailableEditorIdsContext });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.KEEP_EDITOR_COMMAND_ID, title: nls.localize('keepOpen', "Keep Open"), precondition: EditorPinnedContext.toNegated() }, group: '3_preview', order: 10, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.PIN_EDITOR_COMMAND_ID, title: nls.localize('pin', "Pin") }, group: '3_preview', order: 20, when: ContextKeyExpr.and(EditorStickyContext.toNegated(), ContextKeyExpr.has('config.workbench.editor.showTabs')) });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.UNPIN_EDITOR_COMMAND_ID, title: nls.localize('unpin', "Unpin") }, group: '3_preview', order: 20, when: ContextKeyExpr.and(EditorStickyContext, ContextKeyExpr.has('config.workbench.editor.showTabs')) });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.KEEP_EDITOR_COMMAND_ID, title: nls.localize('keepOpen', "Keep Open"), precondition: ActiveEditorPinnedContext.toNegated() }, group: '3_preview', order: 10, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.PIN_EDITOR_COMMAND_ID, title: nls.localize('pin', "Pin") }, group: '3_preview', order: 20, when: ActiveEditorStickyContext.toNegated() });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.UNPIN_EDITOR_COMMAND_ID, title: nls.localize('unpin', "Unpin") }, group: '3_preview', order: 20, when: ActiveEditorStickyContext });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_UP, title: nls.localize('splitUp', "Split Up") }, group: '5_split', order: 10 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_DOWN, title: nls.localize('splitDown', "Split Down") }, group: '5_split', order: 20 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_LEFT, title: nls.localize('splitLeft', "Split Left") }, group: '5_split', order: 30 });
@@ -518,14 +520,14 @@ appendEditorToolItem(
}
);
// Editor Title Menu: Close Group (tabs disabled)
// Editor Title Menu: Close (tabs disabled, dirty editor)
appendEditorToolItem(
{
id: editorCommands.CLOSE_EDITOR_COMMAND_ID,
title: nls.localize('close', "Close"),
icon: { id: 'codicon/close' }
icon: { id: 'codicon/close-dirty' }
},
ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ContextKeyExpr.not('groupActiveEditorDirty')),
ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ActiveEditorDirtyContext),
1000000, // towards the far end
{
id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID,
@@ -534,13 +536,30 @@ appendEditorToolItem(
}
);
// Editor Title Menu: Close (tabs disabled, sticky editor)
appendEditorToolItem(
{
id: editorCommands.UNPIN_EDITOR_COMMAND_ID,
title: nls.localize('unpin', "Unpin"),
icon: { id: 'codicon/pinned' }
},
ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ActiveEditorDirtyContext.toNegated(), ActiveEditorStickyContext),
1000000, // towards the far end
{
id: editorCommands.CLOSE_EDITOR_COMMAND_ID,
title: nls.localize('close', "Close"),
icon: { id: 'codicon/close' }
}
);
// Editor Title Menu: Unpin (tabs disabled, normal editor)
appendEditorToolItem(
{
id: editorCommands.CLOSE_EDITOR_COMMAND_ID,
title: nls.localize('close', "Close"),
icon: { id: 'codicon/close-dirty' }
icon: { id: 'codicon/close' }
},
ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ContextKeyExpr.has('groupActiveEditorDirty')),
ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ActiveEditorDirtyContext.toNegated(), ActiveEditorStickyContext.toNegated()),
1000000, // towards the far end
{
id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID,
@@ -596,12 +615,15 @@ appendEditorToolItem(
// Editor Commands for Command Palette
const viewCategory = { value: nls.localize('view', "View"), original: 'View' };
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.KEEP_EDITOR_COMMAND_ID, title: { value: nls.localize('keepEditor', "Keep Editor"), original: 'Keep Editor' }, category: viewCategory }, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.PIN_EDITOR_COMMAND_ID, title: { value: nls.localize('pinEditor', "Pin Editor"), original: 'Pin Editor' }, category: viewCategory }, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.UNPIN_EDITOR_COMMAND_ID, title: { value: nls.localize('unpinEditor', "Unpin Editor"), original: 'Unpin Editor' }, category: viewCategory }, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.PIN_EDITOR_COMMAND_ID, title: { value: nls.localize('pinEditor', "Pin Editor"), original: 'Pin Editor' }, category: viewCategory } });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.UNPIN_EDITOR_COMMAND_ID, title: { value: nls.localize('unpinEditor', "Unpin Editor"), original: 'Unpin Editor' }, category: viewCategory } });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_EDITOR_COMMAND_ID, title: { value: nls.localize('closeEditor', "Close Editor"), original: 'Close Editor' }, category: viewCategory } });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_PINNED_EDITOR_COMMAND_ID, title: { value: nls.localize('closePinnedEditor', "Close Pinned Editor"), original: 'Close Pinned Editor' }, category: viewCategory } });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: { value: nls.localize('closeEditorsInGroup', "Close All Editors in Group"), original: 'Close All Editors in Group' }, category: viewCategory } });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: { value: nls.localize('closeSavedEditors', "Close Saved Editors in Group"), original: 'Close Saved Editors in Group' }, category: viewCategory } });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID, title: { value: nls.localize('closeOtherEditors', "Close Other Editors in Group"), original: 'Close Other Editors in Group' }, category: viewCategory } });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID, title: { value: nls.localize('closeRightEditors', "Close Editors to the Right in Group"), original: 'Close Editors to the Right in Group' }, category: viewCategory } });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_EDITORS_AND_GROUP_COMMAND_ID, title: { value: nls.localize('closeEditorGroup', "Close Editor Group"), original: 'Close Editor Group' }, category: viewCategory }, when: MultipleEditorGroupsContext });
// File menu
MenuRegistry.appendMenuItem(MenuId.MenubarRecentMenu, {

View File

@@ -30,6 +30,7 @@ export const DEFAULT_EDITOR_PART_OPTIONS: IEditorPartOptions = {
highlightModifiedTabs: false,
tabCloseButton: 'right',
tabSizing: 'fit',
pinnedTabSizing: 'shrink',
titleScrollbarSizing: 'default',
focusRecentEditorAfterClose: true,
showIcons: true,

View File

@@ -10,7 +10,7 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la
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, 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 { 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, UNPIN_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands';
import { IEditorGroupsService, IEditorGroup, GroupsArrangement, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder, OpenEditorContext } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -406,6 +406,24 @@ export class CloseEditorAction extends Action {
}
}
export class UnpinEditorAction extends Action {
static readonly ID = 'workbench.action.unpinActiveEditor';
static readonly LABEL = nls.localize('unpinEditor', "Unpin Editor");
constructor(
id: string,
label: string,
@ICommandService private readonly commandService: ICommandService
) {
super(id, label, Codicon.pinned.classNames);
}
run(context?: IEditorCommandsContext): Promise<void> {
return this.commandService.executeCommand(UNPIN_EDITOR_COMMAND_ID, undefined, context);
}
}
export class CloseOneEditorAction extends Action {
static readonly ID = 'workbench.action.closeActiveEditor';

View File

@@ -4,10 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import * as types from 'vs/base/common/types';
import { isObject, isString, isUndefined, isNumber, withNullAsUndefined } from 'vs/base/common/types';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { TextCompareEditorVisibleContext, EditorInput, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditorInput, IVisibleEditorPane, EditorStickyContext, EditorsOrder } from 'vs/workbench/common/editor';
import { TextCompareEditorVisibleContext, EditorInput, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditorInput, IVisibleEditorPane, ActiveEditorStickyContext, EditorsOrder } from 'vs/workbench/common/editor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor';
@@ -29,6 +29,7 @@ export const CLOSE_EDITORS_IN_GROUP_COMMAND_ID = 'workbench.action.closeEditorsI
export const CLOSE_EDITORS_AND_GROUP_COMMAND_ID = 'workbench.action.closeEditorsAndGroup';
export const CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID = 'workbench.action.closeEditorsToTheRight';
export const CLOSE_EDITOR_COMMAND_ID = 'workbench.action.closeActiveEditor';
export const CLOSE_PINNED_EDITOR_COMMAND_ID = 'workbench.action.closeActivePinnedEditor';
export const CLOSE_EDITOR_GROUP_COMMAND_ID = 'workbench.action.closeGroup';
export const CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID = 'workbench.action.closeOtherEditors';
@@ -59,19 +60,19 @@ export interface ActiveEditorMoveArguments {
}
const isActiveEditorMoveArg = function (arg: ActiveEditorMoveArguments): boolean {
if (!types.isObject(arg)) {
if (!isObject(arg)) {
return false;
}
if (!types.isString(arg.to)) {
if (!isString(arg.to)) {
return false;
}
if (!types.isUndefined(arg.by) && !types.isString(arg.by)) {
if (!isUndefined(arg.by) && !isString(arg.by)) {
return false;
}
if (!types.isUndefined(arg.value) && !types.isNumber(arg.value)) {
if (!isUndefined(arg.value) && !isNumber(arg.value)) {
return false;
}
@@ -451,7 +452,7 @@ export function splitEditor(editorGroupService: IEditorGroupsService, direction:
if (context && typeof context.editorIndex === 'number') {
editorToCopy = sourceGroup.getEditorByIndex(context.editorIndex);
} else {
editorToCopy = types.withNullAsUndefined(sourceGroup.activeEditor);
editorToCopy = withNullAsUndefined(sourceGroup.activeEditor);
}
if (editorToCopy && (editorToCopy as EditorInput).supportsSplitEditor()) {
@@ -469,7 +470,7 @@ function registerSplitEditorCommands() {
{ id: SPLIT_EDITOR_LEFT, direction: GroupDirection.LEFT },
{ id: SPLIT_EDITOR_RIGHT, direction: GroupDirection.RIGHT }
].forEach(({ id, direction }) => {
CommandsRegistry.registerCommand(id, function (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) {
CommandsRegistry.registerCommand(id, function (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) {
splitEditor(accessor.get(IEditorGroupsService), direction, getCommandsContext(resourceOrContext, context));
});
});
@@ -477,51 +478,55 @@ function registerSplitEditorCommands() {
function registerCloseEditorCommands() {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_SAVED_EDITORS_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_U),
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const contexts = getMultiSelectedEditorContexts(getCommandsContext(resourceOrContext, context), accessor.get(IListService), editorGroupService);
// A special handler for "Close Editor" depending on context
// - keybindining: do not close sticky editors, rather open the next non-sticky editor
// - menu: always close editor, even sticky ones
function closeEditorHandler(accessor: ServicesAccessor, forceCloseStickyEditors: boolean, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext): Promise<unknown> {
const editorGroupsService = accessor.get(IEditorGroupsService);
const editorService = accessor.get(IEditorService);
const activeGroup = editorGroupService.activeGroup;
if (contexts.length === 0) {
contexts.push({ groupId: activeGroup.id }); // active group as fallback
}
return Promise.all(distinct(contexts.map(c => c.groupId)).map(async groupId => {
const group = editorGroupService.getGroup(groupId);
if (group) {
return group.closeEditors({ savedOnly: true, excludeSticky: true });
}
}));
let keepStickyEditors = true;
if (forceCloseStickyEditors) {
keepStickyEditors = false; // explicitly close sticky editors
} else if (resourceOrContext || context) {
keepStickyEditors = false; // we have a context, as such this command was used e.g. from the tab context menu
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_EDITORS_IN_GROUP_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_W),
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const contexts = getMultiSelectedEditorContexts(getCommandsContext(resourceOrContext, context), accessor.get(IListService), editorGroupService);
const distinctGroupIds = distinct(contexts.map(c => c.groupId));
// Without context: skip over sticky editor and select next if active editor is sticky
if (keepStickyEditors && !resourceOrContext && !context) {
const activeGroup = editorGroupsService.activeGroup;
const activeEditor = activeGroup.activeEditor;
if (distinctGroupIds.length === 0) {
distinctGroupIds.push(editorGroupService.activeGroup.id);
}
if (activeEditor && activeGroup.isSticky(activeEditor)) {
return Promise.all(distinctGroupIds.map(async groupId => {
const group = editorGroupService.getGroup(groupId);
if (group) {
return group.closeAllEditors({ excludeSticky: true });
// Open next recently active in same group
const nextNonStickyEditorInGroup = activeGroup.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE, { excludeSticky: true })[0];
if (nextNonStickyEditorInGroup) {
return activeGroup.openEditor(nextNonStickyEditorInGroup);
}
}));
// Open next recently active across all groups
const nextNonStickyEditorInAllGroups = editorService.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE, { excludeSticky: true })[0];
if (nextNonStickyEditorInAllGroups) {
return Promise.resolve(editorGroupsService.getGroup(nextNonStickyEditorInAllGroups.groupId)?.openEditor(nextNonStickyEditorInAllGroups.editor));
}
}
}
});
// With context: proceed to close editors as instructed
const { editors, groups } = getEditorsContext(accessor, resourceOrContext, context);
return Promise.all(groups.map(async group => {
if (group) {
const editorsToClose = coalesce(editors
.filter(editor => editor.groupId === group.id)
.map(editor => typeof editor.editorIndex === 'number' ? group.getEditorByIndex(editor.editorIndex) : group.activeEditor))
.filter(editor => !keepStickyEditors || !group.isSticky(editor));
return group.closeEditors(editorsToClose);
}
}));
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_EDITOR_COMMAND_ID,
@@ -529,25 +534,24 @@ function registerCloseEditorCommands() {
when: undefined,
primary: KeyMod.CtrlCmd | KeyCode.KEY_W,
win: { primary: KeyMod.CtrlCmd | KeyCode.F4, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_W] },
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const contexts = getMultiSelectedEditorContexts(getCommandsContext(resourceOrContext, context), accessor.get(IListService), editorGroupService);
handler: (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
return closeEditorHandler(accessor, false, resourceOrContext, context);
}
});
const activeGroup = editorGroupService.activeGroup;
if (contexts.length === 0 && activeGroup.activeEditor) {
contexts.push({ groupId: activeGroup.id, editorIndex: activeGroup.getIndexOfEditor(activeGroup.activeEditor) }); // active editor as fallback
}
CommandsRegistry.registerCommand(CLOSE_PINNED_EDITOR_COMMAND_ID, (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
return closeEditorHandler(accessor, true /* force close pinned editors */, resourceOrContext, context);
});
const groupIds = distinct(contexts.map(context => context.groupId));
return Promise.all(groupIds.map(async groupId => {
const group = editorGroupService.getGroup(groupId);
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_EDITORS_IN_GROUP_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_W),
handler: (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
return Promise.all(getEditorsContext(accessor, resourceOrContext, context).groups.map(async group => {
if (group) {
const editors = coalesce(contexts
.filter(context => context.groupId === groupId)
.map(context => typeof context.editorIndex === 'number' ? group.getEditorByIndex(context.editorIndex) : group.activeEditor));
return group.closeEditors(editors);
return group.closeAllEditors({ excludeSticky: true });
}
}));
}
@@ -559,7 +563,7 @@ function registerCloseEditorCommands() {
when: ContextKeyExpr.and(ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext),
primary: KeyMod.CtrlCmd | KeyCode.KEY_W,
win: { primary: KeyMod.CtrlCmd | KeyCode.F4, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_W] },
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
handler: (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const commandsContext = getCommandsContext(resourceOrContext, context);
@@ -576,34 +580,40 @@ function registerCloseEditorCommands() {
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_SAVED_EDITORS_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_U),
handler: (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
return Promise.all(getEditorsContext(accessor, resourceOrContext, context).groups.map(async group => {
if (group) {
return group.closeEditors({ savedOnly: true, excludeSticky: true });
}
}));
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: undefined,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_T },
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const contexts = getMultiSelectedEditorContexts(getCommandsContext(resourceOrContext, context), accessor.get(IListService), editorGroupService);
const activeGroup = editorGroupService.activeGroup;
if (contexts.length === 0 && activeGroup.activeEditor) {
contexts.push({ groupId: activeGroup.id, editorIndex: activeGroup.getIndexOfEditor(activeGroup.activeEditor) }); // active editor as fallback
}
const groupIds = distinct(contexts.map(context => context.groupId));
return Promise.all(groupIds.map(async groupId => {
const group = editorGroupService.getGroup(groupId);
handler: (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const { editors, groups } = getEditorsContext(accessor, resourceOrContext, context);
return Promise.all(groups.map(async group => {
if (group) {
const editors = contexts
.filter(context => context.groupId === groupId)
.map(context => typeof context.editorIndex === 'number' ? group.getEditorByIndex(context.editorIndex) : group.activeEditor);
const editorsToKeep = editors
.filter(editor => editor.groupId === group.id)
.map(editor => typeof editor.editorIndex === 'number' ? group.getEditorByIndex(editor.editorIndex) : group.activeEditor);
const editorsToClose = group.getEditors(EditorsOrder.SEQUENTIAL, { excludeSticky: true }).filter(editor => !editors.includes(editor));
const editorsToClose = group.getEditors(EditorsOrder.SEQUENTIAL, { excludeSticky: true }).filter(editor => !editorsToKeep.includes(editor));
if (group.activeEditor) {
group.pinEditor(group.activeEditor);
for (const editorToKeep of editorsToKeep) {
if (editorToKeep) {
group.pinEditor(editorToKeep);
}
}
return group.closeEditors(editorsToClose);
@@ -617,7 +627,7 @@ function registerCloseEditorCommands() {
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: undefined,
handler: async (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
handler: async (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const { group, editor } = resolveCommandsContext(editorGroupService, getCommandsContext(resourceOrContext, context));
@@ -631,12 +641,28 @@ function registerCloseEditorCommands() {
}
});
CommandsRegistry.registerCommand(CLOSE_EDITORS_AND_GROUP_COMMAND_ID, async (accessor: ServicesAccessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const { group } = resolveCommandsContext(editorGroupService, getCommandsContext(resourceOrContext, context));
if (group) {
await group.closeAllEditors();
if (group.count === 0 && editorGroupService.getGroup(group.id) /* could be gone by now */) {
editorGroupService.removeGroup(group); // only remove group if it is now empty
}
}
});
}
function registerOtherEditorCommands(): void {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: KEEP_EDITOR_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.Enter),
handler: async (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
handler: async (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const { group, editor } = resolveCommandsContext(editorGroupService, getCommandsContext(resourceOrContext, context));
@@ -649,9 +675,9 @@ function registerCloseEditorCommands() {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: PIN_EDITOR_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(EditorStickyContext.toNegated(), ContextKeyExpr.has('config.workbench.editor.showTabs')),
when: ActiveEditorStickyContext.toNegated(),
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.Shift | KeyCode.Enter),
handler: async (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
handler: async (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const { group, editor } = resolveCommandsContext(editorGroupService, getCommandsContext(resourceOrContext, context));
@@ -664,9 +690,9 @@ function registerCloseEditorCommands() {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: UNPIN_EDITOR_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(EditorStickyContext, ContextKeyExpr.has('config.workbench.editor.showTabs')),
when: ActiveEditorStickyContext,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.Shift | KeyCode.Enter),
handler: async (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
handler: async (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const { group, editor } = resolveCommandsContext(editorGroupService, getCommandsContext(resourceOrContext, context));
@@ -681,7 +707,7 @@ function registerCloseEditorCommands() {
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: undefined,
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
handler: (accessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const quickInputService = accessor.get(IQuickInputService);
@@ -696,22 +722,30 @@ function registerCloseEditorCommands() {
return quickInputService.quickAccess.show(ActiveGroupEditorsByMostRecentlyUsedQuickAccess.PREFIX);
}
});
CommandsRegistry.registerCommand(CLOSE_EDITORS_AND_GROUP_COMMAND_ID, async (accessor: ServicesAccessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const { group } = resolveCommandsContext(editorGroupService, getCommandsContext(resourceOrContext, context));
if (group) {
await group.closeAllEditors();
if (group.count === 0 && editorGroupService.getGroup(group.id) /* could be gone by now */) {
editorGroupService.removeGroup(group); // only remove group if it is now empty
}
}
});
}
function getCommandsContext(resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext): IEditorCommandsContext | undefined {
function getEditorsContext(accessor: ServicesAccessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext): { editors: IEditorCommandsContext[], groups: Array<IEditorGroup | undefined> } {
const editorGroupService = accessor.get(IEditorGroupsService);
const listService = accessor.get(IListService);
const editorContext = getMultiSelectedEditorContexts(getCommandsContext(resourceOrContext, context), listService, editorGroupService);
const activeGroup = editorGroupService.activeGroup;
if (editorContext.length === 0 && activeGroup.activeEditor) {
// add the active editor as fallback
editorContext.push({
groupId: activeGroup.id,
editorIndex: activeGroup.getIndexOfEditor(activeGroup.activeEditor)
});
}
return {
editors: editorContext,
groups: distinct(editorContext.map(context => context.groupId)).map(groupId => editorGroupService.getGroup(groupId))
};
}
function getCommandsContext(resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext): IEditorCommandsContext | undefined {
if (URI.isUri(resourceOrContext)) {
return context;
}
@@ -731,12 +765,16 @@ function resolveCommandsContext(editorGroupService: IEditorGroupsService, contex
// Resolve from context
let group = context && typeof context.groupId === 'number' ? editorGroupService.getGroup(context.groupId) : undefined;
let editor = group && context && typeof context.editorIndex === 'number' ? types.withNullAsUndefined(group.getEditorByIndex(context.editorIndex)) : undefined;
let editor = group && context && typeof context.editorIndex === 'number' ? withNullAsUndefined(group.getEditorByIndex(context.editorIndex)) : undefined;
// Fallback to active group as needed
if (!group) {
group = editorGroupService.activeGroup;
editor = <EditorInput>group.activeEditor;
}
// Fallback to active editor as needed
if (!editor) {
editor = withNullAsUndefined(group.activeEditor);
}
return { group, editor };
@@ -803,6 +841,7 @@ export function setup(): void {
registerDiffEditorCommands();
registerOpenEditorAtIndexCommands();
registerCloseEditorCommands();
registerOtherEditorCommands();
registerFocusEditorGroupAtIndexCommands();
registerSplitEditorCommands();
}

View File

@@ -5,7 +5,7 @@
import 'vs/css!./media/editorgroupview';
import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup';
import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, EditorStickyContext, EditorPinnedContext } from 'vs/workbench/common/editor';
import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, Deprecated_EditorPinnedContext, Deprecated_EditorDirtyContext } from 'vs/workbench/common/editor';
import { Event, Emitter, Relay } from 'vs/base/common/event';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { addClass, addClasses, Dimension, trackFocus, toggleClass, removeClass, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom';
@@ -217,10 +217,12 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
private handleGroupContextKeys(contextKeyService: IContextKeyService): void {
const groupActiveEditorDirtyContextKey = EditorGroupActiveEditorDirtyContext.bindTo(contextKeyService);
const groupActiveEditorDirtyContext = ActiveEditorDirtyContext.bindTo(contextKeyService);
const deprecatedGroupActiveEditorDirtyContext = Deprecated_EditorDirtyContext.bindTo(contextKeyService);
const groupActiveEditorPinnedContext = ActiveEditorPinnedContext.bindTo(contextKeyService);
const deprecatedGroupActiveEditorPinnedContext = Deprecated_EditorPinnedContext.bindTo(contextKeyService);
const groupActiveEditorStickyContext = ActiveEditorStickyContext.bindTo(contextKeyService);
const groupEditorsCountContext = EditorGroupEditorsCountContext.bindTo(contextKeyService);
const groupActiveEditorPinnedContext = EditorPinnedContext.bindTo(contextKeyService);
const groupActiveEditorStickyContext = EditorStickyContext.bindTo(contextKeyService);
const activeEditorListener = new MutableDisposable();
@@ -229,10 +231,15 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
const activeEditor = this._group.activeEditor;
if (activeEditor) {
groupActiveEditorDirtyContextKey.set(activeEditor.isDirty() && !activeEditor.isSaving());
activeEditorListener.value = activeEditor.onDidChangeDirty(() => groupActiveEditorDirtyContextKey.set(activeEditor.isDirty() && !activeEditor.isSaving()));
groupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving());
deprecatedGroupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving());
activeEditorListener.value = activeEditor.onDidChangeDirty(() => {
groupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving());
deprecatedGroupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving());
});
} else {
groupActiveEditorDirtyContextKey.set(false);
groupActiveEditorDirtyContext.set(false);
deprecatedGroupActiveEditorDirtyContext.set(false);
}
};
@@ -247,6 +254,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
case GroupChangeKind.EDITOR_PIN:
if (e.editor && e.editor === this._group.activeEditor) {
groupActiveEditorPinnedContext.set(this._group.isPinned(this._group.activeEditor));
deprecatedGroupActiveEditorPinnedContext.set(this._group.isPinned(this._group.activeEditor));
}
break;
case GroupChangeKind.EDITOR_STICKY:
@@ -294,7 +302,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Toolbar
const groupId = this._group.id;
const containerToolbar = this._register(new ActionBar(toolbarContainer, {
ariaLabel: localize('araLabelGroupActions', "Editor group actions"), actionRunner: this._register(new class extends ActionRunner {
ariaLabel: localize('ariaLabelGroupActions', "Editor group actions"), actionRunner: this._register(new class extends ActionRunner {
run(action: IAction) {
return action.run(groupId);
}

View File

@@ -62,9 +62,9 @@
padding-left: 10px;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.close-button-right,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.close-button-off:not(.sticky) {
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab close button is not left (unless sticky) */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-right,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-off:not(.sticky-compact) {
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab actions is not left (unless sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit {
@@ -75,50 +75,67 @@
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink {
min-width: 60px;
min-width: 80px;
flex-basis: 0; /* all tabs are even */
flex-grow: 1; /* all tabs grow even */
max-width: fit-content;
max-width: -moz-fit-content;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky-shrink,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-shrink {
/** Sticky tabs do not scroll in case of overflow and are always above unsticky tabs which scroll under */
/** Sticky compact/shrink tabs do not scroll in case of overflow and are always above unsticky tabs which scroll under */
position: sticky;
z-index: 1;
/** Sticky tabs are even and never grow */
/** Sticky compact/shrink tabs are even and never grow */
flex-basis: 0;
flex-grow: 0;
}
/** Sticky tabs have a fixed width of 38px */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-compact {
/** Sticky compact tabs have a fixed width of 38px */
width: 38px;
min-width: 38px;
max-width: 38px;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fit.sticky,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-shrink.sticky {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky-shrink,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-shrink {
/** Disable sticky positions for sticky tabs if the available space is too little */
/** Sticky shrink tabs have a fixed width of 80px */
width: 80px;
min-width: 80px;
max-width: 80px;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fit.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-shrink.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fit.sticky-shrink,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-shrink.sticky-shrink {
/** Disable sticky positions for sticky compact/shrink tabs if the available space is too little */
position: static;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-left .action-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-left .action-label {
margin-right: 4px !important;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-left::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off::after {
content: '';
display: flex;
flex: 0;
width: 5px; /* Reserve space to hide tab fade when close button is left or off (fixes https://github.com/Microsoft/vscode/issues/45728) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-left {
min-width: 80px; /* make more room for close button when it shows to the left */
padding-right: 5px; /* we need less room when sizing is shrink */
}
@@ -131,7 +148,7 @@
pointer-events: none; /* prevents cursor flickering (fixes https://github.com/Microsoft/vscode/issues/38753) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-left {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-left {
flex-direction: row-reverse;
padding-left: 0;
padding-right: 10px;
@@ -178,6 +195,7 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label {
margin-top: auto;
margin-bottom: auto;
line-height: 35px; /* aligns icon and label vertically centered in the tab */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink .tab-label {
@@ -198,8 +216,8 @@
opacity: 0; /* when tab has the focus this shade breaks the tab border (fixes https://github.com/Microsoft/vscode/issues/57819) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky:not(.has-icon) .monaco-icon-label {
text-align: center; /* ensure that sticky tabs without icon have label centered */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky-compact:not(.has-icon) .monaco-icon-label {
text-align: center; /* ensure that sticky-compact tabs without icon have label centered */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label,
@@ -215,61 +233,57 @@
text-overflow: ellipsis;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .monaco-icon-label::before {
height: 16px; /* tweak the icon size of the editor labels when icons are enabled */
}
/* Tab Actions */
/* Tab Close */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-actions {
margin-top: auto;
margin-bottom: auto;
width: 28px;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink > .tab-actions {
flex: 0;
overflow: hidden; /* let the close button be pushed out of view when sizing is set to shrink to make more room... */
overflow: hidden; /* let the tab actions be pushed out of view when sizing is set to shrink to make more room... */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty.close-button-right.sizing-shrink > .tab-close,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink:hover > .tab-close,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close:focus-within {
overflow: visible; /* ...but still show the close button on hover, focus and when dirty */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty.tab-actions-right.sizing-shrink > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink:hover > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink > .tab-actions:focus-within {
overflow: visible; /* ...but still show the tab actions on hover, focus and when dirty */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off:not(.dirty) > .tab-close,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.sticky > .tab-close {
display: none; /* hide the close action bar when we are configured to hide it (unless dirty, but always when sticky) */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off:not(.dirty) > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.sticky-compact > .tab-actions {
display: none; /* hide the tab actions when we are configured to hide it (unless dirty, but always when sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-close .action-label, /* always show it for active tab */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-close .action-label:focus, /* always show it on focus */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-close .action-label, /* always show it on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* always show it on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-close .action-label { /* always show it for dirty tabs */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-actions .action-label, /* always show tab actions for active tab */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-actions .action-label:focus, /* always show tab actions on focus */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-actions .action-label, /* always show tab actions on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-actions .action-label, /* always show tab actions on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-actions .action-label { /* always show tab actions for dirty tabs */
opacity: 1;
}
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-close .action-label.codicon {
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-actions .action-label.codicon {
color: inherit;
font-size: 16px;
}
/* change close icon to dirty state icon */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-close .action-label:not(:hover)::before,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label:not(:hover)::before {
/* change tab actions icon to dirty state icon if tab dirty */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-actions .action-label:not(:hover)::before,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-actions .action-label:not(:hover)::before {
content: "\ea71"; /* use `circle-filled` icon unicode */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label { /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-actions .action-label, /* show tab actions dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-actions .action-label, /* show tab actions dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-actions .action-label, /* show tab actions dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-actions .action-label { /* show tab actions dimmed for inactive group */
opacity: 0.5;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close .action-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-actions .action-label {
opacity: 0;
display: block;
height: 16px;
@@ -280,26 +294,26 @@
margin-right: 0.5em;
}
/* No Tab Close Button */
/* No Tab Actions */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off {
padding-right: 10px; /* give a little bit more room if close button is off */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off {
padding-right: 10px; /* give a little bit more room if tab actions is off */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off:not(.sticky) {
padding-right: 5px; /* we need less room when sizing is shrink (unless tab is sticky) */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off:not(.sticky-compact) {
padding-right: 5px; /* we need less room when sizing is shrink (unless tab is sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty-border-top > .tab-close {
display: none; /* hide dirty state when highlightModifiedTabs is enabled and when running without close button */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.dirty-border-top > .tab-actions {
display: none; /* hide dirty state when highlightModifiedTabs is enabled and when running without tab actions */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty:not(.dirty-border-top):not(.sticky) {
padding-right: 0; /* remove extra padding when we are running without close button (unless tab is sticky) */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.dirty:not(.dirty-border-top):not(.sticky-compact) {
padding-right: 0; /* remove extra padding when we are running without tab actions (unless tab is sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off > .tab-close {
pointer-events: none; /* don't allow dirty state/close button to be clicked when running without close button */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off > .tab-actions {
pointer-events: none; /* don't allow tab actions to be clicked when running without tab actions */
}
/* Editor Actions */

View File

@@ -68,7 +68,7 @@ export class SideBySideEditor extends EditorPane {
}
protected createEditor(parent: HTMLElement): void {
DOM.addClass(parent, 'side-by-side-editor');
parent.classList.add('side-by-side-editor');
const splitview = this.splitview = this._register(new SplitView(parent, { orientation: Orientation.HORIZONTAL }));
this._register(this.splitview.onDidSashReset(() => splitview.distributeViewSizes()));

View File

@@ -20,12 +20,12 @@ 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 { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { IDisposable, dispose, DisposableStore, combinedDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, dispose, DisposableStore, combinedDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { getOrSet } from 'vs/base/common/map';
import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_BACKGROUND, TAB_UNFOCUSED_ACTIVE_BORDER, TAB_ACTIVE_BORDER, TAB_HOVER_BACKGROUND, TAB_HOVER_BORDER, TAB_UNFOCUSED_HOVER_BACKGROUND, TAB_UNFOCUSED_HOVER_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, WORKBENCH_BACKGROUND, TAB_ACTIVE_BORDER_TOP, TAB_UNFOCUSED_ACTIVE_BORDER_TOP, TAB_ACTIVE_MODIFIED_BORDER, TAB_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_ACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_BACKGROUND, TAB_HOVER_FOREGROUND, TAB_UNFOCUSED_HOVER_FOREGROUND, EDITOR_GROUP_HEADER_TABS_BORDER } from 'vs/workbench/common/theme';
import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_BACKGROUND, TAB_UNFOCUSED_ACTIVE_BORDER, TAB_ACTIVE_BORDER, TAB_HOVER_BACKGROUND, TAB_HOVER_BORDER, TAB_UNFOCUSED_HOVER_BACKGROUND, TAB_UNFOCUSED_HOVER_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, WORKBENCH_BACKGROUND, TAB_ACTIVE_BORDER_TOP, TAB_UNFOCUSED_ACTIVE_BORDER_TOP, TAB_ACTIVE_MODIFIED_BORDER, TAB_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_ACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_BACKGROUND, TAB_HOVER_FOREGROUND, TAB_UNFOCUSED_HOVER_FOREGROUND, EDITOR_GROUP_HEADER_TABS_BORDER, TAB_LAST_PINNED_BORDER } from 'vs/workbench/common/theme';
import { activeContrastBorder, contrastBorder, editorBackground, breadcrumbsBackground } from 'vs/platform/theme/common/colorRegistry';
import { ResourcesDropHandler, DraggedEditorIdentifier, DraggedEditorGroupIdentifier, DragAndDropObserver } from 'vs/workbench/browser/dnd';
import { Color } from 'vs/base/common/color';
@@ -35,7 +35,7 @@ import { MergeGroupMode, IMergeGroupOptions, GroupsArrangement, IEditorGroupsSer
import { addClass, addDisposableListener, hasClass, EventType, EventHelper, removeClass, Dimension, scheduleAtNextAnimationFrame, findParentWithClass, clearNode } from 'vs/base/browser/dom';
import { localize } from 'vs/nls';
import { IEditorGroupsAccessor, IEditorGroupView, EditorServiceImpl, EDITOR_TITLE_HEIGHT } from 'vs/workbench/browser/parts/editor/editor';
import { CloseOneEditorAction } from 'vs/workbench/browser/parts/editor/editorActions';
import { CloseOneEditorAction, UnpinEditorAction } from 'vs/workbench/browser/parts/editor/editorActions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { BreadcrumbsControl } from 'vs/workbench/browser/parts/editor/breadcrumbsControl';
import { IFileService } from 'vs/platform/files/common/files';
@@ -45,6 +45,8 @@ import { basenameOrAuthority } from 'vs/base/common/resources';
import { RunOnceScheduler } from 'vs/base/common/async';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
import { IPath, win32, posix } from 'vs/base/common/path';
import { insert } from 'vs/base/common/arrays';
import { ColorScheme } from 'vs/platform/theme/common/theme';
// {{SQL CARBON EDIT}} -- Display the editor's tab color
import { IQueryEditorConfiguration } from 'sql/platform/query/common/query';
@@ -67,7 +69,8 @@ export class TabsTitleControl extends TitleControl {
};
private static readonly TAB_SIZES = {
sticky: 38,
compact: 38,
shrink: 80,
fit: 120
};
@@ -77,10 +80,12 @@ export class TabsTitleControl extends TitleControl {
private editorToolbarContainer: HTMLElement | undefined;
private tabsScrollbar: ScrollableElement | undefined;
private closeOneEditorAction: CloseOneEditorAction;
private readonly closeEditorAction = this._register(this.instantiationService.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL));
private readonly unpinEditorAction = this._register(this.instantiationService.createInstance(UnpinEditorAction, UnpinEditorAction.ID, UnpinEditorAction.LABEL));
private tabResourceLabels: ResourceLabels;
private readonly tabResourceLabels = this._register(this.instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER));
private tabLabels: IEditorInputLabel[] = [];
private tabActionBars: ActionBar[] = [];
private tabDisposables: IDisposable[] = [];
private dimension: Dimension | undefined;
@@ -111,9 +116,6 @@ export class TabsTitleControl extends TitleControl {
) {
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));
// Resolve the correct path library for the OS we are on
// If we are connected to remote, this accounts for the
// remote OS.
@@ -429,6 +431,7 @@ export class TabsTitleControl extends TitleControl {
this.tabDisposables = dispose(this.tabDisposables);
this.tabResourceLabels.clear();
this.tabLabels = [];
this.tabActionBars = [];
this.clearEditorActionsToolbar();
}
@@ -442,8 +445,8 @@ export class TabsTitleControl extends TitleControl {
this.tabLabels.splice(targetIndex, 0, editorLabel);
// As such we need to redraw each tab
this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel) => {
this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel);
this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar) => {
this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar);
});
// Moving an editor requires a layout to keep the active editor visible
@@ -465,7 +468,7 @@ export class TabsTitleControl extends TitleControl {
private doHandleStickyEditorChange(editor: IEditorInput): void {
// Update tab
this.withTab(editor, (editor, index, tabContainer, tabLabelWidget, tabLabel) => this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel));
this.withTab(editor, (editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar) => this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar));
// A change to the sticky state requires a layout to keep the active editor visible
this.layout(this.dimension);
@@ -525,6 +528,7 @@ export class TabsTitleControl extends TitleControl {
oldOptions.labelFormat !== newOptions.labelFormat ||
oldOptions.tabCloseButton !== newOptions.tabCloseButton ||
oldOptions.tabSizing !== newOptions.tabSizing ||
oldOptions.pinnedTabSizing !== newOptions.pinnedTabSizing ||
oldOptions.showIcons !== newOptions.showIcons ||
oldOptions.hasIcons !== newOptions.hasIcons ||
oldOptions.highlightModifiedTabs !== newOptions.highlightModifiedTabs
@@ -537,23 +541,24 @@ export class TabsTitleControl extends TitleControl {
this.redraw();
}
private forEachTab(fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void {
private forEachTab(fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel, tabActionBar: ActionBar) => void): void {
this.group.editors.forEach((editor, index) => {
this.doWithTab(index, editor, fn);
});
}
private withTab(editor: IEditorInput, fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void {
private withTab(editor: IEditorInput, fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel, tabActionBar: ActionBar) => void): void {
this.doWithTab(this.group.getIndexOfEditor(editor), editor, fn);
}
private doWithTab(index: number, editor: IEditorInput, fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void {
private doWithTab(index: number, editor: IEditorInput, fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel, tabActionBar: ActionBar) => void): void {
const tabsContainer = assertIsDefined(this.tabsContainer);
const tabContainer = tabsContainer.children[index] as HTMLElement;
const tabResourceLabel = this.tabResourceLabels.get(index);
const tabLabel = this.tabLabels[index];
const tabActionBar = this.tabActionBars[index];
if (tabContainer && tabResourceLabel && tabLabel) {
fn(editor, index, tabContainer, tabResourceLabel, tabLabel);
fn(editor, index, tabContainer, tabResourceLabel, tabLabel, tabActionBar);
}
}
@@ -577,26 +582,31 @@ export class TabsTitleControl extends TitleControl {
// Tab Editor Label
const editorLabel = this.tabResourceLabels.create(tabContainer);
// Tab Close Button
const tabCloseContainer = document.createElement('div');
addClass(tabCloseContainer, 'tab-close');
tabContainer.appendChild(tabCloseContainer);
// Tab Actions
const tabActionsContainer = document.createElement('div');
addClass(tabActionsContainer, 'tab-actions');
tabContainer.appendChild(tabActionsContainer);
const tabActionRunner = new EditorCommandsContextActionRunner({ groupId: this.group.id, editorIndex: index });
const tabActionBar = new ActionBar(tabActionsContainer, { ariaLabel: localize('ariaLabelTabActions', "Tab actions"), actionRunner: tabActionRunner, });
tabActionBar.onDidBeforeRun(e => {
if (e.action.id === this.closeEditorAction.id) {
this.blockRevealActiveTabOnce();
}
});
const tabActionBarDisposable = combinedDisposable(tabActionBar, toDisposable(insert(this.tabActionBars, tabActionBar)));
// Tab Border Bottom
const tabBorderBottomContainer = document.createElement('div');
addClass(tabBorderBottomContainer, 'tab-border-bottom-container');
tabContainer.appendChild(tabBorderBottomContainer);
const tabActionRunner = new EditorCommandsContextActionRunner({ groupId: this.group.id, editorIndex: index });
const tabActionBar = new ActionBar(tabCloseContainer, { ariaLabel: localize('araLabelTabActions', "Tab actions"), actionRunner: tabActionRunner });
tabActionBar.push(this.closeOneEditorAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(this.closeOneEditorAction) });
tabActionBar.onDidBeforeRun(() => this.blockRevealActiveTabOnce());
// Eventing
const eventsDisposable = this.registerTabListeners(tabContainer, index, tabsContainer, tabsScrollbar);
this.tabDisposables.push(combinedDisposable(eventsDisposable, tabActionBar, tabActionRunner, editorLabel));
this.tabDisposables.push(combinedDisposable(eventsDisposable, tabActionBarDisposable, tabActionRunner, editorLabel));
return tabContainer;
}
@@ -659,7 +669,7 @@ export class TabsTitleControl extends TitleControl {
EventHelper.stop(e, true /* for https://github.com/Microsoft/vscode/issues/56715 */);
this.blockRevealActiveTabOnce();
this.closeOneEditorAction.run({ groupId: this.group.id, editorIndex: index });
this.closeEditorAction.run({ groupId: this.group.id, editorIndex: index });
}
}));
@@ -1011,8 +1021,8 @@ export class TabsTitleControl extends TitleControl {
}
// For each tab
this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel) => {
this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel);
this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar) => {
this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar);
});
// Update Editor Actions Toolbar
@@ -1022,28 +1032,38 @@ export class TabsTitleControl extends TitleControl {
this.layout(this.dimension);
}
private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel, tabActionBar: ActionBar): void {
const isTabSticky = this.group.isSticky(index);
const isTabLastSticky = isTabSticky && this.group.stickyCount === index + 1;
const options = this.accessor.partOptions;
// Label
this.redrawLabel(editor, index, tabContainer, tabLabelWidget, tabLabel);
// Action
const tabAction = isTabSticky ? this.unpinEditorAction : this.closeEditorAction;
if (!tabActionBar.hasAction(tabAction)) {
if (!tabActionBar.isEmpty()) {
tabActionBar.clear();
}
tabActionBar.push(tabAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(tabAction) });
}
// Borders / Outline
const borderRightColor = (this.getColor(TAB_BORDER) || this.getColor(contrastBorder));
const borderRightColor = ((isTabLastSticky ? this.getColor(TAB_LAST_PINNED_BORDER) : undefined) || this.getColor(TAB_BORDER) || this.getColor(contrastBorder));
tabContainer.style.borderRight = borderRightColor ? `1px solid ${borderRightColor}` : '';
tabContainer.style.outlineColor = this.getColor(activeContrastBorder) || '';
// Settings
const isTabSticky = this.group.isSticky(index);
const options = this.accessor.partOptions;
const tabCloseButton = isTabSticky ? 'off' /* treat sticky tabs as tabCloseButton: 'off' */ : options.tabCloseButton;
const tabActionsVisibility = isTabSticky && options.pinnedTabSizing === 'compact' ? 'off' /* treat sticky compact tabs as tabCloseButton: 'off' */ : options.tabCloseButton;
['off', 'left', 'right'].forEach(option => {
const domAction = tabCloseButton === option ? addClass : removeClass;
domAction(tabContainer, `close-button-${option}`);
const domAction = tabActionsVisibility === option ? addClass : removeClass;
domAction(tabContainer, `tab-actions-${option}`);
});
const tabSizing = isTabSticky && options.pinnedTabSizing === 'shrink' ? 'shrink' /* treat sticky shrink tabs as tabSizing: 'shrink' */ : options.tabSizing;
['fit', 'shrink'].forEach(option => {
const domAction = options.tabSizing === option ? addClass : removeClass;
const domAction = tabSizing === option ? addClass : removeClass;
domAction(tabContainer, `sizing-${option}`);
});
@@ -1053,13 +1073,26 @@ export class TabsTitleControl extends TitleControl {
removeClass(tabContainer, 'has-icon');
}
// Sticky Tabs need a position to remain at their location
['compact', 'shrink', 'normal'].forEach(option => {
const domAction = isTabSticky && options.pinnedTabSizing === option ? addClass : removeClass;
domAction(tabContainer, `sticky-${option}`);
});
// Sticky compact/shrink tabs need a position to remain at their location
// when scrolling to stay in view (requirement for position: sticky)
if (isTabSticky) {
addClass(tabContainer, 'sticky');
tabContainer.style.left = `${index * TabsTitleControl.TAB_SIZES.sticky}px`;
if (isTabSticky && options.pinnedTabSizing !== 'normal') {
let stickyTabWidth = 0;
switch (options.pinnedTabSizing) {
case 'compact':
stickyTabWidth = TabsTitleControl.TAB_SIZES.compact;
break;
case 'shrink':
stickyTabWidth = TabsTitleControl.TAB_SIZES.shrink;
break;
}
tabContainer.style.left = `${index * stickyTabWidth}px`;
} else {
removeClass(tabContainer, 'sticky');
tabContainer.style.left = 'auto';
}
@@ -1068,17 +1101,19 @@ export class TabsTitleControl extends TitleControl {
}
private redrawLabel(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
const isTabSticky = this.group.isSticky(index);
const options = this.accessor.partOptions;
// Unless tabs are sticky, show the full label and description
// Sticky tabs will only show an icon if icons are enabled
// Unless tabs are sticky compact, show the full label and description
// Sticky compact tabs will only show an icon if icons are enabled
// or their first character of the name otherwise
let name: string | undefined;
let forceLabel = false;
let description: string;
if (isTabSticky) {
const isShowingIcons = this.accessor.partOptions.showIcons && this.accessor.partOptions.hasIcons;
if (options.pinnedTabSizing === 'compact' && this.group.isSticky(index)) {
const isShowingIcons = options.showIcons && options.hasIcons;
name = isShowingIcons ? '' : tabLabel.name?.charAt(0).toUpperCase();
description = '';
forceLabel = true;
} else {
name = tabLabel.name;
description = tabLabel.description || '';
@@ -1097,7 +1132,7 @@ export class TabsTitleControl extends TitleControl {
// Label
tabLabelWidget.setResource(
{ name, description, resource: toResource(editor, { supportSideBySide: SideBySideEditor.BOTH }) },
{ title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel: isTabSticky }
{ title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel }
);
this.setEditorTabColor(editor, tabContainer, this.group.isActive(editor)); // {{SQL CARBON EDIT}} -- Display the editor's tab color
@@ -1265,7 +1300,7 @@ export class TabsTitleControl extends TitleControl {
//
// Synopsis
// - allTabsWidth: sum of all tab widths
// - stickyTabsWidth: sum of all sticky tab widths
// - stickyTabsWidth: sum of all sticky tab widths (unless `pinnedTabSizing: normal`)
// - visibleContainerWidth: size of tab container
// - availableContainerWidth: size of tab container minus size of sticky tabs
//
@@ -1281,7 +1316,24 @@ export class TabsTitleControl extends TitleControl {
const visibleTabsContainerWidth = tabsContainer.offsetWidth;
const allTabsWidth = tabsContainer.scrollWidth;
let stickyTabsWidth = this.group.stickyCount * TabsTitleControl.TAB_SIZES.sticky;
// Compute width of sticky tabs depending on pinned tab sizing
// - compact: sticky-tabs * TAB_SIZES.compact
// - shrink: sticky-tabs * TAB_SIZES.shrink
// - normal: 0 (sticky tabs inherit look and feel from non-sticky tabs)
let stickyTabsWidth = 0;
if (this.group.stickyCount > 0) {
let stickyTabWidth = 0;
switch (this.accessor.partOptions.pinnedTabSizing) {
case 'compact':
stickyTabWidth = TabsTitleControl.TAB_SIZES.compact;
break;
case 'shrink':
stickyTabWidth = TabsTitleControl.TAB_SIZES.shrink;
break;
}
stickyTabsWidth = this.group.stickyCount * stickyTabWidth;
}
let activeTabSticky = this.group.isSticky(activeIndex);
let availableTabsContainerWidth = visibleTabsContainerWidth - stickyTabsWidth;
@@ -1475,7 +1527,7 @@ export class TabsTitleControl extends TitleControl {
let sqlEditor = editor as any;
const tabColorMode = this.configurationService.getValue<IQueryEditorConfiguration>('queryEditor').tabColorMode;
if (tabColorMode === 'off' || (tabColorMode !== 'border' && tabColorMode !== 'fill')
|| this.themeService.getColorTheme().type === HIGH_CONTRAST || !sqlEditor.tabColor) {
|| this.themeService.getColorTheme().type === ColorScheme.HIGH_CONTRAST || !sqlEditor.tabColor) {
tabContainer.style.borderTopColor = '';
tabContainer.style.borderTopWidth = '';
tabContainer.style.borderTopStyle = '';
@@ -1502,7 +1554,7 @@ export class TabsTitleControl extends TitleControl {
registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => {
// Add border between tabs and breadcrumbs in high contrast mode.
if (theme.type === HIGH_CONTRAST) {
if (theme.type === ColorScheme.HIGH_CONTRAST) {
const borderColor = (theme.getColor(TAB_BORDER) || theme.getColor(contrastBorder));
collector.addRule(`
.monaco-workbench .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container {
@@ -1526,10 +1578,10 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
outline-offset: -5px;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-actions .action-label {
opacity: 1 !important;
}
`);
@@ -1621,11 +1673,11 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
// Adjust gradient for focused and unfocused hover background
const makeTabHoverBackgroundRule = (color: Color, colorDrag: Color, hasFocus = false) => `
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky):hover > .tab-label::after {
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky-compact):hover > .tab-label::after {
background: linear-gradient(to left, ${color}, transparent) !important;
}
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky):hover > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky-compact):hover > .tab-label::after {
background: linear-gradient(to left, ${colorDrag}, transparent) !important;
}
`;
@@ -1648,19 +1700,19 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
if (editorDragAndDropBackground && adjustedTabDragBackground) {
const adjustedColorDrag = editorDragAndDropBackground.flatten(adjustedTabDragBackground);
collector.addRule(`
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged):not(.sticky) > .tab-label::after,
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged):not(.sticky) > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged):not(.sticky-compact) > .tab-label::after,
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged):not(.sticky-compact) > .tab-label::after {
background: linear-gradient(to left, ${adjustedColorDrag}, transparent) !important;
}
`);
}
const makeTabBackgroundRule = (color: Color, colorDrag: Color, focused: boolean, active: boolean) => `
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky) > .tab-label::after {
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky-compact) > .tab-label::after {
background: linear-gradient(to left, ${color}, transparent);
}
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky) > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky-compact) > .tab-label::after {
background: linear-gradient(to left, ${colorDrag}, transparent);
}
`;

View File

@@ -32,7 +32,7 @@ import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs';
import { BreadcrumbsControl, IBreadcrumbsControlOptions } from 'vs/workbench/browser/parts/editor/breadcrumbsControl';
import { IEditorGroupsAccessor, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, toResource, IEditorPartOptions, SideBySideEditor, EditorPinnedContext, EditorStickyContext } from 'vs/workbench/common/editor';
import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, toResource, IEditorPartOptions, SideBySideEditor, ActiveEditorPinnedContext, ActiveEditorStickyContext } from 'vs/workbench/common/editor';
import { ResourceContextKey } from 'vs/workbench/common/resources';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
@@ -87,8 +87,8 @@ export abstract class TitleControl extends Themable {
super(themeService);
this.resourceContext = this._register(instantiationService.createInstance(ResourceContextKey));
this.editorPinnedContext = EditorPinnedContext.bindTo(contextKeyService);
this.editorStickyContext = EditorStickyContext.bindTo(contextKeyService);
this.editorPinnedContext = ActiveEditorPinnedContext.bindTo(contextKeyService);
this.editorStickyContext = ActiveEditorStickyContext.bindTo(contextKeyService);
this.contextMenu = this._register(this.menuService.createMenu(MenuId.EditorTitleContext, this.contextKeyService));
@@ -138,7 +138,7 @@ export abstract class TitleControl extends Themable {
this.editorActionsToolbar = this._register(new ToolBar(container, this.contextMenuService, {
actionViewItemProvider: action => this.actionViewItemProvider(action),
orientation: ActionsOrientation.HORIZONTAL,
ariaLabel: localize('araLabelEditorActions', "Editor actions"),
ariaLabel: localize('ariaLabelEditorActions', "Editor actions"),
getKeyBinding: action => this.getKeybinding(action),
actionRunner: this._register(new EditorCommandsContextActionRunner(context)),
anchorAlignmentProvider: () => AnchorAlignment.RIGHT

View File

@@ -26,7 +26,7 @@ import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbe
import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { Dimension, trackFocus, addClass, toggleClass, EventHelper } from 'vs/base/browser/dom';
import { Dimension, trackFocus, EventHelper } from 'vs/base/browser/dom';
import { localize } from 'vs/nls';
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
@@ -422,10 +422,10 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
private createEmptyPanelMessage(): void {
const contentArea = this.getContentArea()!;
this.emptyPanelMessageElement = document.createElement('div');
addClass(this.emptyPanelMessageElement, 'empty-panel-message-area');
this.emptyPanelMessageElement.classList.add('empty-panel-message-area');
const messageElement = document.createElement('div');
addClass(messageElement, 'empty-panel-message');
messageElement.classList.add('empty-panel-message');
messageElement.innerText = localize('panel.emptyMessage', "Drag a view into the panel to display.");
this.emptyPanelMessageElement.appendChild(messageElement);
@@ -613,7 +613,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
private emptyPanelMessageElement: HTMLElement | undefined;
private layoutEmptyMessage(): void {
if (this.emptyPanelMessageElement) {
toggleClass(this.emptyPanelMessageElement, 'visible', this.compositeBar.getVisibleComposites().length === 0);
this.emptyPanelMessageElement.classList.toggle('visible', this.compositeBar.getVisibleComposites().length === 0);
}
}

View File

@@ -15,7 +15,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor } from 'vs/workbench/services/statusbar/common/statusbar';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { Action, IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Separator } from 'vs/base/common/actions';
import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, ThemeColor, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, ThemeColor } from 'vs/platform/theme/common/themeService';
import { STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND, STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND, STATUS_BAR_BORDER, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER } from 'vs/workbench/common/theme';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry';
@@ -38,6 +38,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { RawContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ColorScheme } from 'vs/platform/theme/common/theme';
interface IPendingStatusbarEntry {
id: string;
@@ -672,7 +673,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
this.styleElement = createStyleSheet(container);
}
this.styleElement.innerHTML = `.monaco-workbench .part.statusbar > .items-container > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor}; }`;
this.styleElement.textContent = `.monaco-workbench .part.statusbar > .items-container > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor}; }`;
}
private doCreateStatusItem(id: string, alignment: StatusbarAlignment, ...extraClasses: string[]): HTMLElement {
@@ -889,7 +890,7 @@ class StatusbarEntryItem extends Disposable {
}
registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => {
if (theme.type !== HIGH_CONTRAST) {
if (theme.type !== ColorScheme.HIGH_CONTRAST) {
const statusBarItemHoverBackground = theme.getColor(STATUS_BAR_ITEM_HOVER_BACKGROUND);
if (statusBarItemHoverBackground) {
collector.addRule(`.monaco-workbench .part.statusbar > .items-container > .statusbar-item a:hover { background-color: ${statusBarItemHoverBackground}; }`);

View File

@@ -39,7 +39,7 @@ import { IMenuService, IMenu, MenuId } from 'vs/platform/actions/common/actions'
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IProductService } from 'vs/platform/product/common/productService';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { Schemas } from 'vs/base/common/network';
export class TitlebarPart extends Part implements ITitleService {
@@ -290,7 +290,7 @@ export class TitlebarPart extends Part implements ITitleService {
const folderPath = folder ? this.labelService.getUriLabel(folder.uri) : '';
const dirty = editor?.isDirty() && !editor.isSaving() ? TitlebarPart.TITLE_DIRTY : '';
const appName = this.productService.nameLong;
const remoteName = this.labelService.getHostLabel(REMOTE_HOST_SCHEME, this.environmentService.configuration.remoteAuthority);
const remoteName = this.labelService.getHostLabel(Schemas.vscodeRemote, this.environmentService.configuration.remoteAuthority);
const separator = this.configurationService.getValue<string>('window.titleSeparator');
const titleTemplate = this.configurationService.getValue<string>('window.title');

View File

@@ -9,9 +9,8 @@ import { Event, Emitter } from 'vs/base/common/event';
import { ColorIdentifier, activeContrastBorder, foreground } from 'vs/platform/theme/common/colorRegistry';
import { attachStyler, IColorMapping, attachButtonStyler, attachLinkStyler, attachProgressBarStyler } from 'vs/platform/theme/common/styler';
import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER, PANEL_BACKGROUND, SIDE_BAR_BACKGROUND, PANEL_SECTION_HEADER_FOREGROUND, PANEL_SECTION_HEADER_BACKGROUND, PANEL_SECTION_HEADER_BORDER, PANEL_SECTION_DRAG_AND_DROP_BACKGROUND, PANEL_SECTION_BORDER } from 'vs/workbench/common/theme';
import { after, append, $, trackFocus, toggleClass, EventType, isAncestor, Dimension, addDisposableListener, removeClass, addClass, createCSSRule, asCSSUrl, addClasses } from 'vs/base/browser/dom';
import { after, append, $, trackFocus, EventType, isAncestor, Dimension, addDisposableListener, createCSSRule, asCSSUrl, addClasses } from 'vs/base/browser/dom';
import { IDisposable, combinedDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { firstIndex } from 'vs/base/common/arrays';
import { IAction, Separator, IActionViewItem } from 'vs/base/common/actions';
import { ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -238,7 +237,7 @@ export abstract class ViewPane extends Pane implements IView {
set headerVisible(visible: boolean) {
super.headerVisible = visible;
toggleClass(this.element, 'merged-header', !visible);
this.element.classList.toggle('merged-header', !visible);
}
setVisible(visible: boolean): void {
@@ -294,7 +293,7 @@ export abstract class ViewPane extends Pane implements IView {
this.renderHeaderTitle(container, this.title);
const actions = append(container, $('.actions'));
toggleClass(actions, 'show', this.showActionsAlways);
actions.classList.toggle('show', this.showActionsAlways);
this.toolbar = new ToolBar(actions, this.contextMenuService, {
orientation: ActionsOrientation.HORIZONTAL,
actionViewItemProvider: action => this.getActionViewItem(action),
@@ -357,7 +356,7 @@ export abstract class ViewPane extends Pane implements IView {
-webkit-mask-size: 16px;
`);
} else if (isString(icon)) {
addClass(this.iconContainer, 'codicon');
this.iconContainer.classList.add('codicon');
cssClass = icon;
}
@@ -366,7 +365,7 @@ export abstract class ViewPane extends Pane implements IView {
}
const calculatedTitle = this.calculateTitle(title);
this.titleContainer = append(container, $('h3.title', undefined, calculatedTitle));
this.titleContainer = append(container, $('h3.title', { title: calculatedTitle }, calculatedTitle));
if (this._titleDescription) {
this.setTitleDescription(this._titleDescription);
@@ -380,6 +379,7 @@ export abstract class ViewPane extends Pane implements IView {
const calculatedTitle = this.calculateTitle(title);
if (this.titleContainer) {
this.titleContainer.textContent = calculatedTitle;
this.titleContainer.setAttribute('title', calculatedTitle);
}
if (this.iconContainer) {
@@ -394,9 +394,10 @@ export abstract class ViewPane extends Pane implements IView {
private setTitleDescription(description: string | undefined) {
if (this.titleDescriptionContainer) {
this.titleDescriptionContainer.textContent = description ?? '';
this.titleDescriptionContainer.setAttribute('title', description ?? '');
}
else if (description && this.titleContainer) {
this.titleDescriptionContainer = after(this.titleContainer, $('span.description', undefined, description));
this.titleDescriptionContainer = after(this.titleContainer, $('span.description', { title: description }, description));
}
}
@@ -489,7 +490,7 @@ export abstract class ViewPane extends Pane implements IView {
return;
}
const shouldAlwaysShowActions = this.configurationService.getValue<boolean>('workbench.view.alwaysShowHeaderActions');
toggleClass(this.headerContainer, 'actions-always-visible', shouldAlwaysShowActions);
this.headerContainer.classList.toggle('actions-always-visible', shouldAlwaysShowActions);
}
protected updateActions(): void {
@@ -534,7 +535,7 @@ export abstract class ViewPane extends Pane implements IView {
this.viewWelcomeDisposable.dispose();
if (!this.shouldShowWelcome()) {
removeClass(this.bodyContainer, 'welcome');
this.bodyContainer.classList.remove('welcome');
this.viewWelcomeContainer.innerText = '';
this.scrollableElement.scanDomNode();
return;
@@ -543,14 +544,14 @@ export abstract class ViewPane extends Pane implements IView {
const contents = this.viewWelcomeController.contents;
if (contents.length === 0) {
removeClass(this.bodyContainer, 'welcome');
this.bodyContainer.classList.remove('welcome');
this.viewWelcomeContainer.innerText = '';
this.scrollableElement.scanDomNode();
return;
}
const disposables = new DisposableStore();
addClass(this.bodyContainer, 'welcome');
this.bodyContainer.classList.add('welcome');
this.viewWelcomeContainer.innerText = '';
let buttonIndex = 0;
@@ -680,15 +681,15 @@ class ViewPaneDropOverlay extends Themable {
// Parent
this.paneElement.appendChild(this.container);
addClass(this.paneElement, 'dragged-over');
this.paneElement.classList.add('dragged-over');
this._register(toDisposable(() => {
this.paneElement.removeChild(this.container);
removeClass(this.paneElement, 'dragged-over');
this.paneElement.classList.remove('dragged-over');
}));
// Overlay
this.overlay = document.createElement('div');
addClass(this.overlay, 'pane-overlay-indicator');
this.overlay.classList.add('pane-overlay-indicator');
this.container.appendChild(this.overlay);
// Overlay Event Handling
@@ -819,7 +820,7 @@ class ViewPaneDropOverlay extends Themable {
this.overlay.style.opacity = '1';
// Enable transition after a timeout to prevent initial animation
setTimeout(() => addClass(this.overlay, 'overlay-move-transition'), 0);
setTimeout(() => this.overlay.classList.add('overlay-move-transition'), 0);
// Remember as current split direction
this._currentDropOperation = dropDirection;
@@ -1581,7 +1582,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
}
private removePane(pane: ViewPane): void {
const index = firstIndex(this.paneItems, i => i.pane === pane);
const index = this.paneItems.findIndex(i => i.pane === pane);
if (index === -1) {
return;
@@ -1598,8 +1599,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
}
movePane(from: ViewPane, to: ViewPane): void {
const fromIndex = firstIndex(this.paneItems, item => item.pane === from);
const toIndex = firstIndex(this.paneItems, item => item.pane === to);
const fromIndex = this.paneItems.findIndex(item => item.pane === from);
const toIndex = this.paneItems.findIndex(item => item.pane === to);
const fromViewDescriptor = this.viewContainerModel.visibleViewDescriptors[fromIndex];
const toViewDescriptor = this.viewContainerModel.visibleViewDescriptors[toIndex];

View File

@@ -5,12 +5,13 @@
import 'vs/css!./media/style';
import { registerThemingParticipant, IColorTheme, ICssStyleCollector, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
import { registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { iconForeground, foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
import { WORKBENCH_BACKGROUND, TITLE_BAR_ACTIVE_BACKGROUND } from 'vs/workbench/common/theme';
import { isWeb, isIOS, isMacintosh, isWindows } from 'vs/base/common/platform';
import { createMetaElement } from 'vs/base/browser/dom';
import { isSafari, isStandalone } from 'vs/base/browser/browser';
import { ColorScheme } from 'vs/platform/theme/common/theme';
registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => {
@@ -127,7 +128,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
}
// High Contrast theme overwrites for outline
if (theme.type === HIGH_CONTRAST) {
if (theme.type === ColorScheme.HIGH_CONTRAST) {
collector.addRule(`
.hc-black [tabindex="0"]:focus,
.hc-black [tabindex="-1"]:focus,

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { mark } from 'vs/base/common/performance';
import { domContentLoaded, addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom';
import { domContentLoaded, addDisposableListener, EventType, EventHelper, detectFullscreen, addDisposableThrottledListener } from 'vs/base/browser/dom';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ILogService, ConsoleLogService, MultiplexLogService } from 'vs/platform/log/common/log';
import { ConsoleLogInAutomationService } from 'vs/platform/log/browser/log';
@@ -25,8 +25,8 @@ import { Schemas } from 'vs/base/common/network';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { onUnexpectedError } from 'vs/base/common/errors';
import * as browser from 'vs/base/browser/browser';
import * as platform from 'vs/base/common/platform';
import { setFullscreen } from 'vs/base/browser/browser';
import { isIOS, isMacintosh } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
import { WorkspaceService } from 'vs/workbench/services/configuration/browser/configurationService';
@@ -34,9 +34,6 @@ import { ConfigurationCache } from 'vs/workbench/services/configuration/browser/
import { ISignService } from 'vs/platform/sign/common/sign';
import { SignService } from 'vs/platform/sign/browser/signService';
import { IWorkbenchConstructionOptions, IWorkspace, IWorkbench } from 'vs/workbench/workbench.web.api';
import { FileUserDataProvider } from 'vs/workbench/services/userData/common/fileUserDataProvider';
import { BACKUPS } from 'vs/platform/environment/common/environment';
import { joinPath } from 'vs/base/common/resources';
import { BrowserStorageService } from 'vs/platform/storage/browser/storageService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { registerWindowDriver } from 'vs/platform/driver/browser/driver';
@@ -61,6 +58,14 @@ class BrowserMain extends Disposable {
private readonly configuration: IWorkbenchConstructionOptions
) {
super();
this.init();
}
private init(): void {
// Browser config
setFullscreen(!!detectFullscreen());
}
async open(): Promise<IWorkbench> {
@@ -102,7 +107,7 @@ class BrowserMain extends Disposable {
private registerListeners(workbench: Workbench, storageService: BrowserStorageService): void {
// Layout
const viewport = platform.isIOS && (<any>window).visualViewport ? (<any>window).visualViewport /** Visual viewport */ : window /** Layout viewport */;
const viewport = isIOS && window.visualViewport ? window.visualViewport /** Visual viewport */ : window /** Layout viewport */;
this._register(addDisposableListener(viewport, EventType.RESIZE, () => workbench.layout()));
// Prevent the back/forward gestures in macOS
@@ -126,16 +131,15 @@ class BrowserMain extends Disposable {
}));
this._register(workbench.onShutdown(() => this.dispose()));
// Fullscreen
// Fullscreen (Browser)
[EventType.FULLSCREEN_CHANGE, EventType.WK_FULLSCREEN_CHANGE].forEach(event => {
this._register(addDisposableListener(document, event, () => {
if (document.fullscreenElement || (<any>document).webkitFullscreenElement || (<any>document).webkitIsFullScreen) {
browser.setFullscreen(true);
} else {
browser.setFullscreen(false);
}
}));
this._register(addDisposableListener(document, event, () => setFullscreen(!!detectFullscreen())));
});
// Fullscreen (Native)
this._register(addDisposableThrottledListener(viewport, EventType.RESIZE, () => {
setFullscreen(!!detectFullscreen());
}, undefined, isMacintosh ? 2000 /* adjust for macOS animation */ : 800 /* can be throttled */));
}
private async initServices(): Promise<{ serviceCollection: ServiceCollection, logService: ILogService, storageService: BrowserStorageService }> {
@@ -213,11 +217,14 @@ class BrowserMain extends Disposable {
serviceCollection.set(IUserDataInitializationService, userDataInitializationService);
if (await userDataInitializationService.requiresInitialization()) {
mark('willInitRequiredUserData');
// Initialize required resources - settings & global state
await userDataInitializationService.initializeRequiredResources();
// Reload configuration after initializing
await configurationService.reloadConfiguration();
// Important Reload only local user configuration after initializing
// Reloading complete configuraiton blocks workbench until remote configuration is loaded.
await configurationService.reloadLocalUserConfiguration();
mark('didInitRequiredUserData');
}
return { serviceCollection, logService, storageService };
@@ -250,17 +257,9 @@ class BrowserMain extends Disposable {
const connection = remoteAgentService.getConnection();
if (connection) {
// Remote file system
const remoteFileSystemProvider = this._register(new RemoteFileSystemProvider(remoteAgentService));
fileService.registerProvider(Schemas.vscodeRemote, remoteFileSystemProvider);
if (!this.configuration.userDataProvider) {
const remoteUserDataUri = this.getRemoteUserDataUri();
if (remoteUserDataUri) {
this.configuration.userDataProvider = this._register(new FileUserDataProvider(remoteUserDataUri, joinPath(remoteUserDataUri, BACKUPS), remoteFileSystemProvider, environmentService, logService));
}
}
}
// User data
@@ -331,18 +330,6 @@ class BrowserMain extends Disposable {
return { id: 'empty-window' };
}
private getRemoteUserDataUri(): URI | undefined {
const element = document.getElementById('vscode-remote-user-data-uri');
if (element) {
const remoteUserDataPath = element.getAttribute('data-settings');
if (remoteUserDataPath) {
return joinPath(URI.revive(JSON.parse(remoteUserDataPath)), 'User');
}
}
return undefined;
}
private getCookieValue(name: string): string | undefined {
const match = document.cookie.match('(^|[^;]+)\\s*' + name + '\\s*=\\s*([^;]+)'); // See https://stackoverflow.com/a/25490531

View File

@@ -34,12 +34,12 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
},
'workbench.editor.scrollToSwitchTabs': {
'type': 'boolean',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'scrollToSwitchTabs' }, "Controls whether scrolling over tabs will open them or not. By default tabs will only reveal upon scrolling, but not open. You can press and hold the Shift-key while scrolling to change this behaviour for that duration."),
'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'scrollToSwitchTabs' }, "Controls whether scrolling over tabs will open them or not. By default tabs will only reveal upon scrolling, but not open. You can press and hold the Shift-key while scrolling to change this behaviour for that duration. This value is ignored when `#workbench.editor.showTabs#` is `false`."),
'default': false
},
'workbench.editor.highlightModifiedTabs': {
'type': 'boolean',
'description': nls.localize('highlightModifiedTabs', "Controls whether a top border is drawn on modified (dirty) editor tabs or not."),
'markdownDescription': nls.localize('highlightModifiedTabs', "Controls whether a top border is drawn on modified (dirty) editor tabs or not. This value is ignored when `#workbench.editor.showTabs#` is `false`."),
'default': false
},
'workbench.editor.labelFormat': {
@@ -74,7 +74,7 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
'type': 'string',
'enum': ['left', 'right', 'off'],
'default': 'right',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorTabCloseButton' }, "Controls the position of the editor's tabs close buttons, or disables them when set to 'off'.")
'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorTabCloseButton' }, "Controls the position of the editor's tabs close buttons, or disables them when set to 'off'. This value is ignored when `#workbench.editor.showTabs#` is `false`.")
},
'workbench.editor.tabSizing': {
'type': 'string',
@@ -84,7 +84,18 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
nls.localize('workbench.editor.tabSizing.fit', "Always keep tabs large enough to show the full editor label."),
nls.localize('workbench.editor.tabSizing.shrink', "Allow tabs to get smaller when the available space is not enough to show all tabs at once.")
],
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabSizing' }, "Controls the sizing of editor tabs.")
'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabSizing' }, "Controls the sizing of editor tabs. This value is ignored when `#workbench.editor.showTabs#` is `false`.")
},
'workbench.editor.pinnedTabSizing': {
'type': 'string',
'enum': ['compact', 'shrink', 'normal'],
'default': 'shrink',
'enumDescriptions': [
nls.localize('workbench.editor.pinnedTabSizing.compact', "A pinned tab will show in a compact form with only icon or first letter of the editor name."),
nls.localize('workbench.editor.pinnedTabSizing.shrink', "A pinned tab shrinks to a compact fixed size showing parts of the editor name."),
nls.localize('workbench.editor.pinnedTabSizing.normal', "A pinned tab inherits the look of non pinned tabs.")
],
'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'pinnedTabSizing' }, "Controls the sizing of pinned editor tabs. Pinned tabs are sorted to the begining of all opened tabs and typically do not close until unpinned. This value is ignored when `#workbench.editor.showTabs#` is `false`.")
},
'workbench.editor.splitSizing': {
'type': 'string',
@@ -330,7 +341,7 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
nls.localize('window.menuBarVisibility.visible', "Menu is always visible even in full screen mode."),
nls.localize('window.menuBarVisibility.toggle', "Menu is hidden but can be displayed via Alt key."),
nls.localize('window.menuBarVisibility.hidden', "Menu is always hidden."),
nls.localize('window.menuBarVisibility.compact', "Menu is displayed as a compact button in the sidebar. This value is ignored when 'window.titleBarStyle' is 'native'.")
nls.localize('window.menuBarVisibility.compact', "Menu is displayed as a compact button in the sidebar. This value is ignored when `#window.titleBarStyle#` is `native`.")
],
'default': isWeb ? 'compact' : 'default',
'scope': ConfigurationScope.APPLICATION,