Skip to content

Commit

Permalink
Merge pull request #144080 from microsoft/hediet/widget-position-affi…
Browse files Browse the repository at this point in the history
…nity

Fixes #132021 by introducing position affinity for widgets.
  • Loading branch information
hediet authored Mar 2, 2022
2 parents 6f906f3 + 6e624de commit 7e4da40
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 9 deletions.
6 changes: 6 additions & 0 deletions src/vs/editor/browser/editorBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ export interface IContentWidgetPosition {
* Placement preference for position, in order of preference.
*/
preference: ContentWidgetPositionPreference[];

/**
* Placement preference when multiple view positions refer to the same (model) position.
* This plays a role when injected text is involved.
*/
positionAffinity?: PositionAffinity;
}
/**
* A content widget renders inline with the text and can be easily placed 'near' an editor position.
Expand Down
2 changes: 1 addition & 1 deletion src/vs/editor/browser/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ export class View extends ViewEventHandler {
}
}
const newPreference = widgetData.position ? widgetData.position.preference : null;
this._contentWidgets.setWidgetPosition(widgetData.widget, newRange, newPreference);
this._contentWidgets.setWidgetPosition(widgetData.widget, newRange, newPreference, widgetData.position?.positionAffinity ?? null);
this._scheduleRender();
}

Expand Down
18 changes: 11 additions & 7 deletions src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import * as viewEvents from 'vs/editor/common/viewEvents';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { IDimension } from 'vs/editor/common/core/dimension';
import { PositionAffinity } from 'vs/editor/common/model';


class Coordinate {
Expand Down Expand Up @@ -112,9 +113,9 @@ export class ViewContentWidgets extends ViewPart {
this.setShouldRender();
}

public setWidgetPosition(widget: IContentWidget, range: IRange | null, preference: ContentWidgetPositionPreference[] | null): void {
public setWidgetPosition(widget: IContentWidget, range: IRange | null, preference: ContentWidgetPositionPreference[] | null, affinity: PositionAffinity | null): void {
const myWidget = this._widgets[widget.getId()];
myWidget.setPosition(range, preference);
myWidget.setPosition(range, preference, affinity);

this.setShouldRender();
}
Expand Down Expand Up @@ -193,6 +194,7 @@ class Widget {
private _lineHeight: number;

private _range: IRange | null;
private _affinity: PositionAffinity | null;
private _viewRange: Range | null;
private _preference: ContentWidgetPositionPreference[] | null;
private _cachedDomNodeOffsetWidth: number;
Expand Down Expand Up @@ -222,6 +224,7 @@ class Widget {

this._range = null;
this._viewRange = null;
this._affinity = null;
this._preference = [];
this._cachedDomNodeOffsetWidth = -1;
this._cachedDomNodeOffsetHeight = -1;
Expand All @@ -248,18 +251,19 @@ class Widget {
}

public onLineMappingChanged(e: viewEvents.ViewLineMappingChangedEvent): void {
this._setPosition(this._range);
this._setPosition(this._range, this._affinity);
}

private _setPosition(range: IRange | null): void {
private _setPosition(range: IRange | null, affinity: PositionAffinity | null): void {
this._range = range;
this._viewRange = null;
this._affinity = affinity;

if (this._range) {
// Do not trust that widgets give a valid position
const validModelRange = this._context.viewModel.model.validateRange(this._range);
if (this._context.viewModel.coordinatesConverter.modelPositionIsVisible(validModelRange.getStartPosition()) || this._context.viewModel.coordinatesConverter.modelPositionIsVisible(validModelRange.getEndPosition())) {
this._viewRange = this._context.viewModel.coordinatesConverter.convertModelRangeToViewRange(validModelRange);
this._viewRange = this._context.viewModel.coordinatesConverter.convertModelRangeToViewRange(validModelRange, this._affinity ?? undefined);
}
}
}
Expand All @@ -272,8 +276,8 @@ class Widget {
);
}

public setPosition(range: IRange | null, preference: ContentWidgetPositionPreference[] | null): void {
this._setPosition(range);
public setPosition(range: IRange | null, preference: ContentWidgetPositionPreference[] | null, affinity: PositionAffinity | null): void {
this._setPosition(range, affinity);
this._preference = preference;
if (this._viewRange && this._preference && this._preference.length > 0) {
// this content widget would like to be visible if possible
Expand Down
10 changes: 9 additions & 1 deletion src/vs/editor/contrib/message/browser/messageController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { EditorCommand, registerEditorCommand, registerEditorContribution } from
import { IPosition } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { IEditorContribution, ScrollType } from 'vs/editor/common/editorCommon';
import { PositionAffinity } from 'vs/editor/common/model';
import * as nls from 'vs/nls';
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
Expand Down Expand Up @@ -181,7 +182,14 @@ class MessageWidget implements IContentWidget {
}

getPosition(): IContentWidgetPosition {
return { position: this._position, preference: [ContentWidgetPositionPreference.ABOVE, ContentWidgetPositionPreference.BELOW] };
return {
position: this._position,
preference: [
ContentWidgetPositionPreference.ABOVE,
ContentWidgetPositionPreference.BELOW,
],
positionAffinity: PositionAffinity.Right,
};
}

afterRender(position: ContentWidgetPositionPreference | null): void {
Expand Down
5 changes: 5 additions & 0 deletions src/vs/monaco.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4608,6 +4608,11 @@ declare namespace monaco.editor {
* Placement preference for position, in order of preference.
*/
preference: ContentWidgetPositionPreference[];
/**
* Placement preference when multiple view positions refer to the same (model) position.
* This plays a role when injected text is involved.
*/
positionAffinity?: PositionAffinity;
}

/**
Expand Down

0 comments on commit 7e4da40

Please sign in to comment.