Convert createLink to a class

This commit is contained in:
Daniel Imms 2020-04-18 18:29:13 -07:00
parent 16718fdb51
commit fe3527d742
4 changed files with 73 additions and 67 deletions

View file

@ -4,76 +4,82 @@
*--------------------------------------------------------------------------------------------*/
import { IViewportRange, IBufferRange, ILink } from 'xterm';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { DisposableStore } from 'vs/base/common/lifecycle';
import * as dom from 'vs/base/browser/dom';
import { RunOnceScheduler } from 'vs/base/common/async';
import { convertBufferRangeToViewport } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers';
export const TOOLTIP_HOVER_THRESHOLD = 300;
export function createLink(
range: IBufferRange,
text: string,
viewportY: number,
activateCallback: (event: MouseEvent, uri: string) => void,
tooltipCallback: (event: MouseEvent, uri: string, location: IViewportRange, modifierDownCallback?: () => void, modifierUpCallback?: () => void) => boolean | void,
hideDecorations: boolean
): ILink {
// Listen for modifier before handing it off to the hover to handle so it gets disposed correctly
const disposables: IDisposable[] = [];
if (hideDecorations) {
disposables.push(dom.addDisposableListener(document, 'keydown', e => {
// TODO: Use ctrl/option or cmd
if (e.ctrlKey && link.hideDecorations) {
link.hideDecorations = false;
export class TerminalLink extends DisposableStore implements ILink {
private _viewportRange: IViewportRange;
hideDecorations: boolean;
constructor(
public readonly range: IBufferRange,
public readonly text: string,
viewportY: number,
private readonly _activateCallback: (event: MouseEvent, uri: string) => void,
private readonly _tooltipCallback: (event: MouseEvent, uri: string, location: IViewportRange, modifierDownCallback?: () => void, modifierUpCallback?: () => void) => boolean | void,
private readonly _shouldHideDecorations: boolean = false,
) {
super();
this.hideDecorations = this._shouldHideDecorations;
this._viewportRange = convertBufferRangeToViewport(range, viewportY);
}
activate(event: MouseEvent, text: string): void {
this._activateCallback(event, text);
}
hover(event: MouseEvent, text: string): void {
// Listen for modifier before handing it off to the hover to handle so it gets disposed correctly
if (this._shouldHideDecorations) {
this.add(dom.addDisposableListener(document, 'keydown', e => {
// TODO: Use ctrl/option or cmd
if (e.ctrlKey && this._shouldHideDecorations) {
this.hideDecorations = false;
}
}));
this.add(dom.addDisposableListener(document, 'keyup', e => {
if (!e.ctrlKey) {
this.hideDecorations = true;
}
}));
}
const scheduler = new RunOnceScheduler(() => {
this._tooltipCallback(
event,
text,
this._viewportRange,
this._shouldHideDecorations ? () => this.hideDecorations = false : undefined,
this._shouldHideDecorations ? () => this.hideDecorations = true : undefined
);
this.dispose();
// TODO: Use editor.hover.delay instead
}, TOOLTIP_HOVER_THRESHOLD);
this.add(scheduler);
scheduler.schedule();
const origin = { x: event.pageX, y: event.pageY };
this.add(dom.addDisposableListener(document, dom.EventType.MOUSE_MOVE, e => {
// Update decorations
if (this._shouldHideDecorations) {
this.hideDecorations = !e.ctrlKey;
}
}));
disposables.push(dom.addDisposableListener(document, 'keyup', e => {
if (!e.ctrlKey) {
link.hideDecorations = true;
// Reset the scheduler if the mouse moves too much
if (Math.abs(e.pageX - origin.x) > window.devicePixelRatio * 2 || Math.abs(e.pageY - origin.y) > window.devicePixelRatio * 2) {
origin.x = e.pageX;
origin.y = e.pageY;
scheduler.schedule();
}
}));
}
let scheduler: RunOnceScheduler;
const link = {
text,
range,
hideDecorations,
activate: (event: MouseEvent, text: string) => activateCallback(event, text),
hover: (event: MouseEvent, text: string) => {
scheduler = new RunOnceScheduler(() => {
tooltipCallback(
event,
text,
convertBufferRangeToViewport(range, viewportY),
hideDecorations ? () => link.hideDecorations = false : undefined,
hideDecorations ? () => link.hideDecorations = true : undefined
);
dispose(disposables);
// TODO: Use editor.hover.delay instead
}, TOOLTIP_HOVER_THRESHOLD);
disposables.push(scheduler);
scheduler.schedule();
const origin = { x: event.pageX, y: event.pageY };
disposables.push(dom.addDisposableListener(document, dom.EventType.MOUSE_MOVE, e => {
// Update decorations
if (hideDecorations) {
link.hideDecorations = !e.ctrlKey;
}
// Reset the scheduler if the mouse moves too much
if (Math.abs(e.pageX - origin.x) > window.devicePixelRatio * 2 || Math.abs(e.pageY - origin.y) > window.devicePixelRatio * 2) {
origin.x = e.pageX;
origin.y = e.pageY;
scheduler.schedule();
}
}));
},
leave: () => dispose(disposables)
};
return link;
leave(): void {
this.dispose();
}
}

View file

@ -7,7 +7,7 @@ import { Terminal, ILinkProvider, IViewportRange, IBufferCellPosition, ILink, IB
import { getXtermLineContent, convertLinkRangeToBuffer, positionIsInRange } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers';
import { OperatingSystem } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { createLink } from 'vs/workbench/contrib/terminal/browser/links/terminalLink';
import { TerminalLink } from 'vs/workbench/contrib/terminal/browser/links/terminalLink';
const pathPrefix = '(\\.\\.?|\\~)';
const pathSeparatorClause = '\\/';
@ -109,7 +109,7 @@ export class TerminalValidatedLocalLinkProvider implements ILinkProvider {
this._activateFileCallback(event, text);
}
};
callback(createLink(bufferRange, link, this._xterm.buffer.active.viewportY, activateCallback, this._tooltipCallback, false));
callback(new TerminalLink(bufferRange, link, this._xterm.buffer.active.viewportY, activateCallback, this._tooltipCallback, false));
} else {
callback(undefined);
}

View file

@ -6,7 +6,7 @@
import { Terminal, IViewportRange, ILinkProvider, IBufferCellPosition, ILink, IBufferLine } from 'xterm';
import { ILinkComputerTarget, LinkComputer } from 'vs/editor/common/modes/linkComputer';
import { getXtermLineContent, convertLinkRangeToBuffer, positionIsInRange } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers';
import { createLink } from 'vs/workbench/contrib/terminal/browser/links/terminalLink';
import { TerminalLink } from 'vs/workbench/contrib/terminal/browser/links/terminalLink';
export class TerminalWebLinkProvider implements ILinkProvider {
private _linkComputerTarget: ILinkComputerTarget | undefined;
@ -46,7 +46,7 @@ export class TerminalWebLinkProvider implements ILinkProvider {
// Check if the link if within the mouse position
if (positionIsInRange(position, range)) {
found = true;
callback(createLink(range, link.url?.toString() || '', this._xterm.buffer.active.viewportY, this._activateCallback, this._tooltipCallback, false));
callback(new TerminalLink(range, link.url?.toString() || '', this._xterm.buffer.active.viewportY, this._activateCallback, this._tooltipCallback, false));
}
});

View file

@ -4,9 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import { Terminal, ILinkProvider, IViewportRange, IBufferCellPosition, ILink } from 'xterm';
import { createLink } from 'vs/workbench/contrib/terminal/browser/links/terminalLink';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ITerminalConfiguration, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal';
import { TerminalLink } from 'vs/workbench/contrib/terminal/browser/links/terminalLink';
export class TerminalWordLinkProvider implements ILinkProvider {
constructor(
@ -61,6 +61,6 @@ export class TerminalWordLinkProvider implements ILinkProvider {
text += char;
}
callback(createLink({ start, end }, text, this._xterm.buffer.active.viewportY, this._activateCallback, this._tooltipCallback, true));
callback(new TerminalLink({ start, end }, text, this._xterm.buffer.active.viewportY, this._activateCallback, this._tooltipCallback, true));
}
}