提交 68ed2365 编写于 作者: B Benjamin Pasero

grid - handle editor close properly as before

上级 83055547
......@@ -38,7 +38,7 @@ import { RunOnceWorker } from 'vs/base/common/async';
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
export interface IGroupsAccessor {
isOpenedInOtherGroup(editor: EditorInput): boolean;
getGroups(): NextEditorGroupView[];
}
export class NextEditorGroupView extends Themable implements IView, INextEditorGroup {
......@@ -60,6 +60,12 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
private _onWillOpenEditor: Emitter<IEditorOpeningEvent> = this._register(new Emitter<IEditorOpeningEvent>());
get onWillOpenEditor(): Event<IEditorOpeningEvent> { return this._onWillOpenEditor.event; }
private _onWillCloseEditor: Emitter<EditorInput> = this._register(new Emitter<EditorInput>());
get onWillCloseEditor(): Event<EditorInput> { return this._onWillCloseEditor.event; }
private _onDidCloseEditor: Emitter<EditorInput> = this._register(new Emitter<EditorInput>());
get onDidCloseEditor(): Event<EditorInput> { return this._onDidCloseEditor.event; }
private _onDidOpenEditorFail: Emitter<EditorInput> = this._register(new Emitter<EditorInput>());
get onDidOpenEditorFail(): Event<EditorInput> { return this._onDidOpenEditorFail.event; }
......@@ -100,7 +106,7 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
} else {
this.group = this._register(instantiationService.createInstance(EditorGroup, ''));
}
this.group.label = `Group <${this.group.id}>`;
this.group.label = `Group <${this.group.id}>`; // TODO@grid find a way to have a proper label
this.disposedEditorsWorker = this._register(new RunOnceWorker(editors => this.handleDisposedEditors(editors), 0));
......@@ -109,11 +115,15 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
}
private registerListeners(): void {
// Model Events
this._register(this.group.onEditorsStructureChanged(() => this.updateContainer()));
this._register(this.group.onEditorDirty(editor => this.pinEditor(editor)));
this._register(this.group.onEditorOpened(editor => this.onEditorOpened(editor)));
this._register(this.group.onEditorClosed(editor => this.onEditorClosed(editor)));
this._register(this.group.onEditorDisposed(editor => this.onEditorDisposed(editor)));
// Configuration Changes
this._register(this.configurationService.onDidChangeConfiguration(e => this.onDidChangeConfiguration(e)));
}
......@@ -129,6 +139,16 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
}
private onEditorClosed(event: EditorCloseEvent): void {
// Before close
this._onWillCloseEditor.fire(event.editor);
// Handle event
this.handleEditorClosed(event.editor);
// After close
this._onDidCloseEditor.fire(event.editor);
/* __GDPR__
"editorClosed" : {
"${include}": [
......@@ -139,6 +159,23 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
this.telemetryService.publicLog('editorClosed', event.editor.getTelemetryDescriptor());
}
private handleEditorClosed(editor: EditorInput): void {
const editorsToClose = [editor];
// Include both sides of side by side editors when being closed and not opened multiple times
if (editor instanceof SideBySideEditorInput && !this.groupsAccessor.getGroups().some(groupView => groupView.group.contains(editor))) {
editorsToClose.push(editor.master, editor.details);
}
// Close the editor when it is no longer open in any group including diff editors
editorsToClose.forEach(editorToClose => {
const resource = editorToClose ? editorToClose.getResource() : void 0; // prefer resource to not close right-hand side editors of a diff editor
if (!this.groupsAccessor.getGroups().some(groupView => groupView.group.contains(resource || editorToClose))) {
editorToClose.close();
}
});
}
private onEditorDisposed(editor: EditorInput): void {
// To prevent race conditions, we handle disposed editors in our worker with a timeout
......@@ -247,10 +284,6 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
}
}
contains(editor: EditorInput): boolean {
return this.group.contains(editor);
}
isEmpty(): boolean {
return this.group.count === 0;
}
......@@ -446,6 +479,8 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
private doCloseInactiveEditor(editor: EditorInput): void {
this.group.closeEditor(editor); // Closing inactive editor is just a model update
// TODO@grid need to update the title area control as well!
}
private handleDirty(editors: EditorInput[], ignoreIfOpenedInOtherGroup?: boolean): Thenable<boolean /* veto */> {
......@@ -463,10 +498,20 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
}
private doHandleDirty(editor: EditorInput, ignoreIfOpenedInOtherGroup?: boolean): Thenable<boolean /* veto */> {
if (!editor || !editor.isDirty() || (ignoreIfOpenedInOtherGroup && this.isOpenedInOtherGroup(editor))) {
// Return quickly if editor is not dirty
if (!editor.isDirty()) {
return TPromise.as(false); // no veto
}
// Return if editor is opened in other group and we are OK with it
if (ignoreIfOpenedInOtherGroup) {
const containedInOtherGroup = this.groupsAccessor.getGroups().some(groupView => groupView !== this && groupView.group.contains(editor, true /* support side by side */));
if (containedInOtherGroup) {
return TPromise.as(false); // no veto
}
}
// Switch to editor that we want to handle
return this.openEditor(editor).then(() => {
return editor.confirmSave().then(res => {
......@@ -503,18 +548,6 @@ export class NextEditorGroupView extends Themable implements IView, INextEditorG
});
}
private isOpenedInOtherGroup(editor: EditorInput): boolean {
if (this.groupsAccessor.isOpenedInOtherGroup(editor)) {
return true;
}
if (editor instanceof SideBySideEditorInput && this.groupsAccessor.isOpenedInOtherGroup(editor.master)) {
return true; // consider right-hand-side diff editors too
}
return false;
}
//#endregion
//#region other INextEditorGroup methods
......
......@@ -228,11 +228,7 @@ export class NextEditorPart extends Part implements INextEditorGroupsService {
}
private doCreateGroupView(sourceView?: NextEditorGroupView): NextEditorGroupView {
const groupView = this.instantiationService.createInstance(NextEditorGroupView, sourceView, {
isOpenedInOtherGroup: editor => {
return this.groups.some(group => group !== groupView && group.contains(editor));
}
});
const groupView = this.instantiationService.createInstance(NextEditorGroupView, sourceView, { getGroups: () => this.groups });
// Keep in map
this.groupViews.set(groupView.id, groupView);
......@@ -290,7 +286,7 @@ export class NextEditorPart extends Part implements INextEditorGroupsService {
shutdown(): void {
// TODO@grid persist some UI state in the memento
// TODO@grid persist some UI state in the memento (note: a group can turn empty if none of the inputs can be serialized!)
// Forward to all groups
this.groupViews.forEach(group => group.shutdown());
......
......@@ -601,9 +601,23 @@ export class EditorGroup extends Disposable implements IEditorGroup {
return -1;
}
public contains(editorOrResource: EditorInput | URI): boolean {
public contains(editorOrResource: EditorInput | URI): boolean;
public contains(editor: EditorInput, supportSideBySide?: boolean): boolean;
public contains(editorOrResource: EditorInput | URI, supportSideBySide?: boolean): boolean {
if (editorOrResource instanceof EditorInput) {
return this.indexOf(editorOrResource) >= 0;
const index = this.indexOf(editorOrResource);
if (index >= 0) {
return true;
}
if (supportSideBySide && editorOrResource instanceof SideBySideEditorInput) {
const index = this.indexOf(editorOrResource.master);
if (index >= 0) {
return true;
}
}
return false;
}
const counter = this.mapResourceToEditorCount.get(editorOrResource);
......
......@@ -2016,4 +2016,21 @@ suite('Editor Stacks Model', () => {
assert.equal(clone.isPinned(input3), false);
assert.equal(clone.isActive(input3), true);
});
test('Stack - contains() with diff editor support', function () {
const model = create();
const group1 = model.openGroup('group1');
const input1 = input();
const input2 = input();
const diffInput = new DiffEditorInput('name', 'description', input1, input2);
group1.openEditor(input2, { pinned: true, active: true });
assert.equal(group1.contains(input2), true);
assert.equal(group1.contains(diffInput), false);
assert.equal(group1.contains(diffInput, true), true);
});
});
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册