diff --git a/src/vs/editor/browser/config/configuration.ts b/src/vs/editor/browser/config/configuration.ts index 75964a2edf8..d5a6bcc90ca 100644 --- a/src/vs/editor/browser/config/configuration.ts +++ b/src/vs/editor/browser/config/configuration.ts @@ -15,9 +15,9 @@ import { FontMeasurements } from 'vs/editor/browser/config/fontMeasurements'; import { migrateOptions } from 'vs/editor/browser/config/migrateOptions'; import { TabFocus } from 'vs/editor/browser/config/tabFocus'; import { IEditorConstructionOptions } from 'vs/editor/browser/editorBrowser'; -import { ComputeOptionsMemory, ConfigurationChangedEvent, EditorOption, editorOptionsRegistry, EDITOR_FONT_DEFAULTS, FindComputedEditorOptionValueById, IComputedEditorOptions, IEditorOptions, IEnvironmentalOptions, ValidatedEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { ComputeOptionsMemory, ConfigurationChangedEvent, EditorOption, editorOptionsRegistry, EDITOR_FONT_DEFAULTS, FindComputedEditorOptionValueById, IComputedEditorOptions, IEditorOptions, IEnvironmentalOptions } from 'vs/editor/common/config/editorOptions'; import { EditorZoom } from 'vs/editor/common/config/editorZoom'; -import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo'; +import { BareFontInfo, FontInfo, IValidatedEditorOptions } from 'vs/editor/common/config/fontInfo'; import { IConfiguration, IDimension } from 'vs/editor/common/editorCommon'; import { AccessibilitySupport, IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; @@ -48,95 +48,75 @@ export class Configuration extends Disposable implements IConfiguration { public readonly onDidChangeFast: Event = this._onDidChangeFast.event; public readonly isSimpleWidget: boolean; - private _computeOptionsMemory: ComputeOptionsMemory; - public options!: ComputedEditorOptions; + private readonly _containerObserver: ElementSizeObserver; - private _isDominatedByLongLines: boolean; - private _viewLineCount: number; - private _lineNumbersDigitCount: number; - - private _rawOptions: IEditorOptions; - private _readOptions: RawEditorOptions; - protected _validatedOptions: ValidatedEditorOptions; + private _isDominatedByLongLines: boolean = false; + private _viewLineCount: number = 1; + private _lineNumbersDigitCount: number = 1; private _reservedHeight: number = 0; - private readonly _elementSizeObserver: ElementSizeObserver; + private readonly _computeOptionsMemory: ComputeOptionsMemory = new ComputeOptionsMemory(); + /** + * Raw options as they were passed in and merged with all calls to `updateOptions`. + */ + private readonly _rawOptions: IEditorOptions; + /** + * Validated version of `_rawOptions`. + */ + private _validatedOptions: ValidatedEditorOptions; + /** + * Complete options which are a combination of passed in options and env values. + */ + public options: ComputedEditorOptions; constructor( isSimpleWidget: boolean, options: Readonly, - referenceDomElement: HTMLElement | null, - @IAccessibilityService private readonly accessibilityService: IAccessibilityService + container: HTMLElement | null, + @IAccessibilityService private readonly _accessibilityService: IAccessibilityService ) { super(); this.isSimpleWidget = isSimpleWidget; - - this._isDominatedByLongLines = false; - this._computeOptionsMemory = new ComputeOptionsMemory(); - this._viewLineCount = 1; - this._lineNumbersDigitCount = 1; + this._containerObserver = this._register(new ElementSizeObserver(container, options.dimension)); this._rawOptions = deepCloneAndMigrateOptions(options); - this._readOptions = EditorConfiguration2.readOptions(this._rawOptions); - this._validatedOptions = EditorConfiguration2.validateOptions(this._readOptions); + this._validatedOptions = EditorOptionsUtil.validateOptions(this._rawOptions); + this.options = this._computeOptions(); - this._register(EditorZoom.onDidChangeZoomLevel(_ => this._recomputeOptions())); - this._register(TabFocus.onDidChangeTabFocus(_ => this._recomputeOptions())); - - this._elementSizeObserver = this._register(new ElementSizeObserver(referenceDomElement, options.dimension, () => this._recomputeOptions())); + if (this.options.get(EditorOption.automaticLayout)) { + this._containerObserver.startObserving(); + } + this._register(EditorZoom.onDidChangeZoomLevel(() => this._recomputeOptions())); + this._register(TabFocus.onDidChangeTabFocus(() => this._recomputeOptions())); + this._register(this._containerObserver.onDidChange(() => this._recomputeOptions())); this._register(FontMeasurements.onDidChange(() => this._recomputeOptions())); + this._register(browser.onDidChangeZoomLevel(() => this._recomputeOptions())); + this._register(this._accessibilityService.onDidChangeScreenReaderOptimized(() => this._recomputeOptions())); + } - if (this._validatedOptions.get(EditorOption.automaticLayout)) { - this._elementSizeObserver.startObserving(); + private _recomputeOptions(): void { + const newOptions = this._computeOptions(); + const changeEvent = EditorOptionsUtil.checkEquals(this.options, newOptions); + if (changeEvent === null) { + // nothing changed! + return; } - this._register(browser.onDidChangeZoomLevel(_ => this._recomputeOptions())); - this._register(this.accessibilityService.onDidChangeScreenReaderOptimized(() => this._recomputeOptions())); - - this._recomputeOptions(); + this.options = newOptions; + this._onDidChangeFast.fire(changeEvent); + this._onDidChange.fire(changeEvent); } - public observeReferenceElement(dimension?: IDimension): void { - this._elementSizeObserver.observe(dimension); - } - - public updatePixelRatio(): void { - this._recomputeOptions(); - } - - protected _recomputeOptions(): void { - const oldOptions = this.options; - const newOptions = this._computeInternalOptions(); - - if (!oldOptions) { - this.options = newOptions; - } else { - const changeEvent = EditorConfiguration2.checkEquals(oldOptions, newOptions); - - if (changeEvent === null) { - // nothing changed! - return; - } - - this.options = newOptions; - this._onDidChangeFast.fire(changeEvent); - this._onDidChange.fire(changeEvent); - } - } - - public getRawOptions(): IEditorOptions { - return this._rawOptions; - } - - private _computeInternalOptions(): ComputedEditorOptions { - const partialEnv = this._getEnvConfiguration(); + private _computeOptions(): ComputedEditorOptions { + const partialEnv = this._readEnvConfiguration(); const bareFontInfo = BareFontInfo.createFromValidatedSettings(this._validatedOptions, partialEnv.zoomLevel, partialEnv.pixelRatio, this.isSimpleWidget); + const fontInfo = this._readFontInfo(bareFontInfo); const env: IEnvironmentalOptions = { memory: this._computeOptionsMemory, outerWidth: partialEnv.outerWidth, outerHeight: partialEnv.outerHeight - this._reservedHeight, - fontInfo: this.readConfiguration(bareFontInfo), + fontInfo: fontInfo, extraEditorClassName: partialEnv.extraEditorClassName, isDominatedByLongLines: this._isDominatedByLongLines, viewLineCount: this._viewLineCount, @@ -146,33 +126,63 @@ export class Configuration extends Disposable implements IConfiguration { tabFocusMode: TabFocus.getTabFocusMode(), accessibilitySupport: partialEnv.accessibilitySupport }; - return EditorConfiguration2.computeOptions(this._validatedOptions, env); + return EditorOptionsUtil.computeOptions(this._validatedOptions, env); + } + + protected _readEnvConfiguration(): IEnvConfiguration { + return { + extraEditorClassName: getExtraEditorClassName(), + outerWidth: this._containerObserver.getWidth(), + outerHeight: this._containerObserver.getHeight(), + emptySelectionClipboard: browser.isWebKit || browser.isFirefox, + pixelRatio: browser.getPixelRatio(), + zoomLevel: browser.getZoomLevel(), + accessibilitySupport: ( + this._accessibilityService.isScreenReaderOptimized() + ? AccessibilitySupport.Enabled + : this._accessibilityService.getAccessibilitySupport() + ) + }; + } + + protected _readFontInfo(bareFontInfo: BareFontInfo): FontInfo { + return FontMeasurements.readFontInfo(bareFontInfo); + } + + public getRawOptions(): IEditorOptions { + return this._rawOptions; } public updateOptions(_newOptions: Readonly): void { - if (typeof _newOptions === 'undefined') { - return; - } const newOptions = deepCloneAndMigrateOptions(_newOptions); - const didChange = EditorConfiguration2.applyUpdate(this._rawOptions, newOptions); + const didChange = EditorOptionsUtil.applyUpdate(this._rawOptions, newOptions); if (!didChange) { return; } - this._readOptions = EditorConfiguration2.readOptions(this._rawOptions); - this._validatedOptions = EditorConfiguration2.validateOptions(this._readOptions); + this._validatedOptions = EditorOptionsUtil.validateOptions(this._rawOptions); + this._recomputeOptions(); + } + public observeContainer(dimension?: IDimension): void { + this._containerObserver.observe(dimension); + } + + public observePixelRatio(): void { this._recomputeOptions(); } public setIsDominatedByLongLines(isDominatedByLongLines: boolean): void { + if (this._isDominatedByLongLines === isDominatedByLongLines) { + return; + } this._isDominatedByLongLines = isDominatedByLongLines; this._recomputeOptions(); } - public setMaxLineNumber(maxLineNumber: number): void { - const lineNumbersDigitCount = Configuration._digitCount(maxLineNumber); + public setModelLineCount(modelLineCount: number): void { + const lineNumbersDigitCount = digitCount(modelLineCount); if (this._lineNumbersDigitCount === lineNumbersDigitCount) { return; } @@ -188,57 +198,40 @@ export class Configuration extends Disposable implements IConfiguration { this._recomputeOptions(); } - private static _digitCount(n: number): number { - let r = 0; - while (n) { - n = Math.floor(n / 10); - r++; + public setReservedHeight(reservedHeight: number) { + if (this._reservedHeight === reservedHeight) { + return; } - return r ? r : 1; - } - - private static _getExtraEditorClassName(): string { - let extra = ''; - if (!browser.isSafari && !browser.isWebkitWebView) { - // Use user-select: none in all browsers except Safari and native macOS WebView - extra += 'no-user-select '; - } - if (browser.isSafari) { - // See https://github.com/microsoft/vscode/issues/108822 - extra += 'no-minimap-shadow '; - } - if (platform.isMacintosh) { - extra += 'mac '; - } - return extra; - } - - protected _getEnvConfiguration(): IEnvConfiguration { - return { - extraEditorClassName: Configuration._getExtraEditorClassName(), - outerWidth: this._elementSizeObserver.getWidth(), - outerHeight: this._elementSizeObserver.getHeight(), - emptySelectionClipboard: browser.isWebKit || browser.isFirefox, - pixelRatio: browser.getPixelRatio(), - zoomLevel: browser.getZoomLevel(), - accessibilitySupport: ( - this.accessibilityService.isScreenReaderOptimized() - ? AccessibilitySupport.Enabled - : this.accessibilityService.getAccessibilitySupport() - ) - }; - } - - protected readConfiguration(bareFontInfo: BareFontInfo): FontInfo { - return FontMeasurements.readFontInfo(bareFontInfo); - } - - public reserveHeight(height: number) { - this._reservedHeight = height; + this._reservedHeight = reservedHeight; this._recomputeOptions(); } } +function digitCount(n: number): number { + let r = 0; + while (n) { + n = Math.floor(n / 10); + r++; + } + return r ? r : 1; +} + +function getExtraEditorClassName(): string { + let extra = ''; + if (!browser.isSafari && !browser.isWebkitWebView) { + // Use user-select: none in all browsers except Safari and native macOS WebView + extra += 'no-user-select '; + } + if (browser.isSafari) { + // See https://github.com/microsoft/vscode/issues/108822 + extra += 'no-minimap-shadow '; + } + if (platform.isMacintosh) { + extra += 'mac '; + } + return extra; +} + export interface IEnvConfiguration { extraEditorClassName: string; outerWidth: number; @@ -249,6 +242,19 @@ export interface IEnvConfiguration { accessibilitySupport: AccessibilitySupport; } +class ValidatedEditorOptions implements IValidatedEditorOptions { + private readonly _values: any[] = []; + public _read(option: EditorOption): T { + return this._values[option]; + } + public get(id: T): FindComputedEditorOptionValueById { + return this._values[id]; + } + public _write(option: EditorOption, value: T): void { + this._values[option] = value; + } +} + export class ComputedEditorOptions implements IComputedEditorOptions { private readonly _values: any[] = []; public _read(id: EditorOption): T { @@ -265,31 +271,13 @@ export class ComputedEditorOptions implements IComputedEditorOptions { } } -class RawEditorOptions { - private readonly _values: any[] = []; - public _read(id: EditorOption): T | undefined { - return this._values[id]; - } - public _write(id: EditorOption, value: T | undefined): void { - this._values[id] = value; - } -} +class EditorOptionsUtil { -class EditorConfiguration2 { - public static readOptions(_options: IEditorOptions): RawEditorOptions { - const options: { [key: string]: any; } = _options; - const result = new RawEditorOptions(); - for (const editorOption of editorOptionsRegistry) { - const value = (editorOption.name === '_never_' ? undefined : options[editorOption.name]); - result._write(editorOption.id, value); - } - return result; - } - - public static validateOptions(options: RawEditorOptions): ValidatedEditorOptions { + public static validateOptions(rawOptions: IEditorOptions): ValidatedEditorOptions { const result = new ValidatedEditorOptions(); for (const editorOption of editorOptionsRegistry) { - result._write(editorOption.id, editorOption.validate(options._read(editorOption.id))); + const value = (editorOption.name === '_never_' ? undefined : (rawOptions as any)[editorOption.name]); + result._write(editorOption.id, editorOption.validate(value)); } return result; } @@ -313,7 +301,7 @@ class EditorConfiguration2 { return false; } for (let key in a) { - if (!EditorConfiguration2._deepEquals(a[key], b[key])) { + if (!EditorOptionsUtil._deepEquals(a[key], b[key])) { return false; } } @@ -324,7 +312,7 @@ class EditorConfiguration2 { const result: boolean[] = []; let somethingChanged = false; for (const editorOption of editorOptionsRegistry) { - const changed = !EditorConfiguration2._deepEquals(a._read(editorOption.id), b._read(editorOption.id)); + const changed = !EditorOptionsUtil._deepEquals(a._read(editorOption.id), b._read(editorOption.id)); result[editorOption.id] = changed; if (changed) { somethingChanged = true; diff --git a/src/vs/editor/browser/config/elementSizeObserver.ts b/src/vs/editor/browser/config/elementSizeObserver.ts index d1701143cbd..c2bade80d50 100644 --- a/src/vs/editor/browser/config/elementSizeObserver.ts +++ b/src/vs/editor/browser/config/elementSizeObserver.ts @@ -5,22 +5,24 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { IDimension } from 'vs/editor/common/editorCommon'; +import { Emitter, Event } from 'vs/base/common/event'; export class ElementSizeObserver extends Disposable { - private readonly referenceDomElement: HTMLElement | null; - private readonly changeCallback: () => void; - private width: number; - private height: number; - private resizeObserver: ResizeObserver | null; + private _onDidChange = this._register(new Emitter()); + public readonly onDidChange: Event = this._onDidChange.event; - constructor(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined, changeCallback: () => void) { + private readonly _referenceDomElement: HTMLElement | null; + private _width: number; + private _height: number; + private _resizeObserver: ResizeObserver | null; + + constructor(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined) { super(); - this.referenceDomElement = referenceDomElement; - this.changeCallback = changeCallback; - this.width = -1; - this.height = -1; - this.resizeObserver = null; + this._referenceDomElement = referenceDomElement; + this._width = -1; + this._height = -1; + this._resizeObserver = null; this.measureReferenceDomElement(false, dimension); } @@ -30,30 +32,30 @@ export class ElementSizeObserver extends Disposable { } public getWidth(): number { - return this.width; + return this._width; } public getHeight(): number { - return this.height; + return this._height; } public startObserving(): void { - if (!this.resizeObserver && this.referenceDomElement) { - this.resizeObserver = new ResizeObserver((entries) => { + if (!this._resizeObserver && this._referenceDomElement) { + this._resizeObserver = new ResizeObserver((entries) => { if (entries && entries[0] && entries[0].contentRect) { this.observe({ width: entries[0].contentRect.width, height: entries[0].contentRect.height }); } else { this.observe(); } }); - this.resizeObserver.observe(this.referenceDomElement); + this._resizeObserver.observe(this._referenceDomElement); } } public stopObserving(): void { - if (this.resizeObserver) { - this.resizeObserver.disconnect(); - this.resizeObserver = null; + if (this._resizeObserver) { + this._resizeObserver.disconnect(); + this._resizeObserver = null; } } @@ -61,23 +63,23 @@ export class ElementSizeObserver extends Disposable { this.measureReferenceDomElement(true, dimension); } - private measureReferenceDomElement(callChangeCallback: boolean, dimension?: IDimension): void { + private measureReferenceDomElement(emitEvent: boolean, dimension?: IDimension): void { let observedWidth = 0; let observedHeight = 0; if (dimension) { observedWidth = dimension.width; observedHeight = dimension.height; - } else if (this.referenceDomElement) { - observedWidth = this.referenceDomElement.clientWidth; - observedHeight = this.referenceDomElement.clientHeight; + } else if (this._referenceDomElement) { + observedWidth = this._referenceDomElement.clientWidth; + observedHeight = this._referenceDomElement.clientHeight; } observedWidth = Math.max(5, observedWidth); observedHeight = Math.max(5, observedHeight); - if (this.width !== observedWidth || this.height !== observedHeight) { - this.width = observedWidth; - this.height = observedHeight; - if (callChangeCallback) { - this.changeCallback(); + if (this._width !== observedWidth || this._height !== observedHeight) { + this._width = observedWidth; + this._height = observedHeight; + if (emitEvent) { + this._onDidChange.fire(); } } } diff --git a/src/vs/editor/browser/view/view.ts b/src/vs/editor/browser/view/view.ts index 28df9b778ce..aae814ddd23 100644 --- a/src/vs/editor/browser/view/view.ts +++ b/src/vs/editor/browser/view/view.ts @@ -420,7 +420,7 @@ export class View extends ViewEventHandler { // Try to detect browser zooming and paint again if necessary if (Math.abs(browser.getPixelRatio() - this._configPixelRatio) > 0.001) { // looks like the pixel ratio has changed - this._context.configuration.updatePixelRatio(); + this._context.configuration.observePixelRatio(); } } diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 170222a142e..b5ebe8ae5c3 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -62,7 +62,7 @@ let EDITOR_ID = 0; export interface ICodeEditorWidgetOptions { /** - * Is this a simple widget (not a real code editor) ? + * Is this a simple widget (not a real code editor)? * Defaults to false. */ isSimpleWidget?: boolean; @@ -213,7 +213,10 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE public readonly onDidChangeHiddenAreas: Event = this._onDidChangeHiddenAreas.event; //#endregion - public readonly isSimpleWidget: boolean; + public get isSimpleWidget(): boolean { + return this._configuration.isSimpleWidget; + } + private readonly _telemetryData?: object; private readonly _domElement: HTMLElement; @@ -270,10 +273,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE this._id = (++EDITOR_ID); this._decorationTypeKeysToIds = {}; this._decorationTypeSubtypes = {}; - this.isSimpleWidget = codeEditorWidgetOptions.isSimpleWidget || false; this._telemetryData = codeEditorWidgetOptions.telemetryData; - this._configuration = this._register(this._createConfiguration(options, accessibilityService)); + this._configuration = this._register(this._createConfiguration(codeEditorWidgetOptions.isSimpleWidget || false, options, accessibilityService)); this._register(this._configuration.onDidChange((e) => { this._onDidChangeConfiguration.fire(e); @@ -349,8 +351,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE this._codeEditorService.addCodeEditor(this); } - protected _createConfiguration(options: Readonly, accessibilityService: IAccessibilityService): editorCommon.IConfiguration { - return new Configuration(this.isSimpleWidget, options, this._domElement, accessibilityService); + protected _createConfiguration(isSimpleWidget: boolean, options: Readonly, accessibilityService: IAccessibilityService): Configuration { + return new Configuration(isSimpleWidget, options, this._domElement, accessibilityService); } public getId(): string { @@ -388,8 +390,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE return this._instantiationService.invokeFunction(fn); } - public updateOptions(newOptions: Readonly): void { - this._configuration.updateOptions(newOptions); + public updateOptions(newOptions: Readonly | undefined): void { + this._configuration.updateOptions(newOptions || {}); } public getOptions(): IComputedEditorOptions { @@ -1336,7 +1338,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } public layout(dimension?: editorCommon.IDimension): void { - this._configuration.observeReferenceElement(dimension); + this._configuration.observeContainer(dimension); this.render(); } @@ -1500,7 +1502,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } this._bannerDomNode = domNode; - this._configuration.reserveHeight(domNode ? domNodeHeight : 0); + this._configuration.setReservedHeight(domNode ? domNodeHeight : 0); if (this._bannerDomNode) { this._domElement.prepend(this._bannerDomNode); @@ -1517,7 +1519,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE this._domElement.setAttribute('data-mode-id', model.getLanguageId()); this._configuration.setIsDominatedByLongLines(model.isDominatedByLongLines()); - this._configuration.setMaxLineNumber(model.getLineCount()); + this._configuration.setModelLineCount(model.getLineCount()); model.onBeforeAttached(); diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 7a42d9ad4e2..1d6a4bb0bb7 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -325,7 +325,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this._isVisible = true; this._isHandlingScrollEvent = false; - this._elementSizeObserver = this._register(new ElementSizeObserver(this._containerDomElement, options.dimension, () => this._onDidContainerSizeChanged())); + this._elementSizeObserver = this._register(new ElementSizeObserver(this._containerDomElement, options.dimension)); + this._register(this._elementSizeObserver.onDidChange(() => this._onDidContainerSizeChanged())); if (options.automaticLayout) { this._elementSizeObserver.startObserving(); } diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 3e24c7ea2f7..533b2bb889e 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -733,22 +733,6 @@ export class ConfigurationChangedEvent { } } -/** - * @internal - */ -export class ValidatedEditorOptions { - private readonly _values: any[] = []; - public _read(option: EditorOption): T { - return this._values[option]; - } - public get(id: T): FindComputedEditorOptionValueById { - return this._values[id]; - } - public _write(option: EditorOption, value: T): void { - this._values[option] = value; - } -} - /** * All computed editor options. */ diff --git a/src/vs/editor/common/config/fontInfo.ts b/src/vs/editor/common/config/fontInfo.ts index 2580292155e..c067f58fb6b 100644 --- a/src/vs/editor/common/config/fontInfo.ts +++ b/src/vs/editor/common/config/fontInfo.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as platform from 'vs/base/common/platform'; -import { EditorOptions, ValidatedEditorOptions, EditorOption } from 'vs/editor/common/config/editorOptions'; +import { EditorOptions, EditorOption, FindComputedEditorOptionValueById } from 'vs/editor/common/config/editorOptions'; import { EditorZoom } from 'vs/editor/common/config/editorZoom'; /** @@ -18,13 +18,20 @@ const GOLDEN_LINE_HEIGHT_RATIO = platform.isMacintosh ? 1.5 : 1.35; */ const MINIMUM_LINE_HEIGHT = 8; +/** + * @internal + */ +export interface IValidatedEditorOptions { + get(id: T): FindComputedEditorOptionValueById; +} + export class BareFontInfo { readonly _bareFontInfoBrand: void = undefined; /** * @internal */ - public static createFromValidatedSettings(options: ValidatedEditorOptions, zoomLevel: number, pixelRatio: number, ignoreEditorZoom: boolean): BareFontInfo { + public static createFromValidatedSettings(options: IValidatedEditorOptions, zoomLevel: number, pixelRatio: number, ignoreEditorZoom: boolean): BareFontInfo { const fontFamily = options.get(EditorOption.fontFamily); const fontWeight = options.get(EditorOption.fontWeight); const fontSize = options.get(EditorOption.fontSize); @@ -54,7 +61,7 @@ export class BareFontInfo { if (lineHeight === 0) { lineHeight = GOLDEN_LINE_HEIGHT_RATIO * fontSize; } else if (lineHeight < MINIMUM_LINE_HEIGHT) { - // Values too small to be line heights in pixels are probably in ems. Accept them gracefully. + // Values too small to be line heights in pixels are in ems. lineHeight = lineHeight * fontSize; } @@ -116,7 +123,7 @@ export class BareFontInfo { * @internal */ public getId(): string { - return this.zoomLevel + '-' + this.pixelRatio + '-' + this.fontFamily + '-' + this.fontWeight + '-' + this.fontSize + '-' + this.fontFeatureSettings + '-' + this.lineHeight + '-' + this.letterSpacing; + return `${this.zoomLevel}-${this.pixelRatio}-${this.fontFamily}-${this.fontWeight}-${this.fontSize}-${this.fontFeatureSettings}-${this.lineHeight}-${this.letterSpacing}`; } /** diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 15e7550b29d..dd1160cc182 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -150,19 +150,53 @@ export interface ILineChange extends IChange { * @internal */ export interface IConfiguration extends IDisposable { - onDidChangeFast(listener: (e: ConfigurationChangedEvent) => void): IDisposable; - onDidChange(listener: (e: ConfigurationChangedEvent) => void): IDisposable; + /** + * Is this a simple widget (not a real code editor)? + */ + readonly isSimpleWidget: boolean; + /** + * Computed editor options. + */ readonly options: IComputedEditorOptions; - setMaxLineNumber(maxLineNumber: number): void; - setViewLineCount(viewLineCount: number): void; - updateOptions(newOptions: Readonly): void; + onDidChangeFast: Event; + onDidChange: Event; + + /** + * Get the raw options as they were passed in to the editor + * and merged with all calls to `updateOptions`. + */ getRawOptions(): IEditorOptions; - observeReferenceElement(dimension?: IDimension): void; - updatePixelRatio(): void; + /** + * Update the options with new partial options. All previous + * options will be kept and only present keys will be overwritten. + */ + updateOptions(newOptions: Readonly): void; + /** + * Recompute options with new reference element dimensions. + */ + observeContainer(dimension?: IDimension): void; + /** + * Recompute options with new pixel ratio. + */ + observePixelRatio(): void; + /** + * Set if the current model is dominated by long lines. + */ setIsDominatedByLongLines(isDominatedByLongLines: boolean): void; - reserveHeight(height: number): void; + /** + * Set the current model line count. + */ + setModelLineCount(modelLineCount: number): void; + /** + * Set the current view model line count. + */ + setViewLineCount(viewLineCount: number): void; + /** + * Set reserved height above. + */ + setReservedHeight(reservedHeight: number): void; } // --- view diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index 4cc2eaa04ee..5ca5f8f54ce 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -374,7 +374,7 @@ export class ViewModel extends Disposable implements IViewModel { // Update the configuration and reset the centered view line this._viewportStartLine = -1; - this._configuration.setMaxLineNumber(this.model.getLineCount()); + this._configuration.setModelLineCount(this.model.getLineCount()); this._updateConfigurationViewLineCountNow(); // Recover viewport diff --git a/src/vs/editor/test/browser/config/commonEditorConfig.test.ts b/src/vs/editor/test/browser/config/commonEditorConfig.test.ts index 3709b848896..29e60837cf3 100644 --- a/src/vs/editor/test/browser/config/commonEditorConfig.test.ts +++ b/src/vs/editor/test/browser/config/commonEditorConfig.test.ts @@ -54,7 +54,7 @@ suite('Common Editor Config', () => { }); class TestWrappingConfiguration extends TestConfiguration { - protected override _getEnvConfiguration(): IEnvConfiguration { + protected override _readEnvConfiguration(): IEnvConfiguration { return { extraEditorClassName: '', outerWidth: 1000, diff --git a/src/vs/editor/test/browser/config/testConfiguration.ts b/src/vs/editor/test/browser/config/testConfiguration.ts index d5143219c92..5f27193c2b9 100644 --- a/src/vs/editor/test/browser/config/testConfiguration.ts +++ b/src/vs/editor/test/browser/config/testConfiguration.ts @@ -13,10 +13,9 @@ export class TestConfiguration extends Configuration { constructor(opts: IEditorOptions) { super(false, opts, null, new TestAccessibilityService()); - this._recomputeOptions(); } - protected override _getEnvConfiguration(): IEnvConfiguration { + protected override _readEnvConfiguration(): IEnvConfiguration { return { extraEditorClassName: '', outerWidth: 100, @@ -28,7 +27,7 @@ export class TestConfiguration extends Configuration { }; } - protected override readConfiguration(styling: BareFontInfo): FontInfo { + protected override _readFontInfo(styling: BareFontInfo): FontInfo { return new FontInfo({ zoomLevel: 0, pixelRatio: 1, diff --git a/src/vs/editor/test/browser/testCodeEditor.ts b/src/vs/editor/test/browser/testCodeEditor.ts index 00fe484840d..151f115e946 100644 --- a/src/vs/editor/test/browser/testCodeEditor.ts +++ b/src/vs/editor/test/browser/testCodeEditor.ts @@ -10,7 +10,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService import { View } from 'vs/editor/browser/view/view'; import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget'; import * as editorOptions from 'vs/editor/common/config/editorOptions'; -import { IConfiguration, IEditorContribution } from 'vs/editor/common/editorCommon'; +import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { ITextBufferFactory, ITextModel } from 'vs/editor/common/model'; import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { IModelService } from 'vs/editor/common/services/model'; @@ -44,6 +44,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService'; +import { Configuration } from 'vs/editor/browser/config/configuration'; export interface ITestCodeEditor extends IActiveCodeEditor { getViewModel(): ViewModel | undefined; @@ -54,7 +55,7 @@ export interface ITestCodeEditor extends IActiveCodeEditor { export class TestCodeEditor extends CodeEditorWidget implements ICodeEditor { //#region testing overrides - protected override _createConfiguration(options: Readonly): IConfiguration { + protected override _createConfiguration(isSimpleWidget: boolean, options: Readonly): Configuration { return new TestConfiguration(options); } protected override _createView(viewModel: ViewModel): [View, boolean] { diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellWidgets.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellWidgets.ts index ae549224a87..79a5d94e667 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellWidgets.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellWidgets.ts @@ -5,7 +5,6 @@ import * as DOM from 'vs/base/browser/dom'; import { Disposable } from 'vs/base/common/lifecycle'; -import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver'; import { IDimension } from 'vs/editor/common/editorCommon'; export interface IClickTarget { @@ -19,8 +18,6 @@ export const enum ClickTargetType { ContributedCommandItem = 2 } -declare const ResizeObserver: any; - export interface IResizeObserver { startObserving: () => void; stopObserving: () => void; @@ -32,7 +29,7 @@ export interface IResizeObserver { export class BrowserResizeObserver extends Disposable implements IResizeObserver { private readonly referenceDomElement: HTMLElement | null; - private readonly observer: any; + private readonly observer: ResizeObserver; private width: number; private height: number; @@ -81,9 +78,5 @@ export class BrowserResizeObserver extends Disposable implements IResizeObserver } export function getResizesObserver(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined, changeCallback: () => void): IResizeObserver { - if (ResizeObserver) { - return new BrowserResizeObserver(referenceDomElement, dimension, changeCallback); - } else { - return new ElementSizeObserver(referenceDomElement, dimension, changeCallback); - } + return new BrowserResizeObserver(referenceDomElement, dimension, changeCallback); }