diff --git a/src/Terminal.ts b/src/Terminal.ts index a6633235..13f38860 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -761,10 +761,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure); this.renderer = new Renderer(this); - this.on('cursormove', () => { - console.log('cursormove fired'); - this.renderer.onCursorMove(); - }); + this.on('cursormove', () => this.renderer.onCursorMove()); this.on('resize', () => this.renderer.onResize(this.cols, this.rows)); this.charMeasure.on('charsizechanged', () => { this.renderer.onCharSizeChanged(this.charMeasure.width, this.charMeasure.height); diff --git a/src/renderer/BackgroundRenderLayer.ts b/src/renderer/BackgroundRenderLayer.ts index cf122cc2..271dc2ac 100644 --- a/src/renderer/BackgroundRenderLayer.ts +++ b/src/renderer/BackgroundRenderLayer.ts @@ -1,11 +1,11 @@ -import { IDataRenderLayer, IColorSet } from './Interfaces'; +import { IColorSet } from './Interfaces'; import { IBuffer, ICharMeasure, ITerminal } from '../Interfaces'; import { CHAR_DATA_ATTR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; import { FLAGS } from './Types'; import { BaseRenderLayer } from './BaseRenderLayer'; -export class BackgroundRenderLayer extends BaseRenderLayer implements IDataRenderLayer { +export class BackgroundRenderLayer extends BaseRenderLayer { private _state: GridCache; constructor(container: HTMLElement, zIndex: number, colors: IColorSet) { @@ -23,7 +23,7 @@ export class BackgroundRenderLayer extends BaseRenderLayer implements IDataRende this.clearAll(); } - public render(terminal: ITerminal, startRow: number, endRow: number): void { + public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void { for (let y = startRow; y <= endRow; y++) { let row = y + terminal.buffer.ydisp; let line = terminal.buffer.lines.get(row); diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index e996a2a8..20425e41 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -29,6 +29,8 @@ export abstract class BaseRenderLayer implements IRenderLayer { // TODO: Should this do anything? public onOptionsChanged(terminal: ITerminal): void {} public onCursorMove(terminal: ITerminal): void {} + public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void {} + public onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number]): void {} public onThemeChanged(terminal: ITerminal, colorSet: IColorSet): void { this._charAtlas = null; diff --git a/src/renderer/CursorRenderLayer.ts b/src/renderer/CursorRenderLayer.ts index bfec1d8e..1e5cf647 100644 --- a/src/renderer/CursorRenderLayer.ts +++ b/src/renderer/CursorRenderLayer.ts @@ -1,4 +1,4 @@ -import { IDataRenderLayer, IColorSet } from './Interfaces'; +import { IColorSet } from './Interfaces'; import { IBuffer, ICharMeasure, ITerminal, ITerminalOptions } from '../Interfaces'; import { CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; @@ -12,7 +12,7 @@ import { COLOR_CODES } from './ColorManager'; */ const BLINK_INTERVAL = 600; -export class CursorRenderLayer extends BaseRenderLayer implements IDataRenderLayer { +export class CursorRenderLayer extends BaseRenderLayer { private _state: [number, number]; private _cursorRenderers: {[key: string]: (terminal: ITerminal, x: number, y: number, charData: CharData) => void}; private _cursorBlinkStateManager: CursorBlinkStateManager; @@ -62,7 +62,7 @@ export class CursorRenderLayer extends BaseRenderLayer implements IDataRenderLay } } - public render(terminal: ITerminal, startRow: number, endRow: number): void { + public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void { // Only render if the animation frame is not active if (!this._cursorBlinkStateManager) { this._render(terminal, false); diff --git a/src/renderer/ForegroundRenderLayer.ts b/src/renderer/ForegroundRenderLayer.ts index fa4ef800..5a1d41f6 100644 --- a/src/renderer/ForegroundRenderLayer.ts +++ b/src/renderer/ForegroundRenderLayer.ts @@ -1,4 +1,4 @@ -import { IDataRenderLayer, IColorSet } from './Interfaces'; +import { IColorSet } from './Interfaces'; import { IBuffer, ICharMeasure, ITerminal } from '../Interfaces'; import { CHAR_DATA_ATTR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from '../Buffer'; import { FLAGS } from './Types'; @@ -6,7 +6,7 @@ import { GridCache } from './GridCache'; import { CharData } from '../Types'; import { BaseRenderLayer } from './BaseRenderLayer'; -export class ForegroundRenderLayer extends BaseRenderLayer implements IDataRenderLayer { +export class ForegroundRenderLayer extends BaseRenderLayer { private _state: GridCache; constructor(container: HTMLElement, zIndex: number, colors: IColorSet) { @@ -24,7 +24,7 @@ export class ForegroundRenderLayer extends BaseRenderLayer implements IDataRende this.clearAll(); } - public render(terminal: ITerminal, startRow: number, endRow: number): void { + public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void { // TODO: Ensure that the render is eventually performed // Don't bother render until the atlas bitmap is ready // TODO: Move this to BaseRenderLayer? diff --git a/src/renderer/Interfaces.ts b/src/renderer/Interfaces.ts index 4b8ce816..5626f13d 100644 --- a/src/renderer/Interfaces.ts +++ b/src/renderer/Interfaces.ts @@ -4,6 +4,8 @@ export interface IRenderLayer { onCursorMove(terminal: ITerminal): void; onOptionsChanged(terminal: ITerminal): void; onThemeChanged(terminal: ITerminal, colorSet: IColorSet): void; + onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void; + onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number]): void; /** * Resize the render layer. @@ -16,20 +18,6 @@ export interface IRenderLayer { reset(terminal: ITerminal): void; } -/** - * A render layer that renders when there is a data change. - */ -export interface IDataRenderLayer extends IRenderLayer { - render(terminal: ITerminal, startRow: number, endRow: number): void; -} - -/** - * A render layer that renders when there is a selection change. - */ -export interface ISelectionRenderLayer extends IRenderLayer { - render(terminal: ITerminal, start: [number, number], end: [number, number]): void; -} - export interface IColorSet { foreground: string; diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index 653e2cba..96e899f6 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -6,48 +6,41 @@ import { ITerminal, ITheme } from '../Interfaces'; import { DomElementObjectPool } from '../utils/DomElementObjectPool'; import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; import { createBackgroundFillData } from './Canvas'; -import { IDataRenderLayer, ISelectionRenderLayer } from './Interfaces'; import { BackgroundRenderLayer } from './BackgroundRenderLayer'; import { ForegroundRenderLayer } from './ForegroundRenderLayer'; import { SelectionRenderLayer } from './SelectionRenderLayer'; import { CursorRenderLayer } from './CursorRenderLayer'; import { ColorManager } from './ColorManager'; import { BaseRenderLayer } from './BaseRenderLayer'; +import { IRenderLayer } from './Interfaces'; export class Renderer { /** A queue of the rows to be refreshed */ private _refreshRowsQueue: {start: number, end: number}[] = []; private _refreshAnimationFrame = null; - private _dataRenderLayers: IDataRenderLayer[]; - private _selectionRenderLayers: ISelectionRenderLayer[]; + private _renderLayers: IRenderLayer[]; private _colorManager: ColorManager; constructor(private _terminal: ITerminal) { this._colorManager = new ColorManager(); - this._dataRenderLayers = [ + this._renderLayers = [ new BackgroundRenderLayer(this._terminal.element, 0, this._colorManager.colors), + new SelectionRenderLayer(this._terminal.element, 1, this._colorManager.colors), new ForegroundRenderLayer(this._terminal.element, 2, this._colorManager.colors), new CursorRenderLayer(this._terminal.element, 3, this._colorManager.colors) ]; - this._selectionRenderLayers = [ - new SelectionRenderLayer(this._terminal.element, 1, this._colorManager.colors) - ]; } public setTheme(theme: ITheme): void { console.log('setTheme'); this._colorManager.setTheme(theme); // Clear layers and force a full render - for (let i = 0; i < this._dataRenderLayers.length; i++) { - this._dataRenderLayers[i].onThemeChanged(this._terminal, this._colorManager.colors); - this._dataRenderLayers[i].reset(this._terminal); - } - for (let i = 0; i < this._selectionRenderLayers.length; i++) { - this._selectionRenderLayers[i].onThemeChanged(this._terminal, this._colorManager.colors); - this._selectionRenderLayers[i].reset(this._terminal); - } + this._renderLayers.forEach(l => { + l.onThemeChanged(this._terminal, this._colorManager.colors); + l.reset(this._terminal); + }); // TODO: This is currently done for every single terminal, but it's static so it's wasting time this._terminal.refresh(0, this._terminal.rows - 1); @@ -56,53 +49,29 @@ export class Renderer { public onResize(cols: number, rows: number): void { const width = this._terminal.charMeasure.width * this._terminal.cols; const height = this._terminal.charMeasure.height * this._terminal.rows; - for (let i = 0; i < this._dataRenderLayers.length; i++) { - this._dataRenderLayers[i].resize(this._terminal, width, height, false); - } + this._renderLayers.forEach(l => l.resize(this._terminal, width, height, false)); } public onCharSizeChanged(charWidth: number, charHeight: number): void { const width = charWidth * this._terminal.cols; const height = charHeight * this._terminal.rows; - for (let i = 0; i < this._dataRenderLayers.length; i++) { - this._dataRenderLayers[i].resize(this._terminal, width, height, true); - } - for (let i = 0; i < this._selectionRenderLayers.length; i++) { - this._selectionRenderLayers[i].resize(this._terminal, width, height, true); - } + this._renderLayers.forEach(l => l.resize(this._terminal, width, height, true)); } public onSelectionChanged(start: [number, number], end: [number, number]): void { - for (let i = 0; i < this._selectionRenderLayers.length; i++) { - this._selectionRenderLayers[i].render(this._terminal, start, end); - } + this._renderLayers.forEach(l => l.onSelectionChanged(this._terminal, start, end)); } public onCursorMove(): void { - for (let i = 0; i < this._dataRenderLayers.length; i++) { - this._dataRenderLayers[i].onCursorMove(this._terminal); - } - for (let i = 0; i < this._selectionRenderLayers.length; i++) { - this._selectionRenderLayers[i].onCursorMove(this._terminal); - } + this._renderLayers.forEach(l => l.onCursorMove(this._terminal)); } public onOptionsChanged(): void { - for (let i = 0; i < this._dataRenderLayers.length; i++) { - this._dataRenderLayers[i].onOptionsChanged(this._terminal); - } - for (let i = 0; i < this._selectionRenderLayers.length; i++) { - this._selectionRenderLayers[i].onOptionsChanged(this._terminal); - } + this._renderLayers.forEach(l => l.onOptionsChanged(this._terminal)); } public clear(): void { - for (let i = 0; i < this._dataRenderLayers.length; i++) { - this._dataRenderLayers[i].reset(this._terminal); - } - for (let i = 0; i < this._selectionRenderLayers.length; i++) { - this._selectionRenderLayers[i].reset(this._terminal); - } + this._renderLayers.forEach(l => l.reset(this._terminal)); } /** @@ -146,9 +115,7 @@ export class Renderer { this._refreshAnimationFrame = null; // Render - for (let i = 0; i < this._dataRenderLayers.length; i++) { - this._dataRenderLayers[i].render(this._terminal, start, end); - } + this._renderLayers.forEach(l => l.onGridChanged(this._terminal, start, end)); this._terminal.emit('refresh', {start, end}); } } diff --git a/src/renderer/SelectionRenderLayer.ts b/src/renderer/SelectionRenderLayer.ts index 4ec96764..1dcb8ab6 100644 --- a/src/renderer/SelectionRenderLayer.ts +++ b/src/renderer/SelectionRenderLayer.ts @@ -1,11 +1,11 @@ -import { ISelectionRenderLayer, IColorSet } from './Interfaces'; +import { IColorSet } from './Interfaces'; import { IBuffer, ICharMeasure, ITerminal } from '../Interfaces'; import { CHAR_DATA_ATTR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; import { FLAGS } from './Types'; import { BaseRenderLayer } from './BaseRenderLayer'; -export class SelectionRenderLayer extends BaseRenderLayer implements ISelectionRenderLayer { +export class SelectionRenderLayer extends BaseRenderLayer { private _state: {start: [number, number], end: [number, number]}; constructor(container: HTMLElement, zIndex: number, colors: IColorSet) { @@ -26,7 +26,7 @@ export class SelectionRenderLayer extends BaseRenderLayer implements ISelectionR } } - public render(terminal: ITerminal, start: [number, number], end: [number, number]): void { + public onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number]): void { // Selection has not changed if (this._state.start === start || this._state.end === end) { return;