From 2ce435f98d84f7f4baeaee4ac5a8511abe5d3997 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 19 Apr 2020 03:54:28 -0700 Subject: [PATCH] Allow embedders to customize link decorations independently See microsoft/vscode#95631 --- src/browser/Linkifier2.ts | 58 +++++++++++++++++++++++++-------------- src/browser/Types.d.ts | 7 ++++- typings/xterm.d.ts | 22 +++++++++++++-- 3 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index 8b8e2894..f3e49500 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -3,14 +3,14 @@ * @license MIT */ -import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent } from './Types'; +import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent, ILinkDecorations } from './Types'; import { IDisposable } from 'common/Types'; import { IMouseService, IRenderService } from './services/Services'; import { IBufferService } from 'common/services/Services'; import { EventEmitter, IEvent } from 'common/EventEmitter'; interface ILinkState { - hideDecorations: boolean; + decorations: ILinkDecorations; isHovered: boolean; } @@ -199,21 +199,35 @@ export class Linkifier2 implements ILinkifier2 { if (this._linkAtPosition(link, position)) { this._currentLink = link; this._currentLinkState = { - hideDecorations: link.hideDecorations || false, + decorations: { + underline: link.decorations?.underline || true, + pointerCursor: link.decorations?.pointerCursor || true + }, isHovered: true }; this._linkHover(this._element, link, this._lastMouseEvent); - // Add listener for tracking hideDecorations changes - Object.defineProperties(link, { - hideDecorations: { - get: () => this._currentLinkState?.hideDecorations, + // Add listener for tracking decorations changes + link.decorations = {} as ILinkDecorations; + Object.defineProperties(link.decorations, { + pointerCursor: { + get: () => this._currentLinkState?.decorations.pointerCursor, set: v => { - if (this._currentLinkState && this._currentLinkState.hideDecorations !== v) { - this._currentLinkState.hideDecorations = v; - if (this._currentLinkState?.isHovered) { - this._fireUnderlineEvent(link, !v); - this._element?.classList.toggle('xterm-cursor-pointer', !v); + if (this._currentLinkState && this._currentLinkState?.decorations.pointerCursor !== v) { + this._currentLinkState.decorations.pointerCursor = v; + if (this._currentLinkState.isHovered) { + this._element?.classList.toggle('xterm-cursor-pointer', v); + } + } + } + }, + underline: { + get: () => this._currentLinkState?.decorations.underline, + set: v => { + if (this._currentLinkState && this._currentLinkState?.decorations.underline !== v) { + this._currentLinkState.decorations.underline = v; + if (this._currentLinkState.isHovered) { + this._fireUnderlineEvent(link, v); } } } @@ -230,12 +244,14 @@ export class Linkifier2 implements ILinkifier2 { } protected _linkHover(element: HTMLElement, link: ILink, event: MouseEvent): void { - if (!link.hideDecorations) { - this._fireUnderlineEvent(link, true); - element.classList.add('xterm-cursor-pointer'); - } if (this._currentLinkState) { this._currentLinkState.isHovered = true; + if (this._currentLinkState.decorations.underline) { + this._fireUnderlineEvent(link, true); + } + if (this._currentLinkState.decorations.pointerCursor) { + element.classList.add('xterm-cursor-pointer'); + } } if (link.hover) { @@ -252,12 +268,14 @@ export class Linkifier2 implements ILinkifier2 { } protected _linkLeave(element: HTMLElement, link: ILink, event: MouseEvent): void { - if (!link.hideDecorations) { - this._fireUnderlineEvent(link, false); - element.classList.remove('xterm-cursor-pointer'); - } if (this._currentLinkState) { this._currentLinkState.isHovered = false; + if (this._currentLinkState.decorations.underline) { + this._fireUnderlineEvent(link, false); + } + if (this._currentLinkState.decorations.pointerCursor) { + element.classList.remove('xterm-cursor-pointer'); + } } if (link.leave) { diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index 382d1c42..f4645543 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -172,12 +172,17 @@ interface ILinkProvider { interface ILink { range: IBufferRange; text: string; - hideDecorations?: boolean; + decorations?: ILinkDecorations; activate(event: MouseEvent, text: string): void; hover?(event: MouseEvent, text: string): void; leave?(event: MouseEvent, text: string): void; } +interface ILinkDecorations { + pointerCursor: boolean; + underline: boolean; +} + interface IBufferRange { start: IBufferCellPosition; end: IBufferCellPosition; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index c8901176..3487c410 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1121,10 +1121,11 @@ declare module 'xterm' { text: string; /** - * Whether to hide the underline and cursor styles, this property is tracked and changes made - * after the link is provided will trigger changes. + * What link decorations to show when hovering the link, this property is tracked and changes + * made after the link is provided will trigger changes. If not set, all decroations will be + * enabled. */ - hideDecorations?: boolean; + decorations?: ILinkDecorations; /** * Calls when the link is activated. @@ -1150,6 +1151,21 @@ declare module 'xterm' { leave?(event: MouseEvent, text: string): void; } + /** + * A set of decorations that can be applied to links. + */ + interface ILinkDecorations { + /** + * Whether the cursor is set to pointer. + */ + pointerCursor: boolean; + + /** + * Whether the underline is visible + */ + underline: boolean; + } + /** * A range within a buffer. */