Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allowing to define variable line heights #233110

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
03425a9
Fix advanced line wrap if decorations are present
remcohaszing Nov 21, 2023
88e5584
Support dynamic line heights using decorations
remcohaszing Sep 29, 2023
d84a703
undo commenting
aiday-mar Nov 5, 2024
a2637a1
fixing compiler errors
aiday-mar Nov 5, 2024
824113e
placing tests in block comment
aiday-mar Nov 5, 2024
c54ab2c
adding logs
aiday-mar Nov 14, 2024
a98064b
limiting amount of logging
aiday-mar Nov 14, 2024
8a71210
changikng the font size and the line height directly in the code
aiday-mar Nov 14, 2024
f4e5ada
wip
aiday-mar Nov 15, 2024
8afcd7b
wip
aiday-mar Nov 15, 2024
6c110ab
removing monaco editor related code
aiday-mar Nov 18, 2024
5ee4853
wip
aiday-mar Nov 21, 2024
38dfbf6
wip
aiday-mar Nov 21, 2024
d0685e2
wip
aiday-mar Nov 22, 2024
f7ba276
adding wip
aiday-mar Nov 22, 2024
f7d47a3
setting doc as internal
aiday-mar Nov 22, 2024
cf367af
pushing to text to the bottom
aiday-mar Nov 22, 2024
e329622
adding support for font size
aiday-mar Nov 25, 2024
91d4be2
placing at the end
aiday-mar Nov 25, 2024
f7837fb
fixing tests
aiday-mar Nov 25, 2024
25492d2
adding likne height setting
aiday-mar Nov 25, 2024
aaaad55
adding comments
aiday-mar Nov 25, 2024
6395ef1
adding todo
aiday-mar Nov 29, 2024
549e9ed
overriding the font size in sticky scroll
aiday-mar Nov 29, 2024
95f7739
making sticky scroll also use the editor lines heights
aiday-mar Nov 29, 2024
ce134e3
updating sticky scroll on decoration change, investigating lines
aiday-mar Nov 29, 2024
9dec371
Merge branch 'main' into line-height
aiday-mar Jan 6, 2025
952f891
removing changes for font size, focusing on line height changes
aiday-mar Jan 6, 2025
9f7b34c
adding code
aiday-mar Jan 6, 2025
c6d8a6d
adding css changes to position text at the bottom
aiday-mar Jan 7, 2025
6ab9c03
adding also the chnages for demo
aiday-mar Jan 7, 2025
20d1702
adding code
aiday-mar Jan 7, 2025
54e8958
making content widgets correctly position themselves
aiday-mar Jan 7, 2025
e75e7f1
adding css changes to sticky scroll
aiday-mar Jan 7, 2025
c7ce4b2
adding more methods
aiday-mar Jan 7, 2025
13e7c56
adding code
aiday-mar Jan 8, 2025
5addef1
polishing
aiday-mar Jan 8, 2025
4ee17c5
adding code
aiday-mar Jan 8, 2025
b4b62de
polishing
aiday-mar Jan 8, 2025
4888a4d
adding css to sticky scroll
aiday-mar Jan 8, 2025
61dbab1
fixing bug
aiday-mar Jan 8, 2025
aae1f6d
remove testing code
aiday-mar Jan 8, 2025
35b214a
fixing tests
aiday-mar Jan 8, 2025
295a526
removing extension surfacing
aiday-mar Jan 8, 2025
1e596ca
Merge branch 'main' into line-height
alexdima Jan 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/vs/editor/browser/editorBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,11 @@ export interface ICodeEditor extends editorCommon.IEditor {
*/
getTopForPosition(lineNumber: number, column: number): number;

/**
* Get the line height for the line number.
*/
getLineHeightForLineNumber(lineNumber: number): number;

/**
* Set the model ranges that will be hidden in the view.
* Hidden areas are stored per source.
Expand Down
3 changes: 3 additions & 0 deletions src/vs/editor/browser/services/abstractCodeEditorService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {
public afterContentClassName: string | undefined;
public glyphMarginClassName: string | undefined;
public isWholeLine: boolean;
public lineHeight?: number;
public overviewRuler: IModelDecorationOverviewRulerOptions | undefined;
public stickiness: TrackedRangeStickiness | undefined;
public beforeInjectedText: InjectedTextOptions | undefined;
Expand Down Expand Up @@ -518,6 +519,7 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {

const options = providerArgs.options;
this.isWholeLine = Boolean(options.isWholeLine);
this.lineHeight = options.lineHeight;
this.stickiness = options.rangeBehavior;

const lightOverviewRulerColor = options.light && options.light.overviewRulerColor || options.overviewRulerColor;
Expand Down Expand Up @@ -547,6 +549,7 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {
className: this.className,
glyphMarginClassName: this.glyphMarginClassName,
isWholeLine: this.isWholeLine,
lineHeight: this.lineHeight,
overviewRuler: this.overviewRuler,
stickiness: this.stickiness,
before: this.beforeInjectedText,
Expand Down
4 changes: 4 additions & 0 deletions src/vs/editor/browser/view/renderingContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export abstract class RestrictedRenderingContext {
return this._viewLayout.getVerticalOffsetAfterLineNumber(lineNumber, includeViewZones);
}

public getLineHeightForLineNumber(lineNumber: number): number {
return this._viewLayout.getLineHeightForLineNumber(lineNumber);
}

public getDecorationsInViewport(): ViewModelDecoration[] {
return this.viewportData.getDecorationsInViewport();
}
Expand Down
15 changes: 12 additions & 3 deletions src/vs/editor/browser/view/viewLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ class ViewLayerRenderer<T extends IVisibleLine> {

for (let i = startIndex; i <= endIndex; i++) {
const lineNumber = rendLineNumberStart + i;
lines[i].layoutLine(lineNumber, deltaTop[lineNumber - deltaLN], this._viewportData.lineHeight);
lines[i].layoutLine(lineNumber, deltaTop[lineNumber - deltaLN], this._lineHeightForLineNumber(lineNumber));
}
}

Expand Down Expand Up @@ -560,7 +560,8 @@ class ViewLayerRenderer<T extends IVisibleLine> {
continue;
}

const renderResult = line.renderLine(i + rendLineNumberStart, deltaTop[i], this._viewportData.lineHeight, this._viewportData, sb);
const renderedLineNumber = i + rendLineNumberStart;
const renderResult = line.renderLine(renderedLineNumber, deltaTop[i], this._lineHeightForLineNumber(renderedLineNumber), this._viewportData, sb);
if (!renderResult) {
// line does not need rendering
continue;
Expand Down Expand Up @@ -590,7 +591,8 @@ class ViewLayerRenderer<T extends IVisibleLine> {
continue;
}

const renderResult = line.renderLine(i + rendLineNumberStart, deltaTop[i], this._viewportData.lineHeight, this._viewportData, sb);
const renderedLineNumber = i + rendLineNumberStart;
const renderResult = line.renderLine(renderedLineNumber, deltaTop[i], this._lineHeightForLineNumber(renderedLineNumber), this._viewportData, sb);
if (!renderResult) {
// line does not need rendering
continue;
Expand All @@ -605,4 +607,11 @@ class ViewLayerRenderer<T extends IVisibleLine> {
}
}
}

private _lineHeightForLineNumber(lineNumber: number): number {
if (this._viewportData.specialLineHeights.has(lineNumber)) {
return this._viewportData.specialLineHeights.get(lineNumber)!;
}
return this._viewportData.lineHeight;
}
Comment on lines +611 to +616
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to feed in a getter for this data via a new ctor field if necessary. Please don't add the line heights to the viewport data.

}
10 changes: 4 additions & 6 deletions src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ class Widget {
private readonly _fixedOverflowWidgets: boolean;
private _contentWidth: number;
private _contentLeft: number;
private _lineHeight: number;

private _primaryAnchor: PositionPair = new PositionPair(null, null);
private _secondaryAnchor: PositionPair = new PositionPair(null, null);
Expand Down Expand Up @@ -227,7 +226,6 @@ class Widget {
this._fixedOverflowWidgets = options.get(EditorOption.fixedOverflowWidgets);
this._contentWidth = layoutInfo.contentWidth;
this._contentLeft = layoutInfo.contentLeft;
this._lineHeight = options.get(EditorOption.lineHeight);

this._affinity = null;
this._preference = [];
Expand All @@ -246,7 +244,6 @@ class Widget {

public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): void {
const options = this._context.configuration.options;
this._lineHeight = options.get(EditorOption.lineHeight);
if (e.hasChanged(EditorOption.layoutInfo)) {
const layoutInfo = options.get(EditorOption.layoutInfo);
this._contentLeft = layoutInfo.contentLeft;
Expand Down Expand Up @@ -403,12 +400,12 @@ class Widget {
* The content widget should touch if possible the secondary anchor.
*/
private _getAnchorsCoordinates(ctx: RenderingContext): { primary: AnchorCoordinate | null; secondary: AnchorCoordinate | null } {
const primary = getCoordinates(this._primaryAnchor.viewPosition, this._affinity, this._lineHeight);
const primary = getCoordinates(this._primaryAnchor.viewPosition, this._affinity);
const secondaryViewPosition = (this._secondaryAnchor.viewPosition?.lineNumber === this._primaryAnchor.viewPosition?.lineNumber ? this._secondaryAnchor.viewPosition : null);
const secondary = getCoordinates(secondaryViewPosition, this._affinity, this._lineHeight);
const secondary = getCoordinates(secondaryViewPosition, this._affinity);
return { primary, secondary };

function getCoordinates(position: Position | null, affinity: PositionAffinity | null, lineHeight: number): AnchorCoordinate | null {
function getCoordinates(position: Position | null, affinity: PositionAffinity | null): AnchorCoordinate | null {
if (!position) {
return null;
}
Expand All @@ -421,6 +418,7 @@ class Widget {
// Left-align widgets that should appear :before content
const left = (position.column === 1 && affinity === PositionAffinity.LeftOfInjectedText ? 0 : horizontalPosition.left);
const top = ctx.getVerticalOffsetForLineNumber(position.lineNumber) - ctx.scrollTop;
const lineHeight = ctx.getLineHeightForLineNumber(position.lineNumber);
return new AnchorCoordinate(top, left, lineHeight);
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ export class ViewCursor {
}

const top = ctx.getVerticalOffsetForLineNumber(position.lineNumber) - ctx.bigNumbersDelta;
return new ViewCursorRenderData(top, left, paddingLeft, width, this._lineHeight, textContent, textContentClassName);
const height = this._context.viewLayout.getLineHeightForLineNumber(position.lineNumber);
return new ViewCursorRenderData(top, left, paddingLeft, width, height, textContent, textContentClassName);
}

const visibleRangeForCharacter = ctx.linesVisibleRangesForRange(new Range(position.lineNumber, position.column, position.lineNumber, position.column + nextGrapheme.length), false);
Expand Down Expand Up @@ -223,7 +224,7 @@ export class ViewCursor {
}

let top = ctx.getVerticalOffsetForLineNumber(position.lineNumber) - ctx.bigNumbersDelta;
let height = this._lineHeight;
let height = this._context.viewLayout.getLineHeightForLineNumber(position.lineNumber);

// Underline might interfere with clicking
if (this._cursorStyle === TextEditorCursorStyle.Underline || this._cursorStyle === TextEditorCursorStyle.UnderlineThin) {
Expand Down
5 changes: 4 additions & 1 deletion src/vs/editor/browser/viewParts/viewLines/viewLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ export class ViewLine implements IVisibleLine {
options.renderWhitespace,
options.renderControlCharacters,
options.fontLigatures !== EditorFontLigatures.OFF,
selectionsOnLine
selectionsOnLine,
lineHeight
);

if (this._renderedViewLine && this._renderedViewLine.input.equals(renderLineInput)) {
Expand All @@ -175,6 +176,8 @@ export class ViewLine implements IVisibleLine {
sb.appendString(String(deltaTop));
sb.appendString('px;height:');
sb.appendString(String(lineHeight));
sb.appendString('px;line-height:');
sb.appendString(String(lineHeight));
sb.appendString('px;" class="');
sb.appendString(ViewLine.CLASS_NAME);
sb.appendString('">');
Expand Down
2 changes: 1 addition & 1 deletion src/vs/editor/browser/viewParts/whitespace/whitespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export class WhitespaceOverlay extends DynamicViewOverlay {
const fauxIndentLength = lineData.minColumn - 1;
const onlyBoundary = (this._options.renderWhitespace === 'boundary');
const onlyTrailing = (this._options.renderWhitespace === 'trailing');
const lineHeight = this._options.lineHeight;
const lineHeight = ctx.getLineHeightForLineNumber(lineNumber);
const middotWidth = this._options.middotWidth;
const wsmiddotWidth = this._options.wsmiddotWidth;
const spaceWidth = this._options.spaceWidth;
Expand Down
7 changes: 7 additions & 0 deletions src/vs/editor/browser/widget/codeEditor/codeEditorWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,13 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
return CodeEditorWidget._getVerticalOffsetAfterPosition(this._modelData, lineNumber, maxCol, includeViewZones);
}

public getLineHeightForLineNumber(lineNumber: number): number {
if (!this._modelData) {
return -1;
}
return this._modelData.viewModel.viewLayout.getLineHeightForLineNumber(lineNumber);
}

public setHiddenAreas(ranges: IRange[], source?: unknown, forceUpdate?: boolean): void {
this._modelData?.viewModel.setHiddenAreas(ranges.map(r => Range.lift(r)), source, forceUpdate);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,8 @@ class View extends Disposable {
options.get(EditorOption.renderWhitespace),
options.get(EditorOption.renderControlCharacters),
options.get(EditorOption.fontLigatures) !== EditorFontLigatures.OFF,
null
null,
options.get(EditorOption.lineHeight)
));

return r.html;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ function renderOriginalLine(
options.renderWhitespace,
options.renderControlCharacters,
options.fontLigatures !== EditorFontLigatures.OFF,
null // Send no selections, original line cannot be selected
null, // Send no selections, original line cannot be selected
options.lineHeight
), sb);

sb.appendString('</div>');
Expand Down
1 change: 1 addition & 0 deletions src/vs/editor/common/editorCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,7 @@ export interface IThemeDecorationRenderOptions {
fontStyle?: string;
fontWeight?: string;
fontSize?: string;
lineHeight?: number;
textDecoration?: string;
cursor?: string;
color?: string | ThemeColor;
Expand Down
12 changes: 11 additions & 1 deletion src/vs/editor/common/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { IWordAtPosition } from './core/wordHelper.js';
import { FormattingOptions } from './languages.js';
import { ILanguageSelection } from './languages/language.js';
import { IBracketPairsTextModelPart } from './textModelBracketPairs.js';
import { IModelContentChange, IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelTokensChangedEvent, InternalModelContentChangeEvent, ModelInjectedTextChangedEvent } from './textModelEvents.js';
import { IModelContentChange, IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelTokensChangedEvent, InternalModelContentChangeEvent, ModelInjectedTextChangedEvent, ModelSpecialLineHeightChangedEvent } from './textModelEvents.js';
import { IGuidesTextModelPart } from './textModelGuides.js';
import { ITokenizationTextModelPart } from './tokenizationTextModelPart.js';
import { UndoRedoGroup } from '../../platform/undoRedo/common/undoRedo.js';
Expand Down Expand Up @@ -218,6 +218,10 @@ export interface IModelDecorationOptions {
* with the specified {@link IModelDecorationGlyphMarginOptions} in the glyph margin.
*/
glyphMargin?: IModelDecorationGlyphMarginOptions | null;
/**
* If set, the decoration will override the line height of the lines it spans. This can only increase the line height, not decrease it.
*/
lineHeight?: number | null;
Comment on lines +221 to +224
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qq: why can the line height only be increased?

/**
* If set, the decoration will be rendered in the lines decorations with this CSS class name.
*/
Expand Down Expand Up @@ -1233,6 +1237,12 @@ export interface ITextModel {
* @event
*/
readonly onDidChangeDecorations: Event<IModelDecorationsChangedEvent>;
/**
* An event emitted when line heights from decorations changes
* @internal
* @event
*/
readonly onDidChangeSpecialLineHeight: Event<ModelSpecialLineHeightChangedEvent>;
/**
* An event emitted when the model options have changed.
* @event
Expand Down
Loading
Loading