提交 b52f1c7d 编写于 作者: M Matt Bierner

Trying to hook up background to implement custom editor rename

上级 872c3afd
......@@ -206,43 +206,6 @@ export class MutableDisposable<T extends IDisposable> implements IDisposable {
}
}
/**
* Wrapper class that stores a disposable that is not currently "owned" by anyone.
*
* Example use cases:
*
* - Express that a function/method will take ownership of a disposable parameter.
* - Express that a function returns a disposable that the caller must explicitly take ownership of.
*/
export class UnownedDisposable<T extends IDisposable> extends Disposable {
private _hasBeenAcquired = false;
private _value?: T;
public constructor(value: T) {
super();
this._value = value;
}
public acquire(): T {
if (this._hasBeenAcquired) {
throw new Error('This disposable has already been acquired');
}
this._hasBeenAcquired = true;
const value = this._value!;
this._value = undefined;
return value;
}
public dispose() {
super.dispose();
if (!this._hasBeenAcquired) {
this._hasBeenAcquired = true;
this._value!.dispose();
this._value = undefined;
}
}
}
export interface IReference<T> extends IDisposable {
readonly object: T;
}
......
......@@ -278,7 +278,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
model.onWillSave(e => { e.waitUntil(this._proxy.$onSave(handle)); });
model.onWillSaveAs(e => { e.waitUntil(this._proxy.$onSaveAs(handle, e.resource.toJSON(), e.targetResource.toJSON())); });
webviewInput.onDispose(() => {
webviewInput.onDisposeWebview(() => {
this._customEditorService.models.disposeModel(model);
});
......@@ -326,7 +326,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
private hookupWebviewEventDelegate(handle: extHostProtocol.WebviewPanelHandle, input: WebviewInput) {
input.webview.onDidClickLink((uri: URI) => this.onDidClickLink(handle, uri));
input.webview.onMessage((message: any) => this._proxy.$onMessage(handle, message));
input.onDispose(() => {
input.onDisposeWebview(() => {
this._proxy.$onDidDisposeWebviewPanel(handle).finally(() => {
this._webviewInputs.delete(handle);
});
......
......@@ -398,6 +398,11 @@ export interface IEditorInput extends IDisposable {
*/
saveAs(groupId: GroupIdentifier, options?: ISaveOptions): Promise<boolean>;
/**
* Handles when the input is replaced, such as by renaming its backing resource.
*/
handleMove?(groupId: GroupIdentifier, uri: URI, options?: ITextEditorOptions): IEditorInput | undefined;
/**
* Reverts this input.
*/
......
......@@ -5,12 +5,12 @@
import { memoize } from 'vs/base/common/decorators';
import { Lazy } from 'vs/base/common/lazy';
import { UnownedDisposable } from 'vs/base/common/lifecycle';
import { basename } from 'vs/base/common/path';
import { isEqual } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { IEditorModel, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILabelService } from 'vs/platform/label/common/label';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { GroupIdentifier, IEditorInput, IRevertOptions, ISaveOptions, Verbosity } from 'vs/workbench/common/editor';
......@@ -18,6 +18,7 @@ import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/c
import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview';
import { IWebviewWorkbenchService, LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { assertIsDefined } from 'vs/base/common/types';
export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput {
......@@ -30,9 +31,10 @@ export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput {
resource: URI,
viewType: string,
id: string,
webview: Lazy<UnownedDisposable<WebviewEditorOverlay>>,
webview: Lazy<WebviewEditorOverlay>,
@ILifecycleService lifecycleService: ILifecycleService,
@IWebviewWorkbenchService webviewWorkbenchService: IWebviewWorkbenchService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@ILabelService private readonly labelService: ILabelService,
@ICustomEditorService private readonly customEditorService: ICustomEditorService,
@IEditorService private readonly editorService: IEditorService,
......@@ -150,4 +152,13 @@ export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput {
return this.fileDialogService.pickFileToSave({});//this.getSaveDialogOptions(defaultUri, availableFileSystems));
}
public handleMove(groupId: GroupIdentifier, uri: URI, options?: ITextEditorOptions): IEditorInput | undefined {
const webview = assertIsDefined(this.takeOwnershipOfWebview());
return this.instantiationService.createInstance(CustomFileEditorInput,
uri,
this.viewType,
this.id,
new Lazy(() => webview));
}
}
......@@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { UnownedDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
......@@ -48,7 +47,7 @@ export class CustomEditorInputFactory extends WebviewEditorInputFactory {
location: data.extensionLocation,
id: data.extensionId
} : undefined, data.group);
return new UnownedDisposable(webviewInput.webview);
return webviewInput.webview;
});
const customInput = this._instantiationService.createInstance(CustomFileEditorInput, URI.from((data as any).editorResource), data.viewType, id, webview);
......
......@@ -6,7 +6,7 @@
import { coalesce, distinct, find, mergeSort } from 'vs/base/common/arrays';
import * as glob from 'vs/base/common/glob';
import { Lazy } from 'vs/base/common/lazy';
import { Disposable, UnownedDisposable } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { basename, isEqual } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
......@@ -201,7 +201,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
): CustomFileEditorInput {
const id = generateUuid();
const webview = new Lazy(() => {
return new UnownedDisposable(this.webviewService.createWebviewEditorOverlay(id, { customClasses: options?.customClasses }, {}));
return this.webviewService.createWebviewEditorOverlay(id, { customClasses: options?.customClasses }, {});
});
const input = this.instantiationService.createInstance(CustomFileEditorInput, resource, viewType, id, webview);
if (group) {
......
......@@ -27,7 +27,7 @@ import { IEditorGroupsService, IEditorGroup } from 'vs/workbench/services/editor
import { ResourceQueue, timeout } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
import { withNullAsUndefined } from 'vs/base/common/types';
import { EditorActivation } from 'vs/platform/editor/common/editor';
import { EditorActivation, ITextEditorOptions } from 'vs/platform/editor/common/editor';
export class FileEditorTracker extends Disposable implements IWorkbenchContribution {
......@@ -215,8 +215,8 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut
private handleMovedFileInOpenedEditors(oldResource: URI, newResource: URI): void {
this.editorGroupService.groups.forEach(group => {
group.editors.forEach(editor => {
if (editor instanceof FileEditorInput) {
const resource = editor.getResource();
const resource = editor.getResource();
if (resource && (editor instanceof FileEditorInput || editor.handleMove)) {
// Update Editor if file (or any parent of the input) got renamed or moved
if (resources.isEqualOrParent(resource, oldResource)) {
......@@ -228,15 +228,27 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut
reopenFileResource = resources.joinPath(newResource, resource.path.substr(index + oldResource.path.length + 1)); // parent folder got moved
}
const options: ITextEditorOptions = {
preserveFocus: true,
pinned: group.isPinned(editor),
index: group.getIndexOfEditor(editor),
inactive: !group.isActive(editor),
};
if (editor.handleMove) {
const replacement = editor.handleMove(group.id, reopenFileResource, options);
if (replacement) {
this.editorService.replaceEditors([{ editor, replacement }], group);
return;
}
}
this.editorService.replaceEditors([{
editor: { resource },
replacement: {
resource: reopenFileResource,
options: {
preserveFocus: true,
pinned: group.isPinned(editor),
index: group.getIndexOfEditor(editor),
inactive: !group.isActive(editor),
...options,
viewState: this.getViewStateFor(oldResource, group)
}
},
......
......@@ -99,7 +99,7 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewEd
if (this._options.tryRestoreScrollPosition) {
webview.initialScrollProgress = this._initialScrollProgress;
}
this._webview.value.mountTo(this.container);
webview.mountTo(this.container);
// Forward events from inner webview to outer listeners
this._webviewEvents.clear();
......
......@@ -6,12 +6,12 @@
import * as dom from 'vs/base/browser/dom';
import { memoize } from 'vs/base/common/decorators';
import { Lazy } from 'vs/base/common/lazy';
import { UnownedDisposable as Unowned } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { EditorInput, EditorModel, GroupIdentifier, IEditorInput, Verbosity } from 'vs/workbench/common/editor';
import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview';
import { Emitter } from 'vs/base/common/event';
const WebviewPanelResourceScheme = 'webview-panel';
......@@ -70,20 +70,31 @@ export class WebviewInput extends EditorInput {
private _name: string;
private _iconPath?: { light: URI, dark: URI };
private _group?: GroupIdentifier;
private readonly _webview: Lazy<WebviewEditorOverlay>;
private _didSomeoneTakeMyWebview = false;
private readonly _onDisposeWebview = this._register(new Emitter<void>());
readonly onDisposeWebview = this._onDisposeWebview.event;
constructor(
public readonly id: string,
public readonly viewType: string,
name: string,
webview: Lazy<Unowned<WebviewEditorOverlay>>,
webview: Lazy<WebviewEditorOverlay>,
@ILifecycleService private readonly lifecycleService: ILifecycleService,
) {
super();
this._name = name;
this._webview = webview;
}
this._webview = webview.map(value => this._register(value.acquire())); // The input owns this webview
dispose() {
super.dispose();
if (!this._didSomeoneTakeMyWebview) {
this._webview?.rawValue?.dispose();
this._onDisposeWebview.fire();
}
}
public getTypeId(): string {
......@@ -119,7 +130,7 @@ export class WebviewInput extends EditorInput {
}
public get extension() {
return this._webview.getValue().extension;
return this.webview.extension;
}
public get iconPath() {
......@@ -150,4 +161,12 @@ export class WebviewInput extends EditorInput {
public supportsSplitEditor() {
return false;
}
protected takeOwnershipOfWebview(): WebviewEditorOverlay | undefined {
if (this._didSomeoneTakeMyWebview) {
return undefined;
}
this._didSomeoneTakeMyWebview = true;
return this.webview;
}
}
......@@ -6,7 +6,7 @@
import { equals } from 'vs/base/common/arrays';
import { memoize } from 'vs/base/common/decorators';
import { Lazy } from 'vs/base/common/lazy';
import { IDisposable, toDisposable, UnownedDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { values } from 'vs/base/common/map';
import { isEqual } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
......@@ -108,7 +108,7 @@ export class LazilyResolvedWebviewEditorInput extends WebviewInput {
id: string,
viewType: string,
name: string,
webview: Lazy<UnownedDisposable<WebviewEditorOverlay>>,
webview: Lazy<WebviewEditorOverlay>,
@IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService,
@ILifecycleService lifeCycleService: ILifecycleService,
) {
......@@ -161,7 +161,7 @@ export class WebviewEditorService implements IWebviewWorkbenchService {
options: WebviewInputOptions,
extension: WebviewExtensionDescription | undefined,
): WebviewInput {
const webview = new Lazy(() => new UnownedDisposable(this.createWebiew(id, extension, options)));
const webview = new Lazy(() => this.createWebiew(id, extension, options));
const webviewInput = this._instantiationService.createInstance(WebviewInput, id, viewType, title, webview);
this._editorService.openEditor(webviewInput, {
pinned: true,
......@@ -206,7 +206,7 @@ export class WebviewEditorService implements IWebviewWorkbenchService {
const webview = new Lazy(() => {
const webview = this.createWebiew(id, extension, options);
webview.state = state;
return new UnownedDisposable(webview);
return webview;
});
const webviewInput = this._instantiationService.createInstance(LazilyResolvedWebviewEditorInput, id, viewType, title, webview);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册