提交 619c7e86 编写于 作者: B Benjamin Pasero

grid - first cut empty editor groups

上级 c569505a
......@@ -7,6 +7,12 @@
height: 100%;
}
.monaco-workbench > .part.editor > .content .editor-group-container.empty.active {
outline-width: 1px;
outline-style: solid;
outline-offset: -2px;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title {
height: 35px;
display: flex;
......@@ -16,4 +22,9 @@
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-container {
height: calc(100% - 35px); /* below title control */
}
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .title,
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .editor-container {
display: none;
}
\ No newline at end of file
......@@ -54,7 +54,7 @@
display: none;
}
/* Drag Cursor */
/* Drag Cursor (TODO@grid this depends on the feature to drag an entire group to another location) */
.monaco-workbench > .part.editor > .content.multiple-groups .editor-group-container > .title,
.monaco-workbench > .part.editor > .content.multiple-groups .editor-group-container > .title.tabs .scrollbar .slider,
.monaco-workbench > .part.editor > .content.multiple-groups .editor-group-container > .title .monaco-icon-label::before,
......
......@@ -10,14 +10,14 @@ 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, toggleClass } from 'vs/base/browser/dom';
import { addClass, addClasses, Dimension, trackFocus, toggleClass, removeClass } 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';
import { attachProgressBarStyler } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { editorBackground, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { Themable, EDITOR_GROUP_HEADER_TABS_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND } from 'vs/workbench/common/theme';
import { editorBackground, contrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry';
import { Themable, EDITOR_GROUP_HEADER_TABS_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, EDITOR_GROUP_BACKGROUND } from 'vs/workbench/common/theme';
import { IOpenEditorResult, INextEditorGroup } from 'vs/workbench/services/editor/common/nextEditorGroupsService';
import { INextTitleAreaControl } from 'vs/workbench/browser/parts/editor2/nextTitleControl';
import { NextTabsTitleControl } from 'vs/workbench/browser/parts/editor2/nextTabsTitleControl';
......@@ -26,14 +26,20 @@ import { IView } from 'vs/base/browser/ui/grid/gridview';
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';
export class NextEditorGroupView extends Themable implements IView, INextEditorGroup {
private static readonly EDITOR_TITLE_HEIGHT = 35;
private _onDidFocus: Emitter<void> = this._register(new Emitter<void>());
get onDidFocus(): Event<void> { return this._onDidFocus.event; }
private _onWillDispose: Emitter<void> = this._register(new Emitter<void>());
get onWillDispose(): Event<void> { return this._onWillDispose.event; }
private _onDidActiveEditorChange: Emitter<BaseEditor> = this._register(new Emitter<BaseEditor>());
get onDidActiveEditorChange(): Event<BaseEditor> { return this._onDidActiveEditorChange.event; }
private group: EditorGroup;
private dimension: Dimension;
......@@ -57,17 +63,62 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
this.group = this._register(instantiationService.createInstance(EditorGroup, ''));
this.group.label = `Group <${this.group.id}>`;
this.element = document.createElement('div');
addClass(this.element, 'editor-group-container');
this.doRender();
this.doCreate();
this.registerListeners();
}
private registerListeners(): void {
this._register(this.group.onEditorsStructureChanged(() => this.updateContainer()));
}
get onDidFocus(): Event<void> {
return this._onDidFocus.event;
private doCreate(): void {
// Container
addClasses(this.element, 'editor-group-container');
const focusTracker = this._register(trackFocus(this.element));
this._register(focusTracker.onDidFocus(() => {
this._onDidFocus.fire();
}));
// Title container
this.titleContainer = document.createElement('div');
addClasses(this.titleContainer, 'title', 'tabs', 'show-file-icons');
this.element.appendChild(this.titleContainer);
// Progress bar
this.progressBar = this._register(new ProgressBar(this.element));
this._register(attachProgressBarStyler(this.progressBar, this.themeService));
this.progressBar.hide();
// Editor container
this.editorContainer = document.createElement('div');
addClass(this.editorContainer, 'editor-container');
this.element.appendChild(this.editorContainer);
// Update styles
this.updateStyles();
// Update containers
this.updateContainer();
}
get onWillDispose(): Event<void> {
return this._onWillDispose.event;
private updateContainer(): void {
const empty = this.group.count === 0;
// Empty Container: allow to focus
if (empty) {
addClass(this.element, 'empty');
this.element.tabIndex = 0;
this.element.setAttribute('aria-label', localize('emptyEditorGroup', "Empty Editor Group"));
}
// Non-Empty Container: revert empty container attributes
else {
removeClass(this.element, 'empty');
this.element.removeAttribute('tabIndex');
this.element.removeAttribute('aria-label');
}
}
setActive(isActive: boolean): void {
......@@ -84,10 +135,6 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
//#region INextEditorGroup Implementation
get onDidActiveEditorChange(): Event<BaseEditor> {
return this._onDidActiveEditorChange.event;
}
get id(): GroupIdentifier {
return this.group.id;
}
......@@ -175,7 +222,10 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
//#region Themable Implementation
protected updateStyles(): void {
super.updateStyles();
// Container
this.element.style.backgroundColor = this.getColor(EDITOR_GROUP_BACKGROUND);
this.element.style.outlineColor = this.getColor(focusBorder);
// Title control
const borderColor = this.getColor(EDITOR_GROUP_HEADER_TABS_BORDER) || this.getColor(contrastBorder);
......@@ -184,17 +234,15 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
this.titleContainer.style.borderBottomStyle = borderColor ? 'solid' : null;
this.titleContainer.style.borderBottomColor = borderColor;
// Editor background
this.element.style.backgroundColor = this.getColor(editorBackground);
// TODO@grid use editor group background for empty groups?
// Editor container
this.editorContainer.style.backgroundColor = this.getColor(editorBackground);
}
//#endregion
//#region IView implementation
readonly element: HTMLElement;
readonly element: HTMLElement = document.createElement('div');
readonly minimumWidth = 170;
readonly minimumHeight = 70;
......@@ -203,34 +251,6 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
get onDidChange() { return Event.None; }
private doRender(): void {
// Title container
this.titleContainer = document.createElement('div');
addClasses(this.titleContainer, 'title', 'tabs', 'show-file-icons', 'active');
this.element.appendChild(this.titleContainer);
// Progress bar
this.progressBar = this._register(new ProgressBar(this.element));
this._register(attachProgressBarStyler(this.progressBar, this.themeService));
this.progressBar.hide();
// Editor container
this.editorContainer = document.createElement('div');
addClass(this.editorContainer, 'editor-container');
this.editorContainer.setAttribute('role', 'tabpanel');
this.element.appendChild(this.editorContainer);
// Track focus in editor container
const focusTracker = this._register(trackFocus(this.editorContainer));
this._register(focusTracker.onDidFocus(() => {
this._onDidFocus.fire();
}));
// Update styles
this.updateStyles();
}
layout(width: number, height: number): void {
this.dimension = new Dimension(width, height);
......@@ -251,6 +271,8 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
}
}
//#endregion
shutdown(): void {
if (this.editorControl) {
this.editorControl.shutdown();
......@@ -262,6 +284,4 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
super.dispose();
}
//#endregion
}
\ No newline at end of file
......@@ -25,7 +25,10 @@ export class NextEditorPart extends Part implements INextEditorGroupsService {
_serviceBrand: any;
private _onDidLayout: Emitter<Dimension> = this._register(new Emitter<Dimension>());
get onDidLayout(): Event<Dimension> { return this._onDidLayout.event; }
private _onDidActiveGroupChange: Emitter<NextEditorGroupView> = this._register(new Emitter<NextEditorGroupView>());
get onDidActiveGroupChange(): Event<NextEditorGroupView> { return this._onDidActiveGroupChange.event; }
private dimension: Dimension;
......@@ -47,10 +50,6 @@ export class NextEditorPart extends Part implements INextEditorGroupsService {
//#region INextEditorGroupsService Implementation
get onDidActiveGroupChange(): Event<NextEditorGroupView> {
return this._onDidActiveGroupChange.event;
}
get activeGroup(): NextEditorGroupView {
return this._activeGroup;
}
......@@ -163,12 +162,7 @@ export class NextEditorPart extends Part implements INextEditorGroupsService {
//#region Part Implementation
get onDidLayout(): Event<Dimension> {
return this._onDidLayout.event;
}
protected updateStyles(): void {
super.updateStyles();
// Part container
const container = this.getContainer();
......
......@@ -365,10 +365,7 @@ export abstract class NextTitleControl extends Themable implements INextTitleAre
//#region IThemeable implementation
protected updateStyles(): void {
super.updateStyles();
// run a sync update when the theme changes to new styles
this.doScheduleUpdate(true);
this.doScheduleUpdate(true); // run a sync update when the theme changes to new styles
}
//#endregion
......
......@@ -12,7 +12,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { dispose, IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { Position, Direction } from 'vs/platform/editor/common/editor';
import { ResourceMap } from 'vs/base/common/map';
......@@ -44,23 +44,10 @@ export interface ISerializedEditorGroup {
preview: number;
}
export class EditorGroup implements IEditorGroup {
export class EditorGroup extends Disposable implements IEditorGroup {
private static IDS = 0;
private _id: GroupIdentifier;
private _label: string;
private editors: EditorInput[];
private mru: EditorInput[];
private mapResourceToEditorCount: ResourceMap<number>;
private preview: EditorInput; // editor in preview state
private active: EditorInput; // editor in active state
private toDispose: IDisposable[];
private editorOpenPositioning: 'left' | 'right' | 'first' | 'last';
private readonly _onEditorActivated: Emitter<EditorInput>;
private readonly _onEditorOpened: Emitter<EditorInput>;
private readonly _onEditorClosed: Emitter<EditorCloseEvent>;
......@@ -73,32 +60,43 @@ export class EditorGroup implements IEditorGroup {
private readonly _onEditorStateChanged: Emitter<EditorInput>;
private readonly _onEditorsStructureChanged: Emitter<EditorInput>;
private _id: GroupIdentifier;
private _label: string;
private editors: EditorInput[];
private mru: EditorInput[];
private mapResourceToEditorCount: ResourceMap<number>;
private preview: EditorInput; // editor in preview state
private active: EditorInput; // editor in active state
private editorOpenPositioning: 'left' | 'right' | 'first' | 'last';
constructor(
arg1: string | ISerializedEditorGroup,
@IInstantiationService private instantiationService: IInstantiationService,
@IConfigurationService private configurationService: IConfigurationService
) {
super();
this._id = EditorGroup.IDS++;
this.editors = [];
this.mru = [];
this.toDispose = [];
this.mapResourceToEditorCount = new ResourceMap<number>();
this.onConfigurationUpdated();
this._onEditorActivated = new Emitter<EditorInput>();
this._onEditorOpened = new Emitter<EditorInput>();
this._onEditorClosed = new Emitter<EditorCloseEvent>();
this._onEditorDisposed = new Emitter<EditorInput>();
this._onEditorDirty = new Emitter<EditorInput>();
this._onEditorLabelChange = new Emitter<EditorInput>();
this._onEditorMoved = new Emitter<EditorInput>();
this._onEditorPinned = new Emitter<EditorInput>();
this._onEditorUnpinned = new Emitter<EditorInput>();
this._onEditorStateChanged = new Emitter<EditorInput>();
this._onEditorsStructureChanged = new Emitter<EditorInput>();
this.toDispose.push(this._onEditorActivated, this._onEditorOpened, this._onEditorClosed, this._onEditorDisposed, this._onEditorDirty, this._onEditorLabelChange, this._onEditorMoved, this._onEditorPinned, this._onEditorUnpinned, this._onEditorStateChanged, this._onEditorsStructureChanged);
this._onEditorActivated = this._register(new Emitter<EditorInput>());
this._onEditorOpened = this._register(new Emitter<EditorInput>());
this._onEditorClosed = this._register(new Emitter<EditorCloseEvent>());
this._onEditorDisposed = this._register(new Emitter<EditorInput>());
this._onEditorDirty = this._register(new Emitter<EditorInput>());
this._onEditorLabelChange = this._register(new Emitter<EditorInput>());
this._onEditorMoved = this._register(new Emitter<EditorInput>());
this._onEditorPinned = this._register(new Emitter<EditorInput>());
this._onEditorUnpinned = this._register(new Emitter<EditorInput>());
this._onEditorStateChanged = this._register(new Emitter<EditorInput>());
this._onEditorsStructureChanged = this._register(new Emitter<EditorInput>());
if (typeof arg1 === 'object') {
this.deserialize(arg1);
......@@ -110,7 +108,7 @@ export class EditorGroup implements IEditorGroup {
}
private registerListeners(): void {
this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(e)));
this._register(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(e)));
}
private onConfigurationUpdated(event?: IConfigurationChangeEvent): void {
......@@ -687,10 +685,6 @@ export class EditorGroup implements IEditorGroup {
this.active = this.mru[0];
this.preview = this.editors[data.preview];
}
public dispose(): void {
dispose(this.toDispose);
}
}
interface ISerializedEditorStacksModel {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册