Add terminal and addon refs to all windows
This commit is contained in:
+6
-6
@@ -206,21 +206,21 @@ if (document.location.pathname === '/test') {
|
|||||||
const typedTerm = createTerminal();
|
const typedTerm = createTerminal();
|
||||||
|
|
||||||
controlBar = new ControlBar(document.getElementById('sidebar'), document.querySelector('.banner-tabs'), []);
|
controlBar = new ControlBar(document.getElementById('sidebar'), document.querySelector('.banner-tabs'), []);
|
||||||
addonsWindow = new AddonsWindow();
|
addonsWindow = new AddonsWindow(typedTerm, addons);
|
||||||
controlBar.registerWindow(addonsWindow);
|
controlBar.registerWindow(addonsWindow);
|
||||||
actionElements = {
|
actionElements = {
|
||||||
findNext: addonsWindow.findNextInput,
|
findNext: addonsWindow.findNextInput,
|
||||||
findPrevious: addonsWindow.findPreviousInput,
|
findPrevious: addonsWindow.findPreviousInput,
|
||||||
findResults: addonsWindow.findResultsSpan
|
findResults: addonsWindow.findResultsSpan
|
||||||
};
|
};
|
||||||
gpuWindow = new GpuWindow();
|
gpuWindow = new GpuWindow(typedTerm, addons);
|
||||||
controlBar.registerWindow(gpuWindow, { afterId: 'addons', hidden: true, smallTab: true });
|
controlBar.registerWindow(gpuWindow, { afterId: 'addons', hidden: true, smallTab: true });
|
||||||
optionsWindow = new OptionsWindow(updateTerminalSize, updateTerminalContainerBackground);
|
optionsWindow = new OptionsWindow(typedTerm, addons, { updateTerminalSize, updateTerminalContainerBackground });
|
||||||
const styleWindow = controlBar.registerWindow(new StyleWindow());
|
const styleWindow = controlBar.registerWindow(new StyleWindow(typedTerm, addons));
|
||||||
paddingElement = styleWindow.paddingElement;
|
paddingElement = styleWindow.paddingElement;
|
||||||
controlBar.registerWindow(optionsWindow);
|
controlBar.registerWindow(optionsWindow);
|
||||||
controlBar.registerWindow(new TestWindow(typedTerm, addons, { disposeRecreateButtonHandler, createNewWindowButtonHandler }));
|
controlBar.registerWindow(new TestWindow(typedTerm, addons, { disposeRecreateButtonHandler, createNewWindowButtonHandler }));
|
||||||
vtWindow = new VtWindow();
|
vtWindow = new VtWindow(typedTerm, addons);
|
||||||
controlBar.registerWindow(vtWindow);
|
controlBar.registerWindow(vtWindow);
|
||||||
vtWindow.initTerminal(term);
|
vtWindow.initTerminal(term);
|
||||||
controlBar.activateDefaultTab();
|
controlBar.activateDefaultTab();
|
||||||
@@ -351,7 +351,7 @@ function createTerminal(): Terminal {
|
|||||||
|
|
||||||
// fit is called within a setTimeout, cols and rows need this.
|
// fit is called within a setTimeout, cols and rows need this.
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
optionsWindow.initOptions(term, addDomListener);
|
optionsWindow.initOptions(addDomListener);
|
||||||
|
|
||||||
// Set terminal size again to set the specific dimensions on the demo
|
// Set terminal size again to set the specific dimensions on the demo
|
||||||
updateTerminalSize();
|
updateTerminalSize();
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// <reference path="../../typings/xterm.d.ts"/>
|
||||||
|
|
||||||
|
import type { Terminal } from '@xterm/xterm';
|
||||||
|
import type { AddonCollection } from 'types';
|
||||||
|
|
||||||
export interface ITabConfig {
|
export interface ITabConfig {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
@@ -12,6 +17,7 @@ export interface IControlWindow {
|
|||||||
readonly id: string;
|
readonly id: string;
|
||||||
readonly label: string;
|
readonly label: string;
|
||||||
build(container: HTMLElement): void;
|
build(container: HTMLElement): void;
|
||||||
|
setTerminal(terminal: Terminal): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ControlBar {
|
export class ControlBar {
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Terminal } from '@xterm/xterm';
|
import { BaseWindow } from './baseWindow';
|
||||||
import type { IControlWindow } from '../controlBar';
|
import type { IControlWindow } from '../controlBar';
|
||||||
|
|
||||||
export class AddonsWindow implements IControlWindow {
|
export class AddonsWindow extends BaseWindow implements IControlWindow {
|
||||||
public readonly id = 'addons';
|
public readonly id = 'addons';
|
||||||
public readonly label = 'Addons';
|
public readonly label = 'Addons';
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 The xterm.js authors. All rights reserved.
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <reference path="../../../typings/xterm.d.ts"/>
|
||||||
|
|
||||||
|
import type { AddonCollection } from '../../types';
|
||||||
|
import type { IControlWindow } from '../controlBar';
|
||||||
|
import type { Terminal } from '@xterm/xterm';
|
||||||
|
|
||||||
|
export abstract class BaseWindow implements IControlWindow {
|
||||||
|
protected get _terminal(): Terminal { return this.__terminal; }
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private __terminal: Terminal,
|
||||||
|
protected readonly _addons: AddonCollection,
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setTerminal(terminal: Terminal): void {
|
||||||
|
this.__terminal = terminal;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract id: string;
|
||||||
|
abstract label: string;
|
||||||
|
abstract build(container: HTMLElement): void;
|
||||||
|
}
|
||||||
@@ -3,9 +3,10 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { BaseWindow } from './baseWindow';
|
||||||
import type { IControlWindow } from '../controlBar';
|
import type { IControlWindow } from '../controlBar';
|
||||||
|
|
||||||
export class GpuWindow implements IControlWindow {
|
export class GpuWindow extends BaseWindow implements IControlWindow {
|
||||||
public readonly id = 'gpu';
|
public readonly id = 'gpu';
|
||||||
public readonly label = 'GPU';
|
public readonly label = 'GPU';
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { BaseWindow } from './baseWindow';
|
||||||
import type { Terminal, ITheme } from '@xterm/xterm';
|
import type { Terminal, ITheme } from '@xterm/xterm';
|
||||||
import type { IControlWindow } from '../controlBar';
|
import type { IControlWindow } from '../controlBar';
|
||||||
|
import type { AddonCollection } from 'types';
|
||||||
|
|
||||||
const xtermjsTheme: ITheme = {
|
const xtermjsTheme: ITheme = {
|
||||||
foreground: '#F8F8F8',
|
foreground: '#F8F8F8',
|
||||||
@@ -29,23 +31,23 @@ const xtermjsTheme: ITheme = {
|
|||||||
brightWhite: '#FFFFFF'
|
brightWhite: '#FFFFFF'
|
||||||
};
|
};
|
||||||
|
|
||||||
export class OptionsWindow implements IControlWindow {
|
export class OptionsWindow extends BaseWindow implements IControlWindow {
|
||||||
public readonly id = 'options';
|
public readonly id = 'options';
|
||||||
public readonly label = 'Options';
|
public readonly label = 'Options';
|
||||||
|
|
||||||
private _container: HTMLElement;
|
private _container: HTMLElement;
|
||||||
private _optionsContainer: HTMLElement;
|
private _optionsContainer: HTMLElement;
|
||||||
private _term: Terminal;
|
|
||||||
private _autoResize: boolean = true;
|
private _autoResize: boolean = true;
|
||||||
private _updateTerminalSize: () => void;
|
|
||||||
private _updateTerminalContainerBackground: () => void;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
updateTerminalSize: () => void,
|
terminal: Terminal,
|
||||||
updateTerminalContainerBackground: () => void
|
addons: AddonCollection,
|
||||||
|
private readonly _handlers: {
|
||||||
|
updateTerminalSize: () => void,
|
||||||
|
updateTerminalContainerBackground: () => void
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
this._updateTerminalSize = updateTerminalSize;
|
super(terminal, addons)
|
||||||
this._updateTerminalContainerBackground = updateTerminalContainerBackground;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public build(container: HTMLElement): void {
|
public build(container: HTMLElement): void {
|
||||||
@@ -64,9 +66,7 @@ export class OptionsWindow implements IControlWindow {
|
|||||||
container.appendChild(this._optionsContainer);
|
container.appendChild(this._optionsContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public initOptions(term: Terminal, addDomListener: (el: HTMLElement, type: string, handler: (...args: any[]) => any) => void): void {
|
public initOptions(addDomListener: (el: HTMLElement, type: string, handler: (...args: any[]) => any) => void): void {
|
||||||
this._term = term;
|
|
||||||
|
|
||||||
const blacklistedOptions = [
|
const blacklistedOptions = [
|
||||||
'cancelEvents',
|
'cancelEvents',
|
||||||
'convertEol',
|
'convertEol',
|
||||||
@@ -91,11 +91,11 @@ export class OptionsWindow implements IControlWindow {
|
|||||||
wordSeparator: null,
|
wordSeparator: null,
|
||||||
colsRows: null
|
colsRows: null
|
||||||
};
|
};
|
||||||
const options = Object.getOwnPropertyNames(term.options);
|
const options = Object.getOwnPropertyNames(this._terminal.options);
|
||||||
const booleanOptions: string[] = [];
|
const booleanOptions: string[] = [];
|
||||||
const numberOptions: string[] = [];
|
const numberOptions: string[] = [];
|
||||||
options.filter(o => blacklistedOptions.indexOf(o) === -1).forEach(o => {
|
options.filter(o => blacklistedOptions.indexOf(o) === -1).forEach(o => {
|
||||||
switch (typeof term.options[o]) {
|
switch (typeof this._terminal.options[o]) {
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
booleanOptions.push(o);
|
booleanOptions.push(o);
|
||||||
break;
|
break;
|
||||||
@@ -112,21 +112,21 @@ export class OptionsWindow implements IControlWindow {
|
|||||||
let html = '';
|
let html = '';
|
||||||
html += '<div class="option-group">';
|
html += '<div class="option-group">';
|
||||||
booleanOptions.forEach(o => {
|
booleanOptions.forEach(o => {
|
||||||
html += `<div class="option"><label><input id="opt-${o}" type="checkbox" ${term.options[o] ? 'checked' : ''}/> ${o}</label></div>`;
|
html += `<div class="option"><label><input id="opt-${o}" type="checkbox" ${this._terminal.options[o] ? 'checked' : ''}/> ${o}</label></div>`;
|
||||||
});
|
});
|
||||||
html += '</div><div class="option-group">';
|
html += '</div><div class="option-group">';
|
||||||
numberOptions.forEach(o => {
|
numberOptions.forEach(o => {
|
||||||
html += `<div class="option"><label>${o} <input id="opt-${o}" type="number" value="${term.options[o] ?? ''}" step="${o === 'lineHeight' || o === 'scrollSensitivity' ? '0.1' : '1'}"/></label></div>`;
|
html += `<div class="option"><label>${o} <input id="opt-${o}" type="number" value="${this._terminal.options[o] ?? ''}" step="${o === 'lineHeight' || o === 'scrollSensitivity' ? '0.1' : '1'}"/></label></div>`;
|
||||||
});
|
});
|
||||||
html += '</div><div class="option-group">';
|
html += '</div><div class="option-group">';
|
||||||
Object.keys(stringOptions).forEach(o => {
|
Object.keys(stringOptions).forEach(o => {
|
||||||
if (o === 'colsRows') {
|
if (o === 'colsRows') {
|
||||||
html += `<div class="option"><label>size (<var>cols</var><code>x</code><var>rows</var> or <code>auto</code>) <input id="opt-${o}" type="text" value="auto"/></label></div>`;
|
html += `<div class="option"><label>size (<var>cols</var><code>x</code><var>rows</var> or <code>auto</code>) <input id="opt-${o}" type="text" value="auto"/></label></div>`;
|
||||||
} else if (stringOptions[o]) {
|
} else if (stringOptions[o]) {
|
||||||
const selectedOption = o === 'theme' ? 'xtermjs' : term.options[o];
|
const selectedOption = o === 'theme' ? 'xtermjs' : this._terminal.options[o];
|
||||||
html += `<div class="option"><label>${o} <select id="opt-${o}">${stringOptions[o]!.map(v => `<option ${v === selectedOption ? 'selected' : ''}>${v}</option>`).join('')}</select></label></div>`;
|
html += `<div class="option"><label>${o} <select id="opt-${o}">${stringOptions[o]!.map(v => `<option ${v === selectedOption ? 'selected' : ''}>${v}</option>`).join('')}</select></label></div>`;
|
||||||
} else {
|
} else {
|
||||||
html += `<div class="option"><label>${o} <input id="opt-${o}" type="text" value="${term.options[o]}"/></label></div>`;
|
html += `<div class="option"><label>${o} <input id="opt-${o}" type="text" value="${this._terminal.options[o]}"/></label></div>`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
@@ -138,7 +138,7 @@ export class OptionsWindow implements IControlWindow {
|
|||||||
const input = document.getElementById(`opt-${o}`) as HTMLInputElement;
|
const input = document.getElementById(`opt-${o}`) as HTMLInputElement;
|
||||||
addDomListener(input, 'change', () => {
|
addDomListener(input, 'change', () => {
|
||||||
console.log('change', o, input.checked);
|
console.log('change', o, input.checked);
|
||||||
term.options[o] = input.checked;
|
this._terminal.options[o] = input.checked;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
numberOptions.forEach(o => {
|
numberOptions.forEach(o => {
|
||||||
@@ -146,16 +146,16 @@ export class OptionsWindow implements IControlWindow {
|
|||||||
addDomListener(input, 'change', () => {
|
addDomListener(input, 'change', () => {
|
||||||
console.log('change', o, input.value);
|
console.log('change', o, input.value);
|
||||||
if (o === 'lineHeight') {
|
if (o === 'lineHeight') {
|
||||||
term.options.lineHeight = parseFloat(input.value);
|
this._terminal.options.lineHeight = parseFloat(input.value);
|
||||||
} else if (o === 'scrollSensitivity') {
|
} else if (o === 'scrollSensitivity') {
|
||||||
term.options.scrollSensitivity = parseFloat(input.value);
|
this._terminal.options.scrollSensitivity = parseFloat(input.value);
|
||||||
} else if (o === 'scrollback') {
|
} else if (o === 'scrollback') {
|
||||||
term.options.scrollback = parseInt(input.value);
|
this._terminal.options.scrollback = parseInt(input.value);
|
||||||
setTimeout(() => this._updateTerminalSize(), 5);
|
setTimeout(() => this._handlers.updateTerminalSize(), 5);
|
||||||
} else {
|
} else {
|
||||||
term.options[o] = parseInt(input.value);
|
this._terminal.options[o] = parseInt(input.value);
|
||||||
}
|
}
|
||||||
this._updateTerminalSize();
|
this._handlers.updateTerminalSize();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Object.keys(stringOptions).forEach(o => {
|
Object.keys(stringOptions).forEach(o => {
|
||||||
@@ -167,11 +167,11 @@ export class OptionsWindow implements IControlWindow {
|
|||||||
const m = input.value.match(/^([0-9]+)x([0-9]+)$/);
|
const m = input.value.match(/^([0-9]+)x([0-9]+)$/);
|
||||||
if (m) {
|
if (m) {
|
||||||
this._autoResize = false;
|
this._autoResize = false;
|
||||||
term.resize(parseInt(m[1]), parseInt(m[2]));
|
this._terminal.resize(parseInt(m[1]), parseInt(m[2]));
|
||||||
} else {
|
} else {
|
||||||
this._autoResize = true;
|
this._autoResize = true;
|
||||||
input.value = 'auto';
|
input.value = 'auto';
|
||||||
this._updateTerminalSize();
|
this._handlers.updateTerminalSize();
|
||||||
}
|
}
|
||||||
} else if (o === 'theme') {
|
} else if (o === 'theme') {
|
||||||
switch (input.value) {
|
switch (input.value) {
|
||||||
@@ -232,9 +232,9 @@ export class OptionsWindow implements IControlWindow {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
term.options[o] = value;
|
this._terminal.options[o] = value;
|
||||||
if (o === 'theme') {
|
if (o === 'theme') {
|
||||||
this._updateTerminalContainerBackground();
|
this._handlers.updateTerminalContainerBackground();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { BaseWindow } from './baseWindow';
|
||||||
import type { IControlWindow } from '../controlBar';
|
import type { IControlWindow } from '../controlBar';
|
||||||
|
|
||||||
export class StyleWindow implements IControlWindow {
|
export class StyleWindow extends BaseWindow implements IControlWindow {
|
||||||
public readonly id = 'style';
|
public readonly id = 'style';
|
||||||
public readonly label = 'Style';
|
public readonly label = 'Style';
|
||||||
|
|
||||||
|
|||||||
@@ -7,21 +7,23 @@
|
|||||||
|
|
||||||
import { writeUnicodeTable } from 'unicodeTable';
|
import { writeUnicodeTable } from 'unicodeTable';
|
||||||
import type { IControlWindow } from '../controlBar';
|
import type { IControlWindow } from '../controlBar';
|
||||||
|
import { BaseWindow } from './baseWindow';
|
||||||
import type { IDisposable, Terminal } from '@xterm/xterm';
|
import type { IDisposable, Terminal } from '@xterm/xterm';
|
||||||
import type { AddonCollection } from 'types';
|
import type { AddonCollection } from 'types';
|
||||||
|
|
||||||
export class TestWindow implements IControlWindow {
|
export class TestWindow extends BaseWindow implements IControlWindow {
|
||||||
public readonly id = 'test';
|
public readonly id = 'test';
|
||||||
public readonly label = 'Test';
|
public readonly label = 'Test';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _terminal: Terminal,
|
terminal: Terminal,
|
||||||
private readonly _addons: AddonCollection,
|
addons: AddonCollection,
|
||||||
private readonly _handlers: {
|
private readonly _handlers: {
|
||||||
disposeRecreateButtonHandler: () => void,
|
disposeRecreateButtonHandler: () => void,
|
||||||
createNewWindowButtonHandler: () => void,
|
createNewWindowButtonHandler: () => void,
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
|
super(terminal, addons);
|
||||||
}
|
}
|
||||||
|
|
||||||
public build(container: HTMLElement): void {
|
public build(container: HTMLElement): void {
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { BaseWindow } from './baseWindow';
|
||||||
import type { IControlWindow } from '../controlBar';
|
import type { IControlWindow } from '../controlBar';
|
||||||
import type { Terminal } from '@xterm/xterm';
|
import type { Terminal } from '@xterm/xterm';
|
||||||
|
|
||||||
export class VtWindow implements IControlWindow {
|
export class VtWindow extends BaseWindow implements IControlWindow {
|
||||||
public readonly id = 'vt';
|
public readonly id = 'vt';
|
||||||
public readonly label = 'VT';
|
public readonly label = 'VT';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user