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

Support dynamic line heights using decorations #194609

Closed
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
14 changes: 9 additions & 5 deletions src/vs/editor/browser/view/viewLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ export interface IVisibleLine extends ILine {
* Return null if the HTML should not be touched.
* Return the new HTML otherwise.
*/
renderLine(lineNumber: number, deltaTop: number, viewportData: ViewportData, sb: StringBuilder): boolean;
renderLine(lineNumber: number, deltaTop: number, lineHeight: number, viewportData: ViewportData, sb: StringBuilder): boolean;

/**
* Layout the line.
*/
layoutLine(lineNumber: number, deltaTop: number): void;
layoutLine(lineNumber: number, deltaTop: number, lineHeight: number): void;
}

export interface ILine {
Expand Down Expand Up @@ -465,7 +465,9 @@ class ViewLayerRenderer<T extends IVisibleLine> {

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

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

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

const renderResult = line.renderLine(i + rendLineNumberStart, deltaTop[i], this.viewportData, sb);
const lineHeight = deltaTop[i + 1] - deltaTop[i];
const renderResult = line.renderLine(i + rendLineNumberStart, deltaTop[i], lineHeight, this.viewportData, sb);
if (!renderResult) {
// line does not need rendering
continue;
Expand Down
30 changes: 8 additions & 22 deletions src/vs/editor/browser/view/viewOverlays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { IVisibleLine, IVisibleLinesHost, VisibleLinesCollection } from 'vs/editor/browser/view/viewLayer';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { StringBuilder } from 'vs/editor/common/core/stringBuilder';
import { IEditorConfiguration } from 'vs/editor/common/config/editorConfiguration';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/browser/view/renderingContext';
import { ViewContext } from 'vs/editor/common/viewModel/viewContext';
import * as viewEvents from 'vs/editor/common/viewEvents';
Expand Down Expand Up @@ -71,7 +70,7 @@ export class ViewOverlays extends ViewPart implements IVisibleLinesHost<ViewOver
// ---- begin IVisibleLinesHost

public createVisibleLine(): ViewOverlayLine {
return new ViewOverlayLine(this._context.configuration, this._dynamicOverlays);
return new ViewOverlayLine(this._dynamicOverlays);
}

// ---- end IVisibleLinesHost
Expand All @@ -84,12 +83,6 @@ export class ViewOverlays extends ViewPart implements IVisibleLinesHost<ViewOver

public override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {
this._visibleLines.onConfigurationChanged(e);
const startLineNumber = this._visibleLines.getStartLineNumber();
const endLineNumber = this._visibleLines.getEndLineNumber();
for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {
const line = this._visibleLines.getVisibleLine(lineNumber);
line.onConfigurationChanged(e);
}

const options = this._context.configuration.options;
const fontInfo = options.get(EditorOption.fontInfo);
Expand Down Expand Up @@ -149,15 +142,11 @@ export class ViewOverlays extends ViewPart implements IVisibleLinesHost<ViewOver

export class ViewOverlayLine implements IVisibleLine {

private readonly _configuration: IEditorConfiguration;
private readonly _dynamicOverlays: DynamicViewOverlay[];
private _domNode: FastDomNode<HTMLElement> | null;
private _renderedContent: string | null;
private _lineHeight: number;

constructor(configuration: IEditorConfiguration, dynamicOverlays: DynamicViewOverlay[]) {
this._configuration = configuration;
this._lineHeight = this._configuration.options.get(EditorOption.lineHeight);
constructor(dynamicOverlays: DynamicViewOverlay[]) {
this._dynamicOverlays = dynamicOverlays;

this._domNode = null;
Expand All @@ -180,11 +169,8 @@ export class ViewOverlayLine implements IVisibleLine {
public onTokensChanged(): void {
// Nothing
}
public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): void {
this._lineHeight = this._configuration.options.get(EditorOption.lineHeight);
}

public renderLine(lineNumber: number, deltaTop: number, viewportData: ViewportData, sb: StringBuilder): boolean {
public renderLine(lineNumber: number, deltaTop: number, lineHeight: number, viewportData: ViewportData, sb: StringBuilder): boolean {
let result = '';
for (let i = 0, len = this._dynamicOverlays.length; i < len; i++) {
const dynamicOverlay = this._dynamicOverlays[i];
Expand All @@ -198,21 +184,21 @@ export class ViewOverlayLine implements IVisibleLine {

this._renderedContent = result;

sb.appendString('<div style="position:absolute;top:');
sb.appendString('<div class="view-overlay" style="top:');
sb.appendString(String(deltaTop));
sb.appendString('px;width:100%;height:');
sb.appendString(String(this._lineHeight));
sb.appendString('px;height:');
sb.appendString(String(lineHeight));
sb.appendString('px;">');
sb.appendString(result);
sb.appendString('</div>');

return true;
}

public layoutLine(lineNumber: number, deltaTop: number): void {
public layoutLine(lineNumber: number, deltaTop: number, lineHeight: number): void {
if (this._domNode) {
this._domNode.setTop(deltaTop);
this._domNode.setHeight(this._lineHeight);
this._domNode.setHeight(lineHeight);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
left: 0;
top: 0;
box-sizing: border-box;
height: 100%;
}

.monaco-editor .margin-view-overlays .current-line {
Expand All @@ -17,8 +18,11 @@
left: 0;
top: 0;
box-sizing: border-box;
height: 100%;
}

.monaco-editor .margin-view-overlays .current-line.current-line-margin.current-line-margin-both {
.monaco-editor
.margin-view-overlays
.current-line.current-line-margin.current-line-margin-both {
border-right: 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export class CurrentLineHighlightOverlay extends AbstractLineHighlightOverlay {

protected _renderOne(ctx: RenderingContext): string {
const className = 'current-line' + (this._shouldRenderOther() ? ' current-line-both' : '');
return `<div class="${className}" style="width:${Math.max(ctx.scrollWidth, this._contentWidth)}px; height:${this._lineHeight}px;"></div>`;
return `<div class="${className}" style="width:${Math.max(ctx.scrollWidth, this._contentWidth)}px;"></div>`;
}
protected _shouldRenderThis(): boolean {
return this._shouldRenderInContent();
Expand Down
3 changes: 2 additions & 1 deletion src/vs/editor/browser/viewParts/decorations/decorations.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
*/
.monaco-editor .lines-content .cdr {
position: absolute;
}
height: 100%;
}
13 changes: 5 additions & 8 deletions src/vs/editor/browser/viewParts/decorations/decorations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ export class DecorationsOverlay extends DynamicViewOverlay {
}

private _renderWholeLineDecorations(ctx: RenderingContext, decorations: ViewModelDecoration[], output: string[]): void {
const lineHeight = String(this._lineHeight);
const visibleStartLineNumber = ctx.visibleRange.startLineNumber;
const visibleEndLineNumber = ctx.visibleRange.endLineNumber;

Expand All @@ -130,9 +129,7 @@ export class DecorationsOverlay extends DynamicViewOverlay {
const decorationOutput = (
'<div class="cdr '
+ d.options.className
+ '" style="left:0;width:100%;height:'
+ lineHeight
+ 'px;"></div>'
+ '" style="left:0;width:100%;"></div>'
);

const startLineNumber = Math.max(d.range.startLineNumber, visibleStartLineNumber);
Expand Down Expand Up @@ -222,12 +219,12 @@ export class DecorationsOverlay extends DynamicViewOverlay {
+ className
+ '" style="left:'
+ String(visibleRange.left)
+ 'px;width:'
+ (expandToLeft ?
'px;width:100%;height:' :
('px;width:' + String(visibleRange.width) + 'px;height:')
'100%;' :
(String(visibleRange.width) + 'px;')
)
+ lineHeight
+ 'px;"></div>'
+ '"></div>'
);
output[lineIndex] += decorationOutput;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
.monaco-editor .lines-content .core-guide {
position: absolute;
box-sizing: border-box;
height: 100%;
}
6 changes: 1 addition & 5 deletions src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {

private readonly _context: ViewContext;
private _primaryPosition: Position | null;
private _lineHeight: number;
private _spaceWidth: number;
private _renderResult: string[] | null;
private _maxIndentLeft: number;
Expand All @@ -37,7 +36,6 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
const wrappingInfo = options.get(EditorOption.wrappingInfo);
const fontInfo = options.get(EditorOption.fontInfo);

this._lineHeight = options.get(EditorOption.lineHeight);
this._spaceWidth = fontInfo.spaceWidth;
this._maxIndentLeft = wrappingInfo.wrappingColumn === -1 ? -1 : (wrappingInfo.wrappingColumn * fontInfo.typicalHalfwidthCharacterWidth);
this._bracketPairGuideOptions = options.get(EditorOption.guides);
Expand All @@ -60,7 +58,6 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
const wrappingInfo = options.get(EditorOption.wrappingInfo);
const fontInfo = options.get(EditorOption.fontInfo);

this._lineHeight = options.get(EditorOption.lineHeight);
this._spaceWidth = fontInfo.spaceWidth;
this._maxIndentLeft = wrappingInfo.wrappingColumn === -1 ? -1 : (wrappingInfo.wrappingColumn * fontInfo.typicalHalfwidthCharacterWidth);
this._bracketPairGuideOptions = options.get(EditorOption.guides);
Expand Down Expand Up @@ -114,7 +111,6 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
const visibleStartLineNumber = ctx.visibleRange.startLineNumber;
const visibleEndLineNumber = ctx.visibleRange.endLineNumber;
const scrollWidth = ctx.scrollWidth;
const lineHeight = this._lineHeight;

const activeCursorPosition = this._primaryPosition;

Expand Down Expand Up @@ -150,7 +146,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
)?.left ?? (left + this._spaceWidth)) - left
: this._spaceWidth;

result += `<div class="core-guide ${guide.className} ${className}" style="left:${left}px;height:${lineHeight}px;width:${width}px"></div>`;
result += `<div class="core-guide ${guide.className} ${className}" style="left:${left}px;width:${width}px"></div>`;
}
output[lineIndex] = result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/

.monaco-editor .margin-view-overlays .line-numbers {
bottom: 0;
font-variant-numeric: tabular-nums;
position: absolute;
text-align: right;
display: inline-block;
vertical-align: middle;
box-sizing: border-box;
cursor: default;
height: 100%;
}

.monaco-editor .relative-current-line-number {
Expand Down
8 changes: 4 additions & 4 deletions src/vs/editor/browser/viewParts/lines/viewLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export class ViewLine implements IVisibleLine {
return false;
}

public renderLine(lineNumber: number, deltaTop: number, viewportData: ViewportData, sb: StringBuilder): boolean {
public renderLine(lineNumber: number, deltaTop: number, lineHeight: number, viewportData: ViewportData, sb: StringBuilder): boolean {
if (this._isMaybeInvalid === false) {
// it appears that nothing relevant has changed
return false;
Expand Down Expand Up @@ -222,7 +222,7 @@ export class ViewLine implements IVisibleLine {
sb.appendString('<div style="top:');
sb.appendString(String(deltaTop));
sb.appendString('px;height:');
sb.appendString(String(this._options.lineHeight));
sb.appendString(String(lineHeight));
sb.appendString('px;" class="');
sb.appendString(ViewLine.CLASS_NAME);
sb.appendString('">');
Expand Down Expand Up @@ -255,10 +255,10 @@ export class ViewLine implements IVisibleLine {
return true;
}

public layoutLine(lineNumber: number, deltaTop: number): void {
public layoutLine(lineNumber: number, deltaTop: number, lineHeight: number): void {
if (this._renderedViewLine && this._renderedViewLine.domNode) {
this._renderedViewLine.domNode.setTop(deltaTop);
this._renderedViewLine.domNode.setHeight(this._options.lineHeight);
this._renderedViewLine.domNode.setHeight(lineHeight);
}
}

Expand Down
10 changes: 9 additions & 1 deletion src/vs/editor/browser/viewParts/lines/viewLines.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
}

.mtkoverflow {
background-color: var(--vscode-button-background, var(--vscode-editor-background));
background-color: var(
--vscode-button-background,
var(--vscode-editor-background)
);
color: var(--vscode-button-foreground, var(--vscode-editor-foreground));
border-width: 1px;
border-style: solid;
Expand Down Expand Up @@ -63,6 +66,11 @@
width: 100%;
}

.monaco-editor .view-line > span {
bottom: 0;
position: absolute;
}

.monaco-editor .mtkw {
color: var(--vscode-editorWhitespace-foreground) !important;
}
Expand Down
1 change: 1 addition & 0 deletions src/vs/editor/browser/viewParts/selections/selections.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/
.monaco-editor .lines-content .cslr {
position: absolute;
height: 100%;
}

.monaco-editor .focused .selected-text {
Expand Down
Loading