提交 35a8792d 编写于 作者: B Benjamin Pasero

grid - implement better active/inactive group tracking and updating

上级 5941131a
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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?
......
......@@ -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);
}
......
......@@ -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()) {
......
......@@ -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<void> {
run(action: IAction, context?: any): TPromise<void> {
const group = this.group();
if (!group) {
return TPromise.as(void 0);
......
......@@ -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
}
......@@ -139,7 +139,6 @@ export interface IEditorPart {
getActiveEditorInput(): IEditorInput;
}
// TODO@grid temporary
export class NoOpEditorPart implements IEditorPart, IEditorGroupService {
_serviceBrand: ServiceIdentifier<any>;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册