xterm
[VSoRC/.git] / node_modules / xterm / src / browser / renderer / LinkRenderLayer.ts
1 /**
2  * Copyright (c) 2017 The xterm.js authors. All rights reserved.
3  * @license MIT
4  */
5
6 import { IRenderDimensions } from 'browser/renderer/Types';
7 import { BaseRenderLayer } from './BaseRenderLayer';
8 import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
9 import { is256Color } from 'browser/renderer/atlas/CharAtlasUtils';
10 import { IColorSet, ILinkifierEvent, ILinkifier } from 'browser/Types';
11 import { IBufferService, IOptionsService } from 'common/services/Services';
12
13 export class LinkRenderLayer extends BaseRenderLayer {
14   private _state: ILinkifierEvent | undefined;
15
16   constructor(
17     container: HTMLElement,
18     zIndex: number,
19     colors: IColorSet,
20     rendererId: number,
21     linkifier: ILinkifier,
22     readonly bufferService: IBufferService,
23     readonly optionsService: IOptionsService
24   ) {
25     super(container, 'link', zIndex, true, colors, rendererId, bufferService, optionsService);
26     linkifier.onLinkHover(e => this._onLinkHover(e));
27     linkifier.onLinkLeave(e => this._onLinkLeave(e));
28   }
29
30   public resize(dim: IRenderDimensions): void {
31     super.resize(dim);
32     // Resizing the canvas discards the contents of the canvas so clear state
33     this._state = undefined;
34   }
35
36   public reset(): void {
37     this._clearCurrentLink();
38   }
39
40   private _clearCurrentLink(): void {
41     if (this._state) {
42       this._clearCells(this._state.x1, this._state.y1, this._state.cols - this._state.x1, 1);
43       const middleRowCount = this._state.y2 - this._state.y1 - 1;
44       if (middleRowCount > 0) {
45         this._clearCells(0, this._state.y1 + 1, this._state.cols, middleRowCount);
46       }
47       this._clearCells(0, this._state.y2, this._state.x2, 1);
48       this._state = undefined;
49     }
50   }
51
52   private _onLinkHover(e: ILinkifierEvent): void {
53     if (e.fg === INVERTED_DEFAULT_COLOR) {
54       this._ctx.fillStyle = this._colors.background.css;
55     } else if (e.fg && is256Color(e.fg)) {
56       // 256 color support
57       this._ctx.fillStyle = this._colors.ansi[e.fg].css;
58     } else {
59       this._ctx.fillStyle = this._colors.foreground.css;
60     }
61
62     if (e.y1 === e.y2) {
63       // Single line link
64       this._fillBottomLineAtCells(e.x1, e.y1, e.x2 - e.x1);
65     } else {
66       // Multi-line link
67       this._fillBottomLineAtCells(e.x1, e.y1, e.cols - e.x1);
68       for (let y = e.y1 + 1; y < e.y2; y++) {
69         this._fillBottomLineAtCells(0, y, e.cols);
70       }
71       this._fillBottomLineAtCells(0, e.y2, e.x2);
72     }
73     this._state = e;
74   }
75
76   private _onLinkLeave(e: ILinkifierEvent): void {
77     this._clearCurrentLink();
78   }
79 }