terminalPanel.ts 5.5 KB
Newer Older
D
Daniel Imms 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

6
import lifecycle = require('vs/base/common/lifecycle');
7
import platform = require('vs/base/common/platform');
8
import DOM = require('vs/base/browser/dom');
D
Daniel Imms 已提交
9 10
import {TPromise} from 'vs/base/common/winjs.base';
import {Builder, Dimension} from 'vs/base/browser/builder';
11
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
D
Daniel Imms 已提交
12
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
13
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
14
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
15
import {ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/electron-browser/terminal';
D
Daniel Imms 已提交
16
import {Panel} from 'vs/workbench/browser/panel';
17 18
import {TerminalConfigHelper} from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper';
import {TerminalInstance} from 'vs/workbench/parts/terminal/electron-browser/terminalInstance';
D
Daniel Imms 已提交
19 20 21

export class TerminalPanel extends Panel {

22
	private toDispose: lifecycle.IDisposable[];
D
Daniel Imms 已提交
23
	private parentDomElement: HTMLElement;
24
	private themeStyleElement: HTMLElement;
25
	private configurationHelper: TerminalConfigHelper;
26
	private terminalInstance: TerminalInstance;
D
Daniel Imms 已提交
27 28

	constructor(
29
		@IConfigurationService private configurationService: IConfigurationService,
30
		@ITelemetryService telemetryService: ITelemetryService,
31
		@IWorkspaceContextService private contextService: IWorkspaceContextService,
32 33
		@ITerminalService private terminalService: ITerminalService,
		@IThemeService private themeService: IThemeService
D
Daniel Imms 已提交
34 35
	) {
		super(TERMINAL_PANEL_ID, telemetryService);
36
		this.toDispose = [];
D
Daniel Imms 已提交
37 38
	}

39 40 41
	public layout(dimension?: Dimension): void {
		if (this.terminalInstance) {
			this.terminalInstance.layout(dimension);
42
		}
D
Daniel Imms 已提交
43 44 45 46
	}

	public create(parent: Builder): TPromise<void> {
		super.create(parent);
47
		this.parentDomElement = parent.getHTMLElement();
48 49
		this.themeStyleElement = document.createElement('style');
		this.parentDomElement.appendChild(this.themeStyleElement);
50
		this.configurationHelper = new TerminalConfigHelper(platform.platform, this.configurationService, this.parentDomElement);
51 52 53
		this.toDispose.push(DOM.addDisposableListener(this.parentDomElement, 'wheel', (event: WheelEvent) => {
			this.terminalInstance.dispatchEvent(new WheelEvent(event.type, event));
		}));
54

55
		return this.createTerminal();
56 57
	}

58
	public setVisible(visible: boolean): TPromise<void> {
59 60 61 62 63 64 65 66 67 68 69 70
		if (visible) {
			if (this.terminalInstance) {
				this.updateFont();
				this.updateTheme();
			} else {
				return super.setVisible(visible).then(() => {
					this.createTerminal();
					this.updateFont();
					this.updateTheme();
					return Promise.resolve(void 0);
				});
			}
71 72 73 74
		}
		return super.setVisible(visible);
	}

75 76
	private createTerminal(): TPromise<void> {
		return new TPromise<void>(resolve => {
77 78 79
			this.terminalInstance = new TerminalInstance(this.configurationHelper.getShell(), this.parentDomElement, this.contextService, this.terminalService, this.onTerminalInstanceExit.bind(this));
			this.toDispose.push(this.themeService.onDidThemeChange(this.updateTheme.bind(this)));
			this.toDispose.push(this.configurationService.onDidUpdateConfiguration(this.updateFont.bind(this)));
80
			resolve(void 0);
D
Daniel Imms 已提交
81 82
		});
	}
83

84 85 86 87 88 89 90 91 92
	private onTerminalInstanceExit(terminalInstance: TerminalInstance): void {
		if (this.terminalInstance === terminalInstance) {
			this.terminalInstance = null;
		}
		this.terminalService.toggle();
	}

	private updateTheme(themeId?: string): void {
		if (!this.terminalInstance) {
93 94
			return;
		}
95 96 97
		if (!themeId) {
			themeId = this.themeService.getTheme();
		}
D
Daniel Imms 已提交
98 99 100 101
		let theme = this.configurationHelper.getTheme(themeId);

		let css = '';
		theme.forEach((color: string, index: number) => {
102
			// TODO: The classes could probably be reduced, it's so long to beat the specificity of the general rule.
D
Daniel Imms 已提交
103
			let rgba = this.convertHexCssColorToRgba(color, 0.996);
104 105 106 107
			css += `.monaco-workbench .integrated-terminal .terminal .xterm-color-${index} { color: ${color}; }` +
				`.monaco-workbench .integrated-terminal .terminal .xterm-color-${index}::selection { background-color: ${rgba}; }` +
				`.monaco-workbench .integrated-terminal .terminal .xterm-bg-color-${index} { background-color: ${color}; }` +
				`.monaco-workbench .integrated-terminal .terminal .xterm-bg-color-${index}::selection { color: ${color}; }`;
D
Daniel Imms 已提交
108 109
		});

110
		this.themeStyleElement.innerHTML = css;
D
Daniel Imms 已提交
111 112
	}

D
Daniel Imms 已提交
113 114 115
	/**
	 * Converts a CSS hex color (#rrggbb) to a CSS rgba color (rgba(r, g, b, a)).
	 */
D
Daniel Imms 已提交
116 117 118 119 120
	private convertHexCssColorToRgba(hex: string, alpha: number): string {
		let r = parseInt(hex.substr(1, 2), 16);
		let g = parseInt(hex.substr(3, 2), 16);
		let b = parseInt(hex.substr(5, 2), 16);
		return `rgba(${r}, ${g}, ${b}, ${alpha})`;
121 122
	}

123
	private updateFont(): void {
124 125 126 127
		if (!this.terminalInstance) {
			return;
		}
		this.terminalInstance.setFont(this.configurationHelper.getFont());
128
		this.layout(new Dimension(this.parentDomElement.offsetWidth, this.parentDomElement.offsetHeight));
129 130
	}

131

132
	public focus(): void {
133 134
		if (this.terminalInstance) {
			this.terminalInstance.focus(true);
135 136 137
		}
	}

138 139
	public dispose(): void {
		this.toDispose = lifecycle.dispose(this.toDispose);
140 141 142 143
		if (this.terminalInstance) {
			this.terminalInstance.dispose();
			this.terminalInstance = null;
		}
144 145
		super.dispose();
	}
D
Daniel Imms 已提交
146
}