Path: blob/main/src/vs/editor/contrib/placeholderText/browser/placeholderTextContribution.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { h } from '../../../../base/browser/dom.js';6import { structuralEquals } from '../../../../base/common/equals.js';7import { Disposable } from '../../../../base/common/lifecycle.js';8import { autorun, constObservable, DebugOwner, derivedObservableWithCache, derivedOpts, derived, IObservable, IReader } from '../../../../base/common/observable.js';9import { ICodeEditor } from '../../../browser/editorBrowser.js';10import { observableCodeEditor } from '../../../browser/observableCodeEditor.js';11import { EditorOption } from '../../../common/config/editorOptions.js';12import { IEditorContribution } from '../../../common/editorCommon.js';1314/**15* Use the editor option to set the placeholder text.16*/17export class PlaceholderTextContribution extends Disposable implements IEditorContribution {18public static get(editor: ICodeEditor): PlaceholderTextContribution {19return editor.getContribution<PlaceholderTextContribution>(PlaceholderTextContribution.ID)!;20}2122public static readonly ID = 'editor.contrib.placeholderText';23private readonly _editorObs;2425private readonly _placeholderText;2627private readonly _state;2829private readonly _shouldViewBeAlive;3031private readonly _view;3233constructor(34private readonly _editor: ICodeEditor,35) {36super();37this._editorObs = observableCodeEditor(this._editor);38this._placeholderText = this._editorObs.getOption(EditorOption.placeholder);39this._state = derivedOpts<{ placeholder: string } | undefined>({ owner: this, equalsFn: structuralEquals }, reader => {40const p = this._placeholderText.read(reader);41if (!p) { return undefined; }42if (!this._editorObs.valueIsEmpty.read(reader)) { return undefined; }43return { placeholder: p };44});45this._shouldViewBeAlive = isOrWasTrue(this, reader => this._state.read(reader)?.placeholder !== undefined);46this._view = derived((reader) => {47if (!this._shouldViewBeAlive.read(reader)) { return; }4849const element = h('div.editorPlaceholder');5051reader.store.add(autorun(reader => {52const data = this._state.read(reader);53const shouldBeVisibile = data?.placeholder !== undefined;54element.root.style.display = shouldBeVisibile ? 'block' : 'none';55element.root.innerText = data?.placeholder ?? '';56}));57reader.store.add(autorun(reader => {58const info = this._editorObs.layoutInfo.read(reader);59element.root.style.left = `${info.contentLeft}px`;60element.root.style.width = (info.contentWidth - info.verticalScrollbarWidth) + 'px';61element.root.style.top = `${this._editor.getTopForLineNumber(0)}px`;62}));63reader.store.add(autorun(reader => {64element.root.style.fontFamily = this._editorObs.getOption(EditorOption.fontFamily).read(reader);65element.root.style.fontSize = this._editorObs.getOption(EditorOption.fontSize).read(reader) + 'px';66element.root.style.lineHeight = this._editorObs.getOption(EditorOption.lineHeight).read(reader) + 'px';67}));68reader.store.add(this._editorObs.createOverlayWidget({69allowEditorOverflow: false,70minContentWidthInPx: constObservable(0),71position: constObservable(null),72domNode: element.root,73}));74});75this._view.recomputeInitiallyAndOnChange(this._store);76}77}7879function isOrWasTrue(owner: DebugOwner, fn: (reader: IReader) => boolean): IObservable<boolean> {80return derivedObservableWithCache<boolean>(owner, (reader, lastValue) => {81if (lastValue === true) { return true; }82return fn(reader);83});84}858687