diff --git a/src/vs/workbench/browser/parts/editor2/media/nextNoTabsTitleControl.css b/src/vs/workbench/browser/parts/editor2/media/nextNoTabsTitleControl.css index c47a19aa0e796825716f1c3be0187f3d48b34704..de1df91812cfe8c0687c38870a8dcbf68138857a 100644 --- a/src/vs/workbench/browser/parts/editor2/media/nextNoTabsTitleControl.css +++ b/src/vs/workbench/browser/parts/editor2/media/nextNoTabsTitleControl.css @@ -24,7 +24,7 @@ opacity: 0.5; } -.monaco-workbench > .part.editor > .content .editor-group-container > .title.active .title-actions { +.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .title-actions { opacity: 1; } diff --git a/src/vs/workbench/browser/parts/editor2/media/nextTabsTitleControl.css b/src/vs/workbench/browser/parts/editor2/media/nextTabsTitleControl.css index 8d05eea86d3a799faba6025215b3e7f3ef6835d5..11dfbf45576af91359a2e4573779b821e5074365 100644 --- a/src/vs/workbench/browser/parts/editor2/media/nextTabsTitleControl.css +++ b/src/vs/workbench/browser/parts/editor2/media/nextTabsTitleControl.css @@ -149,11 +149,11 @@ display: none; /* hide the close action bar when we are configured to hide it */ } -.monaco-workbench > .part.editor > .content .editor-group-container > .title.active .tabs-container > .tab.active > .tab-close .action-label, /* always show it for active tab */ -.monaco-workbench > .part.editor > .content .editor-group-container > .title.active .tabs-container > .tab > .tab-close .action-label:focus, /* always show it on focus */ -.monaco-workbench > .part.editor > .content .editor-group-container > .title.active .tabs-container > .tab:hover > .tab-close .action-label, /* always show it on hover */ -.monaco-workbench > .part.editor > .content .editor-group-container > .title.active .tabs-container > .tab.active:hover > .tab-close .action-label, /* always show it on hover */ -.monaco-workbench > .part.editor > .content .editor-group-container > .title.active .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-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 */ opacity: 1; } diff --git a/src/vs/workbench/browser/parts/editor2/nextEditorGroupView.ts b/src/vs/workbench/browser/parts/editor2/nextEditorGroupView.ts index 6f342fa09a8270589c1314938b5671dca499befb..057340cdbd6402c65cb2d7bada1958825887515c 100644 --- a/src/vs/workbench/browser/parts/editor2/nextEditorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor2/nextEditorGroupView.ts @@ -10,7 +10,7 @@ import { EditorGroup } from 'vs/workbench/common/editor/editorStacksModel'; import { EditorInput, EditorOptions, GroupIdentifier } from 'vs/workbench/common/editor'; import { Event, Emitter } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { addClass, addClasses, Dimension, trackFocus } from 'vs/base/browser/dom'; +import { addClass, addClasses, Dimension, trackFocus, toggleClass } from 'vs/base/browser/dom'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; @@ -69,6 +69,18 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG return this._onWillDispose.event; } + setActive(isActive: boolean): void { + + // Update container + toggleClass(this.element, 'active', isActive); + toggleClass(this.element, 'inactive', !isActive); + + // Update title control + if (this.titleAreaControl) { + this.titleAreaControl.setActive(isActive); + } + } + //#region INextEditorGroup Implementation get id(): GroupIdentifier { @@ -84,11 +96,8 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG // Update model this.group.openEditor(input, options); - // Update title control - // TODO@grid also, wouldn't it be better if the title widget would register as listener to changes to the group and just - // refresh itself instead of having to do this from the outside? - // See editorGroupsControl#handleStacksChanged() as example for how this is done currently - this.doCreateOrGetTitleControl().refresh(true); + // Forward to title control + this.doCreateOrGetTitleControl().openEditor(input, options); // Forward to editor control // TODO@grid emit input change event when it changed from nextEditorPart? diff --git a/src/vs/workbench/browser/parts/editor2/nextEditorPart.ts b/src/vs/workbench/browser/parts/editor2/nextEditorPart.ts index 9ba58ccda509ae137ccc7926716d4f18162b9479..b2974b8ac4b1321ed6efe651a2b45b54f32374f3 100644 --- a/src/vs/workbench/browser/parts/editor2/nextEditorPart.ts +++ b/src/vs/workbench/browser/parts/editor2/nextEditorPart.ts @@ -112,7 +112,22 @@ export class NextEditorPart extends Part implements INextEditorGroupsService { } private doSetGroupActive(group: NextEditorGroupView): void { + if (this._activeGroup === group) { + return; // return if this is already the active group + } + + const previousActiveGroup = this._activeGroup; this._activeGroup = group; + + // Mark previous one as inactive + if (previousActiveGroup) { + previousActiveGroup.setActive(false); + } + + // Mark group as new active + group.setActive(true); + + // Event this._onDidActiveGroupChange.fire(group); } diff --git a/src/vs/workbench/browser/parts/editor2/nextNoTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor2/nextNoTabsTitleControl.ts index 650b5aeab0762775e13bdbff0f1e29a05f45f6c6..d2fec9de69c7d8d0afd70cbb225610309f983390 100644 --- a/src/vs/workbench/browser/parts/editor2/nextNoTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor2/nextNoTabsTitleControl.ts @@ -54,9 +54,7 @@ export class NextNoTabsTitleControl extends NextTitleControl { private onTitleLabelClick(e: MouseEvent): void { DOM.EventHelper.stop(e, false); - if (!this.dragged) { - setTimeout(() => this.quickOpenService.show()); // delayed to let the onTitleClick() come first which can cause a focus change which can close quick open - } + setTimeout(() => this.quickOpenService.show()); // delayed to let the onTitleClick() come first which can cause a focus change which can close quick open } private onTitleDoubleClick(e: MouseEvent): void { @@ -91,14 +89,7 @@ export class NextNoTabsTitleControl extends NextTitleControl { } const isPinned = this.group.isPinned(this.group.activeEditor); - const isActive = this.stacks.isActive(this.group); - - // Activity state - if (isActive) { - DOM.addClass(this.titleContainer, 'active'); - } else { - DOM.removeClass(this.titleContainer, 'active'); - } + const isActive = this.nextEditorGroupsService.isGroupActive(this.group.id); // Dirty state if (editor.isDirty()) { diff --git a/src/vs/workbench/browser/parts/editor2/nextTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor2/nextTabsTitleControl.ts index bf2ad1eb588cef19370e5bc146a65248d53ae972..97bed87b54fa89e5e0de8507f227f5c7c297edd6 100644 --- a/src/vs/workbench/browser/parts/editor2/nextTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor2/nextTabsTitleControl.ts @@ -42,6 +42,7 @@ import { ResourcesDropHandler, fillResourceDataTransfers, LocalSelectionTransfer import { Color } from 'vs/base/common/color'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { INextEditorGroupsService } from 'vs/workbench/services/editor/common/nextEditorGroupsService'; interface IEditorInputLabel { name: string; @@ -71,6 +72,7 @@ export class NextTabsTitleControl extends NextTitleControl { @IInstantiationService instantiationService: IInstantiationService, @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IEditorGroupService editorGroupService: IEditorGroupService, + @INextEditorGroupsService nextEditorGroupsService: INextEditorGroupsService, @IContextKeyService contextKeyService: IContextKeyService, @IKeybindingService keybindingService: IKeybindingService, @ITelemetryService telemetryService: ITelemetryService, @@ -80,7 +82,7 @@ export class NextTabsTitleControl extends NextTitleControl { @IThemeService themeService: IThemeService, @IExtensionService extensionService: IExtensionService ) { - super(parent, group, contextMenuService, instantiationService, editorService, editorGroupService, contextKeyService, keybindingService, telemetryService, notificationService, menuService, quickOpenService, themeService, extensionService); + super(parent, group, contextMenuService, instantiationService, editorService, editorGroupService, nextEditorGroupsService, contextKeyService, keybindingService, telemetryService, notificationService, menuService, quickOpenService, themeService, extensionService); this.tabDisposeables = []; this.editorLabels = []; @@ -254,21 +256,13 @@ export class NextTabsTitleControl extends NextTitleControl { protected doUpdate(): void { - // Tabs container activity state - const isGroupActive = this.stacks.isActive(this.group); - if (isGroupActive) { - DOM.addClass(this.titleContainer, 'active'); - DOM.removeClass(this.titleContainer, 'inactive'); - } else { - DOM.addClass(this.titleContainer, 'inactive'); - DOM.removeClass(this.titleContainer, 'active'); - } // Compute labels and protect against duplicates const editorsOfGroup = this.group.getEditors(); const labels = this.getTabLabels(editorsOfGroup); // Tab label and styles + const isGroupActive = this.nextEditorGroupsService.isGroupActive(this.group.id); editorsOfGroup.forEach((editor, index) => { const tabContainer = this.tabsContainer.children[index] as HTMLElement; if (!tabContainer) { @@ -460,10 +454,9 @@ export class NextTabsTitleControl extends NextTitleControl { const editor = this.group.activeEditor; if (!editor) { this.clearTabs(); - this.clearEditorActionsToolbar(); - return; // return early if we are being closed + return; } // Handle Tabs @@ -544,7 +537,7 @@ export class NextTabsTitleControl extends NextTitleControl { return tabContainer; } - public layout(dimension: DOM.Dimension): void { + layout(dimension: DOM.Dimension): void { if (!this.activeTab || !dimension) { return; } @@ -857,7 +850,7 @@ export class NextTabsTitleControl extends NextTitleControl { return !isCopy || source.id === target.id; } - public dispose(): void { + dispose(): void { super.dispose(); this.layoutScheduled = dispose(this.layoutScheduled); @@ -873,7 +866,7 @@ class TabActionRunner extends ActionRunner { super(); } - public run(action: IAction, context?: any): TPromise { + run(action: IAction, context?: any): TPromise { const group = this.group(); if (!group) { return TPromise.as(void 0); diff --git a/src/vs/workbench/browser/parts/editor2/nextTitleControl.ts b/src/vs/workbench/browser/parts/editor2/nextTitleControl.ts index 94829e6b315c31fc83488a7cd7ba32f5b4a56226..a791f576f4093b46c8bdcac2bb7c5e2eb194d14c 100644 --- a/src/vs/workbench/browser/parts/editor2/nextTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor2/nextTitleControl.ts @@ -13,7 +13,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { RunOnceScheduler } from 'vs/base/common/async'; import * as arrays from 'vs/base/common/arrays'; -import { IEditorStacksModel, IEditorIdentifier, EditorInput, toResource, IEditorCommandsContext, IEditorGroup } from 'vs/workbench/common/editor'; +import { IEditorStacksModel, IEditorIdentifier, EditorInput, toResource, IEditorCommandsContext, IEditorGroup, EditorOptions } from 'vs/workbench/common/editor'; import { IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -35,33 +35,27 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Themable } from 'vs/workbench/common/theme'; import { isDiffEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { Dimension, findParentWithClass } from 'vs/base/browser/dom'; +import { Dimension } from 'vs/base/browser/dom'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { INextEditorGroupsService } from 'vs/workbench/services/editor/common/nextEditorGroupsService'; export interface IToolbarActions { primary: IAction[]; secondary: IAction[]; } -export interface INextTitleAreaControl { - allowDragging(element: HTMLElement): boolean; - setDragged(dragged: boolean): void; +export interface INextTitleAreaControl extends IDisposable { - refresh(instant?: boolean): void; - update(instant?: boolean): void; - updateEditorActionsToolbar(): void; + openEditor(input: EditorInput, options?: EditorOptions): void; + setActive(isActive: boolean): void; layout(dimension: Dimension): void; - - dispose(): void; } export abstract class NextTitleControl extends Themable implements INextTitleAreaControl { protected stacks: IEditorStacksModel; - protected dragged: boolean; - protected closeOneEditorAction: CloseOneEditorAction; protected splitEditorAction: SplitEditorAction; @@ -86,6 +80,7 @@ export abstract class NextTitleControl extends Themable implements INextTitleAre @IInstantiationService protected instantiationService: IInstantiationService, @IWorkbenchEditorService protected editorService: IWorkbenchEditorService, @IEditorGroupService protected editorGroupService: IEditorGroupService, + @INextEditorGroupsService protected nextEditorGroupsService: INextEditorGroupsService, @IContextKeyService protected contextKeyService: IContextKeyService, @IKeybindingService protected keybindingService: IKeybindingService, @ITelemetryService protected telemetryService: ITelemetryService, @@ -120,23 +115,12 @@ export abstract class NextTitleControl extends Themable implements INextTitleAre private registerListeners(): void { - // Update when extensions register so that e.g. - // actions are properly reflected in the toolbar - this._register(this.extensionService.onDidRegisterExtensions(() => this.update())); + // Update when extensions register so that e.g. actions are properly reflected in the toolbar + this._register(this.extensionService.onDidRegisterExtensions(() => this.doScheduleUpdate())); } protected abstract doCreate(parent: HTMLElement): void; - public setDragged(dragged: boolean): void { - this.dragged = dragged; - } - - protected updateStyles(): void { - super.updateStyles(); - - this.update(true); // run an update when the theme changes to new styles - } - private onSchedule(): void { if (this.refreshScheduled) { this.doRefresh(); @@ -147,7 +131,7 @@ export abstract class NextTitleControl extends Themable implements INextTitleAre this.refreshScheduled = false; } - public update(instant?: boolean): void { + private doScheduleUpdate(instant?: boolean): void { if (instant) { this.titleAreaUpdateScheduler.cancel(); this.onSchedule(); @@ -158,7 +142,7 @@ export abstract class NextTitleControl extends Themable implements INextTitleAre this.titleAreaToolbarUpdateScheduler.cancel(); // a title area update will always refresh the toolbar too } - public refresh(instant?: boolean) { + private doScheduleRefresh(instant?: boolean) { this.refreshScheduled = true; if (instant) { @@ -171,19 +155,11 @@ export abstract class NextTitleControl extends Themable implements INextTitleAre this.titleAreaToolbarUpdateScheduler.cancel(); // a title area update will always refresh the toolbar too } - protected abstract doRefresh(): void; - protected doUpdate(): void { this.doRefresh(); } - public layout(dimension: Dimension): void { - // Subclasses can opt in to react on layout - } - - public allowDragging(element: HTMLElement): boolean { - return !findParentWithClass(element, 'monaco-action-bar', 'editor-group-container'); - } + protected abstract doRefresh(): void; protected initActions(services: IInstantiationService): void { this.closeOneEditorAction = services.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL); @@ -285,9 +261,9 @@ export abstract class NextTitleControl extends Themable implements INextTitleAre return { primary, secondary }; } - public updateEditorActionsToolbar(): void { + protected updateEditorActionsToolbar(): void { const editor = this.group.activeEditor; - const isActive = this.stacks.isActive(this.group); + const isActive = this.nextEditorGroupsService.isGroupActive(this.group.id); // Update Editor Actions Toolbar let primaryEditorActions: IAction[] = []; @@ -385,7 +361,32 @@ export abstract class NextTitleControl extends Themable implements INextTitleAre return keybinding ? keybinding.getLabel() : void 0; } - public dispose(): void { + //#region IThemeable implementation + + protected updateStyles(): void { + super.updateStyles(); + + // run a sync update when the theme changes to new styles + this.doScheduleUpdate(true); + } + + //#endregion + + //#region INextTitleAreaControl implementation + + openEditor(input: EditorInput, options?: EditorOptions): void { + this.doScheduleRefresh(true); // TODO@grid optimize if possible + } + + setActive(isActive: boolean): void { + this.doScheduleUpdate(true); // TODO@grid optimize if possible + } + + layout(dimension: Dimension): void { + // Optionally implemented in subclasses + } + + dispose(): void { super.dispose(); // Actions @@ -399,4 +400,6 @@ export abstract class NextTitleControl extends Themable implements INextTitleAre // Toolbar this.editorActionsToolbar.dispose(); } + + //#endregion } diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index 5e0993cbe4259b2ec66c9a9e6a7f09f2e11a3f75..51a22574d9f232b49a8be539cabc72851a6b546a 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -139,7 +139,6 @@ export interface IEditorPart { getActiveEditorInput(): IEditorInput; } -// TODO@grid temporary export class NoOpEditorPart implements IEditorPart, IEditorGroupService { _serviceBrand: ServiceIdentifier;