Skip to content

Commit

Permalink
Introduces codeEditorObs (#210938)
Browse files Browse the repository at this point in the history
* Introduces obsCodeEditor
  • Loading branch information
hediet authored Apr 22, 2024
1 parent 0b85b6e commit 9f729d2
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 4 deletions.
71 changes: 71 additions & 0 deletions src/vs/editor/browser/observableUtilities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { autorunOpts, derivedOpts, IObservable, observableFromEvent } from 'vs/base/common/observable';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { Position } from 'vs/editor/common/core/position';
import { IModelDeltaDecoration } from 'vs/editor/common/model';

/**
* Returns a facade for the code editor that provides observables for various states/events.
*/
export function obsCodeEditor(editor: ICodeEditor): ObservableCodeEditor {
return ObservableCodeEditor.get(editor);
}

class ObservableCodeEditor {
private static _map = new Map<ICodeEditor, ObservableCodeEditor>();

/**
* Make sure that editor is not disposed yet!
*/
public static get(editor: ICodeEditor): ObservableCodeEditor {
let result = ObservableCodeEditor._map.get(editor);
if (!result) {
result = new ObservableCodeEditor(editor);
ObservableCodeEditor._map.set(editor, result);
const d = editor.onDidDispose(() => {
ObservableCodeEditor._map.delete(editor);
d.dispose();
});
}
return result;
}

private constructor(public readonly editor: ICodeEditor) {
}

public readonly model = observableFromEvent(this.editor.onDidChangeModel, () => this.editor.getModel());
public readonly value = observableFromEvent(this.editor.onDidChangeModelContent, () => this.editor.getValue());
public readonly valueIsEmpty = observableFromEvent(this.editor.onDidChangeModelContent, () => this.editor.getModel()?.getValueLength() === 0);
public readonly selections = observableFromEvent(this.editor.onDidChangeCursorSelection, () => this.editor.getSelections());
public readonly cursorPosition = derivedOpts({ owner: this, equalsFn: Position.equals }, reader => this.selections.read(reader)?.[0]?.getPosition() ?? null);
public readonly isFocused = observableFromEvent(e => {
const d1 = this.editor.onDidFocusEditorWidget(e);
const d2 = this.editor.onDidBlurEditorWidget(e);
return {
dispose() {
d1.dispose();
d2.dispose();
}
};
}, () => this.editor.hasWidgetFocus());

public setDecorations(decorations: IObservable<IModelDeltaDecoration[]>): IDisposable {
const d = new DisposableStore();
const decorationsCollection = this.editor.createDecorationsCollection();
d.add(autorunOpts({ owner: this, debugName: () => `Apply decorations from ${decorations.debugName}` }, reader => {
const d = decorations.read(reader);
decorationsCollection.set(d);
}));
d.add({
dispose: () => {
decorationsCollection.clear();
}
});
return d;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { Emitter, Event } from 'vs/base/common/event';
import { Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IReader, autorunHandleChanges, derived, derivedOpts, observableFromEvent } from 'vs/base/common/observable';
import { IEditorConstructionOptions } from 'vs/editor/browser/config/editorConfiguration';
import { IDiffEditorConstructionOptions } from 'vs/editor/browser/editorBrowser';
import { obsCodeEditor } from 'vs/editor/browser/observableUtilities';
import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditor/codeEditorWidget';
import { IDiffCodeEditorWidgetOptions } from 'vs/editor/browser/widget/diffEditor/diffEditorWidget';
import { OverviewRulerFeature } from 'vs/editor/browser/widget/diffEditor/features/overviewRulerFeature';
Expand All @@ -29,15 +30,15 @@ export class DiffEditorEditors extends Disposable {
public readonly modifiedScrollTop = observableFromEvent(this.modified.onDidScrollChange, () => /** @description modified.getScrollTop */ this.modified.getScrollTop());
public readonly modifiedScrollHeight = observableFromEvent(this.modified.onDidScrollChange, () => /** @description modified.getScrollHeight */ this.modified.getScrollHeight());

public readonly modifiedModel = observableFromEvent(this.modified.onDidChangeModel, () => /** @description modified.model */ this.modified.getModel());
public readonly modifiedModel = obsCodeEditor(this.modified).model;

public readonly modifiedSelections = observableFromEvent(this.modified.onDidChangeCursorSelection, () => this.modified.getSelections() ?? []);
public readonly modifiedCursor = derivedOpts({ owner: this, equalsFn: Position.equals }, reader => this.modifiedSelections.read(reader)[0]?.getPosition() ?? new Position(1, 1));

public readonly originalCursor = observableFromEvent(this.original.onDidChangeCursorPosition, () => this.original.getPosition() ?? new Position(1, 1));

public readonly isOriginalFocused = observableFromEvent(Event.any(this.original.onDidFocusEditorWidget, this.original.onDidBlurEditorWidget), () => this.original.hasWidgetFocus());
public readonly isModifiedFocused = observableFromEvent(Event.any(this.modified.onDidFocusEditorWidget, this.modified.onDidBlurEditorWidget), () => this.modified.hasWidgetFocus());
public readonly isOriginalFocused = obsCodeEditor(this.original).isFocused;
public readonly isModifiedFocused = obsCodeEditor(this.modified).isFocused;

public readonly isFocused = derived(this, reader => this.isOriginalFocused.read(reader) || this.isModifiedFocused.read(reader));

Expand Down

0 comments on commit 9f729d2

Please sign in to comment.