history - first cut notebooks support (#101779)

This commit is contained in:
Benjamin Pasero 2022-02-06 09:19:28 +01:00
parent 6039aa4fc7
commit 7858e237ae
No known key found for this signature in database
GPG key ID: E6380CC4C8219E65
6 changed files with 76 additions and 20 deletions

View file

@ -545,9 +545,12 @@ class SideBySideAwareEditorPaneSelection implements IEditorPaneSelection {
return this.selection.compare(other.selection);
}
restore(options: IEditorOptions): void {
const sideBySideOptions = options as ISideBySideEditorOptions;
this.selection.restore(sideBySideOptions);
sideBySideOptions.target = this.side;
restore(options: IEditorOptions): ISideBySideEditorOptions {
const sideBySideEditorOptions: ISideBySideEditorOptions = {
...options,
target: this.side
};
return this.selection.restore(sideBySideEditorOptions);
}
}

View file

@ -337,9 +337,13 @@ export class TextEditorPaneSelection implements IEditorPaneSelection {
return EditorPaneSelectionCompareResult.DIFFERENT;
}
restore(options: IEditorOptions): void {
const textOptions = options as ITextEditorOptions;
textOptions.selectionRevealType = TextEditorSelectionRevealType.CenterIfOutsideViewport;
textOptions.selection = this.textSelection;
restore(options: IEditorOptions): ITextEditorOptions {
const textEditorOptions: ITextEditorOptions = {
...options,
selection: this.textSelection,
selectionRevealType: TextEditorSelectionRevealType.CenterIfOutsideViewport
};
return textEditorOptions;
}
}

View file

@ -232,7 +232,7 @@ export interface IEditorPaneSelection {
* For a text editor this means to apply the selected
* line and column as text editor options.
*/
restore(options: IEditorOptions): void;
restore(options: IEditorOptions): IEditorOptions;
}
export const enum EditorPaneSelectionCompareResult {

View file

@ -9,16 +9,16 @@ import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
import 'vs/css!./media/notebook';
import { localize } from 'vs/nls';
import { extname } from 'vs/base/common/resources';
import { extname, isEqual } from 'vs/base/common/resources';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { EditorResolution } from 'vs/platform/editor/common/editor';
import { EditorResolution, IEditorOptions } from 'vs/platform/editor/common/editor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { EditorInputCapabilities, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor';
import { EditorInputCapabilities, EditorPaneSelectionChangeReason, EditorPaneSelectionCompareResult, IEditorMemento, IEditorOpenContext, IEditorPaneSelection, IEditorPaneSelectionChangeEvent, IEditorPaneWithSelection } from 'vs/workbench/common/editor';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidget';
@ -36,10 +36,11 @@ import { SELECT_KERNEL_ID } from 'vs/workbench/contrib/notebook/browser/controll
import { NotebooKernelActionViewItem } from 'vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { URI } from 'vs/base/common/uri';
const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState';
export class NotebookEditor extends EditorPane {
export class NotebookEditor extends EditorPane implements IEditorPaneWithSelection {
static readonly ID: string = NOTEBOOK_EDITOR_ID;
private readonly _editorMemento: IEditorMemento<INotebookEditorViewState>;
@ -60,6 +61,9 @@ export class NotebookEditor extends EditorPane {
private readonly _onDidChangeModel = this._register(new Emitter<void>());
readonly onDidChangeModel: Event<void> = this._onDidChangeModel.event;
private readonly _onDidChangeSelection = this._register(new Emitter<IEditorPaneSelectionChangeEvent>());
readonly onDidChangeSelection = this._onDidChangeSelection.event;
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IThemeService themeService: IThemeService,
@ -185,6 +189,7 @@ export class NotebookEditor extends EditorPane {
this._widget = this.instantiationService.invokeFunction(this._notebookWidgetService.retrieveWidget, group, input);
this._widgetDisposableStore.add(this._widget.value!.onDidChangeModel(() => this._onDidChangeModel.fire()));
this._widgetDisposableStore.add(this._widget.value!.onDidChangeActiveCell(() => this._onDidChangeSelection.fire({ reason: EditorPaneSelectionChangeReason.NONE })));
if (this._dimension) {
this._widget.value!.layout(this._dimension, this._rootElement);
@ -215,7 +220,7 @@ export class NotebookEditor extends EditorPane {
return;
}
this._widgetDisposableStore.add(model.notebook.onDidChangeContent(() => this._onDidChangeSelection.fire({ reason: EditorPaneSelectionChangeReason.EDIT })));
const viewState = options?.viewState ?? this._loadNotebookEditorViewState(input);
@ -316,6 +321,17 @@ export class NotebookEditor extends EditorPane {
return this._loadNotebookEditorViewState(input);
}
getSelection(): IEditorPaneSelection | undefined {
if (this._widget.value) {
const cellUri = this._widget.value.getActiveCell()?.uri;
if (cellUri) {
return new NotebookEditorSelection(cellUri);
}
}
return undefined;
}
private _saveEditorViewState(input: EditorInput | undefined): void {
if (this.group && this._widget.value && input instanceof NotebookEditorInput) {
@ -355,7 +371,7 @@ export class NotebookEditor extends EditorPane {
return;
}
if (this._input.resource.toString() !== this._widget.value.textModel?.uri.toString() && this._widget.value?.hasModel()) {
if (this._input.resource.toString() !== this.textModel?.uri.toString() && this._widget.value?.hasModel()) {
// input and widget mismatch
// this happens when
// 1. open document A, pin the document
@ -384,3 +400,34 @@ export class NotebookEditor extends EditorPane {
// };
// }
}
class NotebookEditorSelection implements IEditorPaneSelection {
constructor(
private readonly cellUri: URI
) { }
compare(other: IEditorPaneSelection): EditorPaneSelectionCompareResult {
if (!(other instanceof NotebookEditorSelection)) {
return EditorPaneSelectionCompareResult.DIFFERENT;
}
if (isEqual(this.cellUri, other.cellUri)) {
return EditorPaneSelectionCompareResult.IDENTICAL;
}
return EditorPaneSelectionCompareResult.DIFFERENT;
}
restore(options: IEditorOptions): INotebookEditorOptions {
const notebookOptions: INotebookEditorOptions = {
cellOptions: {
resource: this.cellUri
}
};
Object.assign(notebookOptions, options);
return notebookOptions;
}
}

View file

@ -1387,10 +1387,12 @@ export class EditorNavigationStack extends Disposable {
}
private doNavigate(location: IEditorNavigationStackEntry): Promise<IEditorPane | undefined> {
const options: IEditorOptions = Object.create(null);
let options: IEditorOptions = Object.create(null);
// Apply selection if any
location.selection?.restore(options);
if (location.selection) {
options = location.selection.restore(options);
}
if (isEditorInput(location.editor)) {
return this.editorService.openEditor(location.editor, options, location.groupId);

View file

@ -15,6 +15,7 @@ import { EditorPaneSelectionChangeReason, EditorPaneSelectionCompareResult, IEdi
import { DeferredPromise } from 'vs/base/common/async';
import { TextEditorPaneSelection } from 'vs/workbench/browser/parts/editor/textEditor';
import { Selection } from 'vs/editor/common/core/selection';
import { IEditorOptions } from 'vs/platform/editor/common/editor';
suite('TextEditorPane', () => {
@ -73,8 +74,7 @@ suite('TextEditorPane', () => {
const selection = pane.getSelection();
assert.ok(selection);
await pane.group?.closeAllEditors();
const options = {};
selection.restore(options);
const options = selection.restore({});
pane = await accessor.editorService.openEditor({ resource, options });
assert.ok(pane && isEditorPaneWithSelection(pane));
@ -88,7 +88,7 @@ suite('TextEditorPane', () => {
const sel1 = new TextEditorPaneSelection(new Selection(1, 1, 2, 2));
const sel2 = new TextEditorPaneSelection(new Selection(5, 5, 6, 6));
const sel3 = new TextEditorPaneSelection(new Selection(50, 50, 60, 60));
const sel4 = { compare: () => { throw new Error(); }, restore: () => { } };
const sel4 = { compare: () => { throw new Error(); }, restore: (options: IEditorOptions) => options };
assert.strictEqual(sel1.compare(sel1), EditorPaneSelectionCompareResult.IDENTICAL);
assert.strictEqual(sel1.compare(sel2), EditorPaneSelectionCompareResult.SIMILAR);