more fixes for #9794

This commit is contained in:
Benjamin Pasero 2016-09-12 12:59:42 +02:00
parent 77d8f8b5f4
commit 176f350454
8 changed files with 101 additions and 17 deletions

View file

@ -242,10 +242,6 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
const active = (group.count === 0) || !options || !options.inactive;
group.openEditor(input, { active, pinned, index: options && options.index });
// indicate to the UI that an editor is about to open. we need to update the title because it could be that
// the input is already opened but the title has changed and the UI should reflect that
this.sideBySideControl.updateTitle({ group, editor: input });
// Return early if the editor is to be open inactive and there are other editors in this group to show
if (!active) {
return TPromise.as<BaseEditor>(null);

View file

@ -122,11 +122,13 @@ export interface IEditorInputFactory {
export abstract class EditorInput implements IEditorInput {
private _onDispose: Emitter<void>;
protected _onDidChangeDirty: Emitter<void>;
protected _onDidChangeLabel: Emitter<void>;
private disposed: boolean;
constructor() {
this._onDidChangeDirty = new Emitter<void>();
this._onDidChangeLabel = new Emitter<void>();
this._onDispose = new Emitter<void>();
this.disposed = false;
@ -139,6 +141,13 @@ export abstract class EditorInput implements IEditorInput {
return this._onDidChangeDirty.event;
}
/**
* Fired when the label this input changes.
*/
public get onDidChangeLabel(): Event<void> {
return this._onDidChangeLabel.event;
}
/**
* Fired when the model gets disposed.
*/
@ -247,6 +256,7 @@ export abstract class EditorInput implements IEditorInput {
this._onDispose.fire();
this._onDidChangeDirty.dispose();
this._onDidChangeLabel.dispose();
this._onDispose.dispose();
}
@ -749,6 +759,7 @@ export function getResource(input: IEditorInput): URI {
return candidate;
}
}
return getUntitledOrFileResource(input, true);
}
@ -827,6 +838,7 @@ export interface IEditorGroup {
previewEditor: IEditorInput;
getEditor(index: number): IEditorInput;
getEditor(resource: URI): IEditorInput;
indexOf(editor: IEditorInput): number;
contains(editor: IEditorInput): boolean;

View file

@ -60,8 +60,9 @@ export class DiffEditorInput extends BaseDiffEditorInput {
}
}));
// When the modified model gets dirty, re-emit this to the outside
// Reemit some events from the modified side to the outside
this._toUnbind.push(this.modifiedInput.onDidChangeDirty(() => this._onDidChangeDirty.fire()));
this._toUnbind.push(this.modifiedInput.onDidChangeLabel(() => this._onDidChangeLabel.fire()));
}
public get toUnbind() {

View file

@ -6,7 +6,7 @@
'use strict';
import Event, {Emitter, once} from 'vs/base/common/event';
import {IEditorRegistry, Extensions, EditorInput, getUntitledOrFileResource, IEditorStacksModel, IEditorGroup, IEditorIdentifier, IGroupEvent, GroupIdentifier, IStacksModelChangeEvent, IWorkbenchEditorConfiguration, EditorOpenPositioning} from 'vs/workbench/common/editor';
import {IEditorRegistry, Extensions, EditorInput, getResource, IEditorStacksModel, IEditorGroup, IEditorIdentifier, IGroupEvent, GroupIdentifier, IStacksModelChangeEvent, IWorkbenchEditorConfiguration, EditorOpenPositioning} from 'vs/workbench/common/editor';
import URI from 'vs/base/common/uri';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
@ -17,9 +17,6 @@ import {Registry} from 'vs/platform/platform';
import {Position, Direction} from 'vs/platform/editor/common/editor';
import {DiffEditorInput} from 'vs/workbench/common/editor/diffEditorInput';
// TODO@Ben currently only files and untitled editors are tracked with their resources in the stacks model
// Once the resource is a base concept of all editor inputs, every resource should be tracked for any editor
export interface GroupEvent extends IGroupEvent {
editor: EditorInput;
}
@ -69,6 +66,7 @@ export class EditorGroup implements IEditorGroup {
private _onEditorClosed: Emitter<GroupEvent>;
private _onEditorDisposed: Emitter<EditorInput>;
private _onEditorDirty: Emitter<EditorInput>;
private _onEditorLabelChange: Emitter<EditorInput>;
private _onEditorMoved: Emitter<EditorInput>;
private _onEditorPinned: Emitter<EditorInput>;
private _onEditorUnpinned: Emitter<EditorInput>;
@ -93,13 +91,14 @@ export class EditorGroup implements IEditorGroup {
this._onEditorClosed = new Emitter<GroupEvent>();
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._onEditorMoved, this._onEditorPinned, this._onEditorUnpinned, this._onEditorStateChanged, this._onEditorsStructureChanged);
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);
if (typeof arg1 === 'object') {
this.deserialize(arg1);
@ -154,6 +153,10 @@ export class EditorGroup implements IEditorGroup {
return this._onEditorDirty.event;
}
public get onEditorLabelChange(): Event<EditorInput> {
return this._onEditorLabelChange.event;
}
public get onEditorMoved(): Event<EditorInput> {
return this._onEditorMoved.event;
}
@ -178,8 +181,27 @@ export class EditorGroup implements IEditorGroup {
return mru ? this.mru.slice(0) : this.editors.slice(0);
}
public getEditor(index: number): EditorInput {
return this.editors[index];
public getEditor(index: number): EditorInput;
public getEditor(resource: URI): EditorInput;
public getEditor(arg1: any): EditorInput {
if (typeof arg1 === 'number') {
return this.editors[arg1];
}
const resource: URI = arg1;
if (!this.contains(resource)) {
return null; // fast check for resource opened or not
}
for (let i = 0; i < this.editors.length; i++) {
const editor = this.editors[i];
const editorResource = getResource(editor);
if (editorResource && editorResource.toString() === resource.toString()) {
return editor;
}
}
return null;
}
public get activeEditor(): EditorInput {
@ -308,6 +330,11 @@ export class EditorGroup implements IEditorGroup {
this.fireEvent(this._onEditorDirty, editor, false);
}));
// Re-Emit label changes
unbind.push(editor.onDidChangeLabel(() => {
this.fireEvent(this._onEditorLabelChange, editor, false);
}));
// Clean up dispose listeners once the editor gets closed
unbind.push(this.onEditorClosed(event => {
if (event.editor.matches(editor)) {
@ -514,7 +541,7 @@ export class EditorGroup implements IEditorGroup {
}
private updateResourceMap(editor: EditorInput, remove: boolean): void {
const resource = getUntitledOrFileResource(editor, true /* include diff editors */);
const resource = getResource(editor);
if (resource) {
// It is possible to have the same resource opened twice (once as normal input and once as diff input)
@ -663,6 +690,7 @@ export class EditorStacksModel implements IEditorStacksModel {
private _onGroupRenamed: Emitter<EditorGroup>;
private _onEditorDisposed: Emitter<EditorIdentifier>;
private _onEditorDirty: Emitter<EditorIdentifier>;
private _onEditorLabelChange: Emitter<EditorIdentifier>;
private _onEditorClosed: Emitter<GroupEvent>;
private _onModelChanged: Emitter<IStacksModelChangeEvent>;
@ -686,9 +714,10 @@ export class EditorStacksModel implements IEditorStacksModel {
this._onModelChanged = new Emitter<IStacksModelChangeEvent>();
this._onEditorDisposed = new Emitter<EditorIdentifier>();
this._onEditorDirty = new Emitter<EditorIdentifier>();
this._onEditorLabelChange = new Emitter<EditorIdentifier>();
this._onEditorClosed = new Emitter<GroupEvent>();
this.toDispose.push(this._onGroupOpened, this._onGroupClosed, this._onGroupActivated, this._onGroupDeactivated, this._onGroupMoved, this._onGroupRenamed, this._onModelChanged, this._onEditorDisposed, this._onEditorDirty, this._onEditorClosed);
this.toDispose.push(this._onGroupOpened, this._onGroupClosed, this._onGroupActivated, this._onGroupDeactivated, this._onGroupMoved, this._onGroupRenamed, this._onModelChanged, this._onEditorDisposed, this._onEditorDirty, this._onEditorLabelChange, this._onEditorClosed);
this.registerListeners();
}
@ -733,6 +762,10 @@ export class EditorStacksModel implements IEditorStacksModel {
return this._onEditorDirty.event;
}
public get onEditorLabelChange(): Event<EditorIdentifier> {
return this._onEditorLabelChange.event;
}
public get onEditorClosed(): Event<GroupEvent> {
return this._onEditorClosed.event;
}
@ -1064,6 +1097,7 @@ export class EditorStacksModel implements IEditorStacksModel {
}));
unbind.push(group.onEditorDisposed(editor => this._onEditorDisposed.fire({ editor, group })));
unbind.push(group.onEditorDirty(editor => this._onEditorDirty.fire({ editor, group })));
unbind.push(group.onEditorLabelChange(editor => this._onEditorLabelChange.fire({ editor, group })));
unbind.push(this.onGroupClosed(g => {
if (g === group) {
dispose(unbind);

View file

@ -143,10 +143,24 @@ export class ResourceEditorInput extends EditorInput {
return this.name;
}
public setName(name: string): void {
if (this.name !== name) {
this.name = name;
this._onDidChangeLabel.fire();
}
}
public getDescription(): string {
return this.description;
}
public setDescription(description: string): void {
if (this.description !== description) {
this.description = description;
this._onDidChangeLabel.fire();
}
}
public resolve(refresh?: boolean): TPromise<EditorModel> {
// Use Cached Model

View file

@ -16,6 +16,7 @@ import {Registry} from 'vs/platform/platform';
import {EditorDescriptor} from 'vs/workbench/browser/parts/editor/baseEditor';
import {IEditorRegistry, Extensions as EditorExtensions} from 'vs/workbench/common/editor';
import {SyncDescriptor} from 'vs/platform/instantiation/common/descriptors';
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
// --- Register Editor
(<IEditorRegistry>Registry.as(EditorExtensions.Editors)).registerEditor(new EditorDescriptor(HtmlPreviewPart.ID,
@ -28,9 +29,27 @@ import {SyncDescriptor} from 'vs/platform/instantiation/common/descriptors';
CommandsRegistry.registerCommand('_workbench.previewHtml', function (accessor: ServicesAccessor, resource: URI | string, position?: EditorPosition, label?: string) {
let uri = resource instanceof URI ? resource : URI.parse(resource);
const uri = resource instanceof URI ? resource : URI.parse(resource);
label = label || uri.fsPath;
let input = accessor.get(IInstantiationService).createInstance(HtmlInput, label, '', uri);
let input: HtmlInput;
// Find already opened HTML input if any
const stacks = accessor.get(IEditorGroupService).getStacksModel();
const targetGroup = stacks.groupAt(position) || stacks.activeGroup;
if (targetGroup) {
const existingInput = targetGroup.getEditor(uri);
if (existingInput instanceof HtmlInput) {
input = existingInput;
}
}
// Otherwise, create new input and open it
if (!input) {
input = accessor.get(IInstantiationService).createInstance(HtmlInput, label, '', uri);
} else {
input.setName(label); // make sure to use passed in label
}
return accessor.get(IWorkbenchEditorService)
.openEditor(input, { pinned: true }, position)

View file

@ -111,11 +111,15 @@ export abstract class BaseHistoryService {
// Propagate to history
this.onEditorEvent(activeEditor);
// Apply listener for dirty changes
// Apply listener for dirty and label changes
if (activeInput instanceof EditorInput) {
this.activeEditorListeners.push(activeInput.onDidChangeDirty(() => {
this.updateWindowTitle(activeInput); // Calculate New Window Title when dirty state changes
}));
this.activeEditorListeners.push(activeInput.onDidChangeLabel(() => {
this.updateWindowTitle(activeInput); // Calculate New Window Title when label changes
}));
}
// Apply listener for selection changes if this is a text editor

View file

@ -1483,13 +1483,16 @@ suite('Editor Stacks Model', () => {
assert.ok(model.isOpen(input1Resource));
assert.ok(group1.contains(input1Resource));
assert.equal(model.count(input1Resource), 1);
assert.equal(group1.getEditor(input1Resource), input1);
group2.openEditor(input1);
group1.closeEditor(input1);
assert.ok(model.isOpen(input1Resource));
assert.ok(!group1.contains(input1Resource));
assert.ok(!group1.getEditor(input1Resource));
assert.ok(group2.contains(input1Resource));
assert.equal(group2.getEditor(input1Resource), input1);
assert.equal(model.count(input1Resource), 1);
const input1ResourceClone = URI.file('/hello/world.txt');
@ -1502,6 +1505,7 @@ suite('Editor Stacks Model', () => {
assert.ok(model.isOpen(input1Resource));
assert.ok(group1.contains(input1Resource));
assert.equal(group1.getEditor(input1Resource), input1Clone);
assert.ok(!group2.contains(input1Resource));
group1.closeEditor(input1Clone);