diff --git a/src/vs/workbench/browser/parts/editor2/editor2.ts b/src/vs/workbench/browser/parts/editor2/editor2.ts index 0ac5b63657749f856c50d0b194b9fb6f9f68eb78..3c709710f8f2df022d080be3c12dd51a9510d32b 100644 --- a/src/vs/workbench/browser/parts/editor2/editor2.ts +++ b/src/vs/workbench/browser/parts/editor2/editor2.ts @@ -35,7 +35,7 @@ export function impactsEditorPartOptions(event: IConfigurationChangeEvent): bool } export function getEditorPartOptions(config: IWorkbenchEditorConfiguration): INextEditorPartOptions { - let options: INextEditorPartOptions = assign(Object.create(null), DEFAULT_EDITOR_PART_OPTIONS); + const options: INextEditorPartOptions = assign(Object.create(null), DEFAULT_EDITOR_PART_OPTIONS); if (!config || !config.workbench) { return options; @@ -46,7 +46,7 @@ export function getEditorPartOptions(config: IWorkbenchEditorConfiguration): INe } if (config.workbench.editor) { - options = assign(options, config.workbench.editor); + assign(options, config.workbench.editor); } return options; diff --git a/src/vs/workbench/browser/parts/editor2/nextEditorControl.ts b/src/vs/workbench/browser/parts/editor2/nextEditorControl.ts index f6f7bbfa6c086313feb85b498df080e30370a9c0..97fe3c4a9f64d653408faa3cf7c86ac1865168eb 100644 --- a/src/vs/workbench/browser/parts/editor2/nextEditorControl.ts +++ b/src/vs/workbench/browser/parts/editor2/nextEditorControl.ts @@ -102,7 +102,7 @@ export class NextEditorControl extends Disposable { private doInstantiateEditorControl(descriptor: IEditorDescriptor): BaseEditor { // Return early if already instantiated - const existingControl = this.controls.filter(e => descriptor.describes(e))[0]; + const existingControl = this.controls.filter(control => descriptor.describes(control))[0]; if (existingControl) { return existingControl; } diff --git a/src/vs/workbench/browser/parts/editor2/nextEditorGroupView.ts b/src/vs/workbench/browser/parts/editor2/nextEditorGroupView.ts index 2435316d7ac78fafc16881a51afe227a5c650b61..38827fd4985ea82e4a5775707385bba43ea50dab 100644 --- a/src/vs/workbench/browser/parts/editor2/nextEditorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor2/nextEditorGroupView.ts @@ -26,14 +26,13 @@ import { IProgressService } from 'vs/platform/progress/common/progress'; import { ProgressService } from 'vs/workbench/services/progress/browser/progressService'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { localize } from 'vs/nls'; -import { onUnexpectedError, isPromiseCanceledError, isErrorWithActions, IErrorWithActions } from 'vs/base/common/errors'; +import { isPromiseCanceledError, isErrorWithActions, IErrorWithActions } from 'vs/base/common/errors'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { dispose } from 'vs/base/common/lifecycle'; import { Severity, INotificationService, INotificationActions } from 'vs/platform/notification/common/notification'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { RunOnceWorker } from 'vs/base/common/async'; -import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { getCodeEditor } from 'vs/editor/browser/services/codeEditorService'; import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch'; import { NextTitleControl } from 'vs/workbench/browser/parts/editor2/nextTitleControl'; @@ -43,7 +42,8 @@ import { NextNoTabsTitleControl } from './nextNoTabsTitleControl'; export class NextEditorGroupView extends Themable implements INextEditorGroupView { private static readonly EDITOR_TITLE_HEIGHT = 35; - private static readonly ENABLE_PREVIEW_SETTING = 'workbench.editor.enablePreview'; + private static readonly EDITOR_MIN_WIDTH = 170; + private static readonly EDITOR_MIN_HEIGHT = 70; //#region factory @@ -106,8 +106,7 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie @IThemeService themeService: IThemeService, @IPartService private partService: IPartService, @INotificationService private notificationService: INotificationService, - @ITelemetryService private telemetryService: ITelemetryService, - @IConfigurationService private configurationService: IConfigurationService + @ITelemetryService private telemetryService: ITelemetryService ) { super(themeService); @@ -135,9 +134,6 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie this._register(this._group.onDidEditorBecomeDirty(editor => this.onDidEditorBecomeDirty(editor))); this._register(this._group.onDidEditorLabelChange(editor => this.onDidEditorLabelChange(editor))); - // Configuration Changes - this._register(this.configurationService.onDidChangeConfiguration(e => this.onDidChangeConfiguration(e))); - // Option Changes this._register(this.accessor.onDidEditorPartOptionsChange(e => this.onDidEditorPartOptionsChange(e))); } @@ -224,16 +220,6 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie } } - private onDidChangeConfiguration(event: IConfigurationChangeEvent): void { - - // Pin preview editor once user disables preview - if (event.affectsConfiguration(NextEditorGroupView.ENABLE_PREVIEW_SETTING)) { - if (!this.configurationService.getValue(NextEditorGroupView.ENABLE_PREVIEW_SETTING)) { - this.pinEditor(this._group.previewEditor); - } - } - } - private onDidEditorPartOptionsChange(event: INextEditorPartOptionsChangeEvent): void { // Title container @@ -251,9 +237,9 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie clearNode(this.titleContainer); // Recreate new and open editor - const titleAreaControl = this.doCreateOrGetTitleControl(); + this.createTitleAreaControl(); if (this.group.activeEditor) { - titleAreaControl.openEditor(this.group.activeEditor); + this.titleAreaControl.openEditor(this.group.activeEditor); } } @@ -265,6 +251,11 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie // Styles this.updateStyles(); + + // Pin preview editor once user disables preview + if (event.oldPartOptions.enablePreview && !event.newPartOptions.enablePreview) { + this.pinEditor(this._group.previewEditor); + } } private onDidEditorBecomeDirty(editor: EditorInput): void { @@ -383,6 +374,43 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie toggleClass(this.titleContainer, 'show-file-icons', this.accessor.partOptions.showIcons); } + private createScopedInstantiationService(): void { + this.scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection( + [IContextKeyService, this._register(this.contextKeyService.createScoped(this.element))], + [IProgressService, new ProgressService(this.progressBar)] + )); + } + + private createTitleAreaControl(): NextTitleControl { + if (!this.scopedInstantiationService) { + this.createScopedInstantiationService(); + } + + if (this.accessor.partOptions.showTabs) { + this.titleAreaControl = this.scopedInstantiationService.createInstance(NextTabsTitleControl, this.titleContainer, this.accessor, this); + } else { + this.titleAreaControl = this.scopedInstantiationService.createInstance(NextNoTabsTitleControl, this.titleContainer, this.accessor, this); + } + + this.doLayoutTitleControl(); + + return this.titleAreaControl; + } + + private createEditorControl(): NextEditorControl { + if (!this.scopedInstantiationService) { + this.createScopedInstantiationService(); + } + + this.editorControl = this._register(this.scopedInstantiationService.createInstance(NextEditorControl, this.editorContainer, this._group.id)); + + this.doLayoutEditorControl(); + + return this.editorControl; + } + + //region INextEditorGroupView + get group(): EditorGroup { return this._group; } @@ -407,8 +435,12 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie return this._group.count === 0; } + //#endregion + //#region INextEditorGroup + //#region basics() + get id(): GroupIdentifier { return this._group.id; } @@ -445,6 +477,33 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie return this._group.indexOf(editor); } + isOpened(editor: EditorInput): boolean { + return this._group.contains(editor); + } + + focus(): void { + if (this.activeControl) { + this.activeControl.focus(); + } else { + this.element.focus(); + } + } + + pinEditor(editor: EditorInput = this.activeEditor): void { + if (editor && !this._group.isPinned(editor)) { + + // Update model + this._group.pin(editor); + + // Forward to title control + if (this.titleAreaControl) { + this.titleAreaControl.pinEditor(editor); + } + } + } + + //#endregion + //#region openEditor() openEditor(editor: EditorInput, options?: EditorOptions): Thenable { @@ -480,13 +539,15 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie // Update model this._group.openEditor(editor, openEditorOptions); - // Forward to title control - this.doCreateOrGetTitleControl().openEditor(editor); + // Forward to title control (create lazily) + const titleAreaControl = this.titleAreaControl || this.createTitleAreaControl(); + titleAreaControl.openEditor(editor); - // Forward to editor control if the active editor changed + // Forward to editor control if the active editor changed (create lazily) let openEditorPromise: Thenable; if (openEditorOptions.active) { - openEditorPromise = this.doCreateOrGetEditorControl().openEditor(editor, options).then(result => { + const editorControl = this.editorControl || this.createEditorControl(); + openEditorPromise = editorControl.openEditor(editor, options).then(result => { // Editor change event if (result.editorChanged) { @@ -528,48 +589,11 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie // Recover by closing the active editor (if the input is still the active one) if (this.activeEditor === editor) { - this.doCloseActiveEditor(!(options && options.preserveFocus) /* still preserve focus as needed */, true /* from error */); + const focusNext = !options || !options.preserveFocus; + this.doCloseActiveEditor(focusNext, true /* from error */); } } - private doCreateOrGetScopedInstantiationService(): IInstantiationService { - if (!this.scopedInstantiationService) { - this.scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection( - [IContextKeyService, this._register(this.contextKeyService.createScoped(this.element))], - [IProgressService, new ProgressService(this.progressBar)] - )); - } - - return this.scopedInstantiationService; - } - - private doCreateOrGetTitleControl(): NextTitleControl { - if (!this.titleAreaControl) { - const instantiator = this.doCreateOrGetScopedInstantiationService(); - - if (this.accessor.partOptions.showTabs) { - this.titleAreaControl = instantiator.createInstance(NextTabsTitleControl, this.titleContainer, this.accessor, this); - } else { - this.titleAreaControl = instantiator.createInstance(NextNoTabsTitleControl, this.titleContainer, this.accessor, this); - } - - this.doLayoutTitleControl(); - } - - return this.titleAreaControl; - } - - private doCreateOrGetEditorControl(): NextEditorControl { - if (!this.editorControl) { - const instantiator = this.doCreateOrGetScopedInstantiationService(); - this.editorControl = this._register(instantiator.createInstance(NextEditorControl, this.editorContainer, this._group.id)); - - this.doLayoutEditorControl(); - } - - return this.editorControl; - } - //#endregion //#region moveEditor() @@ -625,7 +649,7 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie target.openEditor(editor, options); // ...and a close afterwards - this.doCloseEditor(editor, false /* do not activate next one behind if any */); + this.doCloseEditor(editor, false /* do not focus next one behind if any */); } //#endregion @@ -648,7 +672,7 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie private doCloseEditor(editor: EditorInput, focusNext = this.accessor.activeGroup === this): void { // Closing the active editor of the group is a bit more work - if (this.activeEditor && this.activeEditor.matches(editor)) { + if (this.group.isActive(editor)) { this.doCloseActiveEditor(focusNext); } @@ -681,11 +705,8 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie this.ignoreOpenEditorErrors = true; } - this.openEditor(nextActiveEditor, !focusNext ? EditorOptions.create({ preserveFocus: true }) : null).then(() => { - this.ignoreOpenEditorErrors = false; - }, error => { - onUnexpectedError(error); - + const options = !focusNext ? EditorOptions.create({ preserveFocus: true }) : void 0; + this.openEditor(nextActiveEditor, options).then(() => { this.ignoreOpenEditorErrors = false; }); } else { @@ -775,35 +796,6 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie //#endregion - //#region other INextEditorGroup methods - - isOpened(editor: EditorInput): boolean { - return this._group.contains(editor); - } - - focus(): void { - if (this.activeControl) { - this.activeControl.focus(); - } else { - this.element.focus(); - } - } - - pinEditor(editor: EditorInput = this.activeEditor): void { - if (editor && !this._group.isPinned(editor)) { - - // Update model - this._group.pin(editor); - - // Forward to title control - if (this.titleAreaControl) { - this.titleAreaControl.pinEditor(editor); - } - } - } - - //#endregion - //#endregion //#region Themable @@ -832,12 +824,12 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie readonly element: HTMLElement = document.createElement('div'); - readonly minimumWidth = 170; - readonly minimumHeight = 70; + readonly minimumWidth = NextEditorGroupView.EDITOR_MIN_WIDTH; + readonly minimumHeight = NextEditorGroupView.EDITOR_MIN_HEIGHT; readonly maximumWidth = Number.POSITIVE_INFINITY; readonly maximumHeight = Number.POSITIVE_INFINITY; - get onDidChange() { return Event.None; } + get onDidChange() { return Event.None; } // only needed if minimum sizes ever change layout(width: number, height: number): void { this._dimension = new Dimension(width, height); diff --git a/src/vs/workbench/browser/parts/editor2/nextEditorPart.ts b/src/vs/workbench/browser/parts/editor2/nextEditorPart.ts index ebd7d9eb417e995d0cf06eb9f0c38129b60381b2..cb7e4af3dd8469178b1d12447c581ed6dcab3c63 100644 --- a/src/vs/workbench/browser/parts/editor2/nextEditorPart.ts +++ b/src/vs/workbench/browser/parts/editor2/nextEditorPart.ts @@ -154,22 +154,9 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN // Open Editor if we Copy const activeEditor = fromGroupView.activeEditor; if (copy && activeEditor) { - - // Copy over as much view state from active control as posisble - let options: EditorOptions; const activeCodeEditorControl = getCodeEditor(fromGroupView.activeControl); - if (activeCodeEditorControl) { - options = TextEditorOptions.fromEditor(activeCodeEditorControl); - } else { - options = new EditorOptions(); - } - - // Set pinned state accordingly - if (copy === CopyKind.GROUP) { - options.pinned = fromGroupView.isPinned(activeEditor); // copy group preserves all pinned state - } else { - options.pinned = true; // copy of single editor is a sign of importance, so pin it - } + const options = activeCodeEditorControl ? TextEditorOptions.fromEditor(activeCodeEditorControl) : new EditorOptions(); + options.pinned = (copy === CopyKind.GROUP) ? fromGroupView.isPinned(activeEditor) : true; newGroupView.openEditor(activeEditor, options); } diff --git a/src/vs/workbench/browser/parts/editor2/nextNoTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor2/nextNoTabsTitleControl.ts index 79567af48d0932ea8e89b3ed77500bfdb4d8d207..43f70cae82d2cec78ed82abf2276d9de4754231b 100644 --- a/src/vs/workbench/browser/parts/editor2/nextNoTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor2/nextNoTabsTitleControl.ts @@ -129,7 +129,7 @@ export class NextNoTabsTitleControl extends NextTitleControl { } } - protected redraw(): void { + private redraw(): void { const editor = this.group.activeEditor; this.lastRenderedEditor = editor; @@ -138,42 +138,43 @@ export class NextNoTabsTitleControl extends NextTitleControl { removeClass(this.titleContainer, 'dirty'); this.editorLabel.clear(); this.clearEditorActionsToolbar(); - - return; } - const isEditorPinned = this.group.isPinned(this.group.activeEditor); - const isGroupActive = this.accessor.activeGroup === this.group; + // Otherwise render it + else { + const isEditorPinned = this.group.isPinned(this.group.activeEditor); + const isGroupActive = this.accessor.activeGroup === this.group; - // Dirty state - this.updateEditorDirty(editor); + // Dirty state + this.updateEditorDirty(editor); - // Editor Label - const resource = toResource(editor, { supportSideBySide: true }); - const name = editor.getName() || ''; - - const { labelFormat } = this.accessor.partOptions; - let description: string; - if (labelFormat === 'default' && !isGroupActive) { - description = ''; // hide description when group is not active and style is 'default' - } else { - description = editor.getDescription(this.getVerbosity(labelFormat)) || ''; - } + // Editor Label + const resource = toResource(editor, { supportSideBySide: true }); + const name = editor.getName() || ''; - let title = editor.getTitle(Verbosity.LONG); - if (description === title) { - title = ''; // dont repeat what is already shown - } + const { labelFormat } = this.accessor.partOptions; + let description: string; + if (labelFormat === 'default' && !isGroupActive) { + description = ''; // hide description when group is not active and style is 'default' + } else { + description = editor.getDescription(this.getVerbosity(labelFormat)) || ''; + } - this.editorLabel.setLabel({ name, description, resource }, { title, italic: !isEditorPinned, extraClasses: ['title-label'] }); - if (isGroupActive) { - this.editorLabel.element.style.color = this.getColor(TAB_ACTIVE_FOREGROUND); - } else { - this.editorLabel.element.style.color = this.getColor(TAB_UNFOCUSED_ACTIVE_FOREGROUND); - } + let title = editor.getTitle(Verbosity.LONG); + if (description === title) { + title = ''; // dont repeat what is already shown + } + + this.editorLabel.setLabel({ name, description, resource }, { title, italic: !isEditorPinned, extraClasses: ['title-label'] }); + if (isGroupActive) { + this.editorLabel.element.style.color = this.getColor(TAB_ACTIVE_FOREGROUND); + } else { + this.editorLabel.element.style.color = this.getColor(TAB_UNFOCUSED_ACTIVE_FOREGROUND); + } - // Update Editor Actions Toolbar - this.updateEditorActionsToolbar(); + // Update Editor Actions Toolbar + this.updateEditorActionsToolbar(); + } } private getVerbosity(style: string): Verbosity { diff --git a/src/vs/workbench/browser/parts/editor2/nextTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor2/nextTabsTitleControl.ts index bcb0ddb51aabad68b2e8fd87ace506b4e2aa3438..68653465d7df043b5028b0206313a0d7d459e47d 100644 --- a/src/vs/workbench/browser/parts/editor2/nextTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor2/nextTabsTitleControl.ts @@ -678,7 +678,7 @@ export class NextTabsTitleControl extends NextTitleControl { } } - protected redraw(): void { + private redraw(): void { // For each tab this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel) => { @@ -751,6 +751,8 @@ export class NextTabsTitleControl extends NextTitleControl { } private redrawEditorActive(isGroupActive: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel): void { + + // Tab is active if (this.group.activeEditor === editor) { // Container @@ -770,7 +772,10 @@ export class NextTabsTitleControl extends NextTitleControl { // Label tabLabelWidget.element.style.color = this.getColor(isGroupActive ? TAB_ACTIVE_FOREGROUND : TAB_UNFOCUSED_ACTIVE_FOREGROUND); - } else { + } + + // Tab is inactive + else { // Containr removeClass(tabContainer, 'active'); diff --git a/src/vs/workbench/browser/parts/editor2/nextTitleControl.ts b/src/vs/workbench/browser/parts/editor2/nextTitleControl.ts index 0a5804c0ea118ddfe433089e05852a061a743e9b..f468812cc5ef9c2e977f2870da4e92ec6bd5f119 100644 --- a/src/vs/workbench/browser/parts/editor2/nextTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor2/nextTitleControl.ts @@ -95,8 +95,6 @@ export abstract class NextTitleControl extends Themable { protected abstract create(parent: HTMLElement): void; - protected abstract redraw(): void; - protected createEditorActionsToolBar(container: HTMLElement): void { this.editorActionsToolbar = this._register(new ToolBar(container, this.contextMenuService, { actionItemProvider: action => this.actionItemProvider(action as Action),