diff --git a/src/vs/workbench/browser/parts/nexteditor/nextEditorPart.ts b/src/vs/workbench/browser/parts/nexteditor/nextEditorPart.ts new file mode 100644 index 0000000000000000000000000000000000000000..15bacf7b2e8bfcf246e7762da59de89478706b76 --- /dev/null +++ b/src/vs/workbench/browser/parts/nexteditor/nextEditorPart.ts @@ -0,0 +1,74 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import 'vs/workbench/browser/parts/editor/editor.contribution'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { Part } from 'vs/workbench/browser/part'; +import { INextEditorGroupService } from 'vs/workbench/services/group/common/nextGroupService'; +import { Dimension, addClass } from 'vs/base/browser/dom'; +import { Event, Emitter } from 'vs/base/common/event'; +import { INextWorkbenchEditorService } from 'vs/workbench/services/editor/common/nextEditorService'; + +export class NextEditorPart extends Part implements INextWorkbenchEditorService, INextEditorGroupService { + + public _serviceBrand: any; + + private readonly _onLayout: Emitter; + + // private dimension: Dimension; + + constructor( + id: string, + @IThemeService themeService: IThemeService + ) { + super(id, { hasTitle: false }, themeService); + + this._onLayout = new Emitter(); + } + + public get onLayout(): Event { + return this._onLayout.event; + } + + public createContentArea(parent: HTMLElement): HTMLElement { + const contentArea = document.createElement('div'); + addClass(contentArea, 'content'); + parent.appendChild(contentArea); + + return contentArea; + } + + protected updateStyles(): void { + super.updateStyles(); + + // TODO@next update styles + } + + public layout(dimension: Dimension): Dimension[] { + const sizes = super.layout(dimension); + + // this.dimension = sizes[1]; + + // TODO@next propagate layout + + this._onLayout.fire(dimension); + + return sizes; + } + + public dispose(): void { + + // Emitters + this._onLayout.dispose(); + + // TODO@next dispose + // - all visible and instantiated editors + // - tokens for opening + + super.dispose(); + } +} \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index c007900105a2de16ebc066c070f8ebb997202fca..7f4103e675ba4bfca9cfd2c80e9653ef7244be70 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -26,7 +26,6 @@ import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } fr import { IEditorInputFactoryRegistry, Extensions as EditorExtensions } from 'vs/workbench/common/editor'; import { HistoryService } from 'vs/workbench/services/history/electron-browser/history'; import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activitybarPart'; -import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart'; import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart'; import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart'; import { StatusbarPart } from 'vs/workbench/browser/parts/statusbar/statusbarPart'; @@ -60,7 +59,7 @@ import { IConfigurationResolverService } from 'vs/workbench/services/configurati import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/electron-browser/configurationResolverService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { ITitleService } from 'vs/workbench/services/title/common/titleService'; -import { IWorkbenchEditorService, IResourceInputType, WorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IWorkbenchEditorService, IResourceInputType, WorkbenchEditorService, NoOpEditorPart } from 'vs/workbench/services/editor/common/editorService'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { ClipboardService } from 'vs/platform/clipboard/electron-browser/clipboardService'; @@ -110,6 +109,9 @@ import { IPCClient } from 'vs/base/parts/ipc/common/ipc'; import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService'; +import { INextEditorService } from 'vs/workbench/services/editor/common/nextEditorService'; +import { NextEditorPart } from 'vs/workbench/browser/parts/nexteditor/nextEditorPart'; +import { INextEditorGroupService } from 'vs/workbench/services/group/common/nextGroupService'; export const EditorsVisibleContext = new RawContextKey('editorIsOpen', false); export const InZenModeContext = new RawContextKey('inZenMode', false); @@ -191,8 +193,9 @@ export class Workbench implements IPartService { private workbench: Builder; private workbenchStarted: boolean; private workbenchCreated: boolean; + private editorService: IWorkbenchEditorService; + private editorGroupService: IEditorGroupService; private workbenchShutdown: boolean; - private editorService: WorkbenchEditorService; private viewletService: IViewletService; private contextKeyService: IContextKeyService; private keybindingService: IKeybindingService; @@ -202,7 +205,8 @@ export class Workbench implements IPartService { private activitybarPart: ActivitybarPart; private sidebarPart: SidebarPart; private panelPart: PanelPart; - private editorPart: EditorPart; + private noOpEditorPart: NoOpEditorPart; // TODO@next adopt methods in next editor part + private editorPart: NextEditorPart; private statusbarPart: StatusbarPart; private quickOpen: QuickOpenController; private quickInput: QuickInputService; @@ -352,7 +356,7 @@ export class Workbench implements IPartService { if (inputs.length) { editorOpenPromise = this.editorService.openEditors(inputs.map(input => { return { input, position: EditorPosition.ONE }; })); } else { - editorOpenPromise = this.editorPart.restoreEditors(); + editorOpenPromise = this.noOpEditorPart.restoreEditors(); } return editorOpenPromise.then(editors => { @@ -472,7 +476,7 @@ export class Workbench implements IPartService { // Empty workbench else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.openUntitledFile()) { - if (this.editorPart.hasEditorsToRestore()) { + if (this.noOpEditorPart.hasEditorsToRestore()) { return TPromise.as([]); // do not open any empty untitled file if we have editors to restore } @@ -588,12 +592,18 @@ export class Workbench implements IPartService { serviceCollection.set(IFileService, this.fileService); this.configurationService.acquireFileService(this.fileService); - // Editor service (editor part) - this.editorPart = this.instantiationService.createInstance(EditorPart, Identifiers.EDITOR_PART, !this.hasFilesToCreateOpenOrDiff); + // Editor service (next editor part) + this.editorPart = this.instantiationService.createInstance(NextEditorPart, Identifiers.EDITOR_PART /*, !this.hasFilesToCreateOpenOrDiff*/); this.toUnbind.push({ dispose: () => this.editorPart.shutdown() }); - this.editorService = this.instantiationService.createInstance(WorkbenchEditorService, this.editorPart); + serviceCollection.set(INextEditorService, this.editorPart); + serviceCollection.set(INextEditorGroupService, this.editorPart); + + // Legacy Editor Services + this.noOpEditorPart = new NoOpEditorPart(this.instantiationService); + this.editorService = this.instantiationService.createInstance(WorkbenchEditorService, this.noOpEditorPart); + this.editorGroupService = this.noOpEditorPart; serviceCollection.set(IWorkbenchEditorService, this.editorService); - serviceCollection.set(IEditorGroupService, this.editorPart); + serviceCollection.set(IEditorGroupService, this.noOpEditorPart); // Title bar this.titlebarPart = this.instantiationService.createInstance(TitlebarPart, Identifiers.TITLEBAR_PART); @@ -852,7 +862,7 @@ export class Workbench implements IPartService { let promise = TPromise.wrap(null); if (hidden && this.sidebarPart.getActiveViewlet()) { promise = this.sidebarPart.hideActiveViewlet().then(() => { - const activeEditor = this.editorPart.getActiveEditor(); + const activeEditor = this.editorService.getActiveEditor(); const activePanel = this.panelPart.getActivePanel(); // Pass Focus to Editor or Panel if Sidebar is now hidden @@ -903,8 +913,9 @@ export class Workbench implements IPartService { let promise = TPromise.wrap(null); if (hidden && this.panelPart.getActivePanel()) { promise = this.panelPart.hideActivePanel().then(() => { + // Pass Focus to Editor if Panel part is now hidden - const editor = this.editorPart.getActiveEditor(); + const editor = this.editorService.getActiveEditor(); if (editor) { editor.focus(); } @@ -1044,14 +1055,14 @@ export class Workbench implements IPartService { private registerListeners(): void { // Listen to editor changes - this.toUnbind.push(this.editorPart.onEditorsChanged(() => this.onEditorsChanged())); + this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); // Listen to editor closing (if we run with --wait) const filesToWait = this.workbenchParams.configuration.filesToWait; if (filesToWait) { const resourcesToWaitFor = filesToWait.paths.map(p => URI.file(p.filePath)); const waitMarkerFile = URI.file(filesToWait.waitMarkerFilePath); - const listenerDispose = this.editorPart.getStacksModel().onEditorClosed(() => this.onEditorClosed(listenerDispose, resourcesToWaitFor, waitMarkerFile)); + const listenerDispose = this.editorGroupService.getStacksModel().onEditorClosed(() => this.onEditorClosed(listenerDispose, resourcesToWaitFor, waitMarkerFile)); this.toUnbind.push(listenerDispose); } @@ -1092,7 +1103,7 @@ export class Workbench implements IPartService { // In wait mode, listen to changes to the editors and wait until the files // are closed that the user wants to wait for. When this happens we delete // the wait marker file to signal to the outside that editing is done. - const stacks = this.editorPart.getStacksModel(); + const stacks = this.editorGroupService.getStacksModel(); if (resourcesToWaitFor.every(r => !stacks.isOpen(r))) { listenerDispose.dispose(); this.fileService.del(waitMarkerFile).done(null, errors.onUnexpectedError); @@ -1344,9 +1355,9 @@ export class Workbench implements IPartService { public toggleZenMode(skipLayout?: boolean): void { this.zenMode.active = !this.zenMode.active; - // Check if zen mode transitioned to full screen and if now we are out of zen mode -> we need to go out of full screen + // Check if zen mode transitioned to full screen and if now we are out of zen mode + // -> we need to go out of full screen (same goes for the centered editor layout) let toggleFullScreen = false; - // Same goes for the centered editor layout if (this.zenMode.active) { const config = this.configurationService.getValue('zenMode'); toggleFullScreen = !browser.isFullscreen() && config.fullScreen; @@ -1366,7 +1377,7 @@ export class Workbench implements IPartService { } if (config.hideTabs) { - this.editorPart.hideTabs(true); + this.noOpEditorPart.hideTabs(true); } if (config.centerLayout) { @@ -1385,8 +1396,8 @@ export class Workbench implements IPartService { // Status bar and activity bar visibility come from settings -> update their visibility. this.onDidUpdateConfiguration(true); - this.editorPart.hideTabs(false); - const activeEditor = this.editorPart.getActiveEditor(); + this.noOpEditorPart.hideTabs(false); + const activeEditor = this.editorService.getActiveEditor(); if (activeEditor) { activeEditor.focus(); } diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index c3e448321aff2bba10457ec1b309df099f2dbb2e..6e492bafc7d074e80d416a88cf24d3294c489c42 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -6,12 +6,12 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import { createDecorator, ServiceIdentifier, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { createDecorator, ServiceIdentifier, IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IEditorService, IEditor, IEditorInput, IEditorOptions, ITextEditorOptions, Position, Direction, IResourceInput, IResourceDiffInput, IResourceSideBySideInput, IUntitledResourceInput } from 'vs/platform/editor/common/editor'; import URI from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; import { basename } from 'vs/base/common/paths'; -import { EditorInput, EditorOptions, TextEditorOptions, Extensions as EditorExtensions, SideBySideEditorInput, IFileEditorInput, IFileInputFactory, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, TextEditorOptions, Extensions as EditorExtensions, SideBySideEditorInput, IFileEditorInput, IFileInputFactory, IEditorInputFactoryRegistry, IEditorStacksModel, IEditorOpeningEvent, IEditorGroup, IStacksModelChangeEvent, IEditorCloseEvent, IEditorIdentifier } from 'vs/workbench/common/editor'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; @@ -19,11 +19,12 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import * as nls from 'vs/nls'; import { getPathLabel } from 'vs/base/common/labels'; import { ResourceMap } from 'vs/base/common/map'; -import { once } from 'vs/base/common/event'; +import { Event, Emitter, once } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IFileService } from 'vs/platform/files/common/files'; import { DataUriEditorInput } from 'vs/workbench/common/editor/dataUriEditorInput'; import { Schemas } from 'vs/base/common/network'; +import { IEditorGroupService, IEditorTabOptions, GroupArrangement } from 'vs/workbench/services/group/common/groupService'; export const IWorkbenchEditorService = createDecorator('editorService'); @@ -138,6 +139,144 @@ export interface IEditorPart { getActiveEditorInput(): IEditorInput; } +// TODO@next temporary +export class NoOpEditorPart implements IEditorPart, IEditorGroupService { + + _serviceBrand: ServiceIdentifier; + stacks: IEditorStacksModel; + + constructor(private instantiationService: IInstantiationService) { + this.stacks = new NoOpEditorStacksModel(); + } + + onEditorsChanged: Event = new Emitter().event; + onEditorOpening: Event = new Emitter().event; + onEditorOpenFail: Event = new Emitter().event; + onEditorGroupMoved: Event = new Emitter().event; + onGroupOrientationChanged: Event = new Emitter().event; + onTabOptionsChanged: Event = new Emitter().event; + + focusGroup(...args: any[]) { } + + activateGroup(...args: any[]) { } + + moveGroup(...args: any[]) { } + + arrangeGroups(arrangement: GroupArrangement): void { } + + setGroupOrientation(orientation: 'vertical' | 'horizontal'): void { } + + getGroupOrientation(): 'vertical' | 'horizontal' { + return 'vertical'; + } + + resizeGroup(position: Position, groupSizeChange: number): void { } + + pinEditor(...args: any[]) { } + + moveEditor(...args: any[]) { } + + getStacksModel(): IEditorStacksModel { + return this.stacks; + } + + getTabOptions(): IEditorTabOptions { + return Object.create(null); + } + + invokeWithinEditorContext(fn: (accessor: ServicesAccessor) => T): T { + return this.instantiationService.invokeFunction(fn); + } + + openEditor(...args: any[]) { + return TPromise.as(void 0); + } + + openEditors(...args: any[]) { + return TPromise.as([]); + } + + replaceEditors(editors: { toReplace: IEditorInput; replaceWith: IEditorInput; options?: IEditorOptions | ITextEditorOptions; }[], position?: Position): TPromise { + return TPromise.as(void 0); + } + + closeEditors(...args: any[]) { + return TPromise.as(void 0); + } + + closeEditor(position: Position, input: IEditorInput): TPromise { + return TPromise.as(void 0); + } + + getActiveEditor(): IEditor { + return null; + } + + getVisibleEditors(): IEditor[] { + return []; + } + + getActiveEditorInput(): IEditorInput { + return null; + } + + hideTabs(...args: any[]): void { } + + hasEditorsToRestore(): boolean { + return false; + } + + restoreEditors(): any { + return TPromise.as([]); + } +} + +class NoOpEditorStacksModel implements IEditorStacksModel { + + onModelChanged: Event = new Emitter().event; + onWillCloseEditor: Event = new Emitter().event; + onEditorClosed: Event = new Emitter().event; + + groups: IEditorGroup[] = []; + activeGroup: IEditorGroup; + + isActive(group: IEditorGroup): boolean { + return false; + } + + getGroup(id: number): IEditorGroup { + return null; + } + + positionOfGroup(group: IEditorGroup): Position { + return Position.ONE; + } + + groupAt(position: Position): IEditorGroup { + return null; + } + + next(jumpGroups: boolean, cycleAtEnd?: boolean): IEditorIdentifier { + return null; + } + + previous(jumpGroups: boolean, cycleAtStart?: boolean): IEditorIdentifier { + return null; + } + + last(): IEditorIdentifier { + return null; + } + + isOpen(resource: URI): boolean { + return false; + } + + toString(): string { + return ''; + } +} + type ICachedEditorInput = ResourceEditorInput | IFileEditorInput | DataUriEditorInput; export class WorkbenchEditorService implements IWorkbenchEditorService { diff --git a/src/vs/workbench/services/editor/common/nextEditorService.ts b/src/vs/workbench/services/editor/common/nextEditorService.ts new file mode 100644 index 0000000000000000000000000000000000000000..00b119692338882ce65d6faea6c6b2bfc88fd3b2 --- /dev/null +++ b/src/vs/workbench/services/editor/common/nextEditorService.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; + +export const INextEditorService = createDecorator('nextWorkbenchEditorService'); + +export interface INextWorkbenchEditorService { + _serviceBrand: ServiceIdentifier; +} \ No newline at end of file diff --git a/src/vs/workbench/services/group/common/nextGroupService.ts b/src/vs/workbench/services/group/common/nextGroupService.ts new file mode 100644 index 0000000000000000000000000000000000000000..e65c3edf4001a95645d0c37a23a3676a5870bbfa --- /dev/null +++ b/src/vs/workbench/services/group/common/nextGroupService.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; + +export const INextEditorGroupService = createDecorator('nextEditorGroupService'); + +export interface INextEditorGroupService { + _serviceBrand: ServiceIdentifier; +} \ No newline at end of file