mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
add scroll decorations
This commit is contained in:
@@ -178,3 +178,17 @@
|
||||
z-index: 6;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.xterm-decoration-scrollbar {
|
||||
z-index: 7;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.xterm-decoration-scrollbar.demo-scrollbar {
|
||||
height: 436px;
|
||||
left: 872px;
|
||||
top: 83px;
|
||||
}
|
||||
|
||||
@@ -151,6 +151,7 @@ if (document.location.pathname === '/test') {
|
||||
document.getElementById('custom-glyph').addEventListener('click', writeCustomGlyphHandler);
|
||||
document.getElementById('load-test').addEventListener('click', loadTest);
|
||||
document.getElementById('add-decoration').addEventListener('click', addDecoration);
|
||||
document.getElementById('add-scrollbar-decoration').addEventListener('click', addScrollbarDecoration);
|
||||
}
|
||||
|
||||
function createTerminal(): void {
|
||||
@@ -550,3 +551,11 @@ function addDecoration() {
|
||||
decoration.element.style.backgroundColor = 'red';
|
||||
});
|
||||
}
|
||||
|
||||
function addScrollbarDecoration() {
|
||||
term.registerDecoration({marker: term.addMarker(1), scrollbarDecorationColor: 'red'});
|
||||
term.registerDecoration({marker: term.addMarker(3), scrollbarDecorationColor: 'green'});
|
||||
term.registerDecoration({marker: term.addMarker(5), scrollbarDecorationColor: 'blue'});
|
||||
document.querySelector('.xterm-decoration-scrollbar').classList.add('demo-scrollbar');
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
<button id="custom-glyph" title="Write custom box drawing and block element characters to the terminal">Test custom glyphs</button>
|
||||
<button id="load-test" title="Write several MB of data to simulate a lot of data coming from the process">Load test</button>
|
||||
<button id="add-decoration" title="Add a decoration to the terminal">Decoration</button>
|
||||
<button id="add-scrollbar-decoration" title="Add a scrollbar decoration to the terminal">Add Scrollbar Decoration</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { addDisposableDomListener } from 'browser/Lifecycle';
|
||||
import { IDecorationService, IRenderService } from 'browser/services/Services';
|
||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
@@ -17,7 +18,11 @@ export class DecorationService extends Disposable implements IDecorationService
|
||||
private _renderService: IRenderService | undefined;
|
||||
private _animationFrame: number | undefined;
|
||||
|
||||
constructor(@IInstantiationService private readonly _instantiationService: IInstantiationService) { super(); }
|
||||
private _scrollbarDecorationCanvas: CanvasRenderingContext2D | null = null;
|
||||
private _scrollbarDecorationNode: HTMLCanvasElement | undefined;
|
||||
private _scrollbarDecorations: { marker: IMarker, color?: string}[] = [];
|
||||
|
||||
constructor(@IInstantiationService private readonly _instantiationService: IInstantiationService, @IBufferService private readonly _bufferService: IBufferService) { super(); }
|
||||
|
||||
public attachToDom(screenElement: HTMLElement, renderService: IRenderService): void {
|
||||
this._renderService = renderService;
|
||||
@@ -27,12 +32,22 @@ export class DecorationService extends Disposable implements IDecorationService
|
||||
screenElement.appendChild(this._container);
|
||||
this.register(this._renderService.onRenderedBufferChange(() => this.refresh()));
|
||||
this.register(this._renderService.onDimensionsChange(() => this.refresh(true)));
|
||||
this.register(addDisposableDomListener(window, 'resize', () => this._refreshScollbarDecorations()));
|
||||
}
|
||||
|
||||
public registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined {
|
||||
if (decorationOptions.marker.isDisposed || !this._container) {
|
||||
return undefined;
|
||||
}
|
||||
if (decorationOptions.scrollbarDecorationColor) {
|
||||
if (!this._scrollbarDecorationCanvas) {
|
||||
this._scrollbarDecorationNode = document.createElement('canvas');
|
||||
this._scrollbarDecorationNode.classList.add('xterm-decoration-scrollbar');
|
||||
this._screenElement?.parentElement?.appendChild(this._scrollbarDecorationNode);
|
||||
this._scrollbarDecorationCanvas = this._scrollbarDecorationNode.getContext('2d');
|
||||
}
|
||||
this._registerScrollbarDecoration(decorationOptions.marker, decorationOptions.scrollbarDecorationColor);
|
||||
}
|
||||
const decoration = this._instantiationService.createInstance(Decoration, decorationOptions, this._container);
|
||||
this._decorations.push(decoration);
|
||||
decoration.onDispose(() => this._decorations.splice(this._decorations.indexOf(decoration), 1));
|
||||
@@ -57,6 +72,7 @@ export class DecorationService extends Disposable implements IDecorationService
|
||||
for (const decoration of this._decorations) {
|
||||
decoration.render(this._renderService, shouldRecreate);
|
||||
}
|
||||
this._refreshScollbarDecorations();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -67,6 +83,41 @@ export class DecorationService extends Disposable implements IDecorationService
|
||||
this._screenElement.removeChild(this._container);
|
||||
}
|
||||
}
|
||||
|
||||
private _registerScrollbarDecoration(marker: IMarker, color?: string): HTMLCanvasElement | undefined {
|
||||
this._scrollbarDecorations.push({ marker, color });
|
||||
if (!this._scrollbarDecorationCanvas) {
|
||||
return;
|
||||
}
|
||||
this._addScrollbarDecoration(marker, color);
|
||||
}
|
||||
|
||||
private _refreshScollbarDecorations(): void {
|
||||
if (!this._scrollbarDecorationCanvas) {
|
||||
return;
|
||||
}
|
||||
if (this._scrollbarDecorationNode) {
|
||||
this._scrollbarDecorationNode.style.width = '7px';
|
||||
this._scrollbarDecorationNode.style.height = `${this._screenElement?.parentElement!.clientHeight}px`;
|
||||
this._scrollbarDecorationNode.width = Math.floor(7*window.devicePixelRatio);
|
||||
this._scrollbarDecorationNode.height = Math.floor(436*window.devicePixelRatio);
|
||||
}
|
||||
this._scrollbarDecorationCanvas.clearRect(0, 0, this._scrollbarDecorationCanvas.canvas.width, this._scrollbarDecorationCanvas.canvas.height);
|
||||
for (const scrollbarDecoration of this._scrollbarDecorations) {
|
||||
this._addScrollbarDecoration(scrollbarDecoration.marker, scrollbarDecoration.color);
|
||||
}
|
||||
}
|
||||
|
||||
private _addScrollbarDecoration(marker: IMarker, color?: string): void {
|
||||
if (!this._scrollbarDecorationCanvas || !this._screenElement?.parentElement?.clientHeight) {
|
||||
return;
|
||||
}
|
||||
this._scrollbarDecorationCanvas.lineWidth = 1;
|
||||
if (color) {
|
||||
this._scrollbarDecorationCanvas.strokeStyle = color;
|
||||
}
|
||||
this._scrollbarDecorationCanvas.strokeRect(0, (marker.line / (this._bufferService.buffers.active.lines.length) * Math.floor(436*window.devicePixelRatio)), Math.floor(7*window.devicePixelRatio), window.devicePixelRatio);
|
||||
}
|
||||
}
|
||||
export class Decoration extends Disposable implements IDecoration {
|
||||
private readonly _marker: IMarker;
|
||||
|
||||
Vendored
+6
@@ -470,6 +470,12 @@ declare module 'xterm' {
|
||||
* cell height
|
||||
*/
|
||||
height?: number;
|
||||
|
||||
/**
|
||||
* When provided, renders the decoration in the scrollbar
|
||||
* with the given color
|
||||
*/
|
||||
scrollbarDecorationColor?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user