noTabsTitleControl.ts 6.3 KB
Newer Older
B
Benjamin Pasero 已提交
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import 'vs/css!./media/notabstitle';
9
import {IAction} from 'vs/base/common/actions';
B
Benjamin Pasero 已提交
10 11 12
import {prepareActions} from 'vs/workbench/browser/actionBarRegistry';
import errors = require('vs/base/common/errors');
import arrays = require('vs/base/common/arrays');
13
import {IEditorGroup, EditorInput} from 'vs/workbench/common/editor';
B
Benjamin Pasero 已提交
14 15 16 17 18
import DOM = require('vs/base/browser/dom');
import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar';
import {TitleControl} from 'vs/workbench/browser/parts/editor/titleControl';

export class NoTabsTitleControl extends TitleControl {
19 20 21 22
	private titleContainer: HTMLElement;
	private titleLabel: HTMLElement;
	private titleDecoration: HTMLElement;
	private titleDescription: HTMLElement;
B
Benjamin Pasero 已提交
23 24 25

	private editorActionsToolbar: ToolBar;

26 27 28
	private currentPrimaryEditorActionIds: string[] = [];
	private currentSecondaryEditorActionIds: string[] = [];

B
Benjamin Pasero 已提交
29 30 31 32 33 34 35

	public setContext(group: IEditorGroup): void {
		super.setContext(group);

		this.editorActionsToolbar.context = { group };
	}

36 37
	public create(parent: HTMLElement): void {
		this.titleContainer = parent;
B
Benjamin Pasero 已提交
38 39

		// Pin on double click
40
		this.toDispose.push(DOM.addDisposableListener(this.titleContainer, DOM.EventType.DBLCLICK, (e: MouseEvent) => {
B
Benjamin Pasero 已提交
41 42 43
			DOM.EventHelper.stop(e);

			this.onTitleDoubleClick();
44 45
		}));

B
Benjamin Pasero 已提交
46
		// Detect mouse click
47
		this.toDispose.push(DOM.addDisposableListener(this.titleContainer, DOM.EventType.MOUSE_UP, (e: MouseEvent) => {
B
Benjamin Pasero 已提交
48 49 50
			DOM.EventHelper.stop(e, false);

			this.onTitleClick(e);
51
		}));
B
Benjamin Pasero 已提交
52 53

		// Left Title Decoration
54 55 56
		this.titleDecoration = document.createElement('div');
		DOM.addClass(this.titleDecoration, 'title-decoration');
		this.titleContainer.appendChild(this.titleDecoration);
B
Benjamin Pasero 已提交
57 58

		// Left Title Label & Description
59 60 61 62 63
		const labelContainer = document.createElement('div');
		DOM.addClass(labelContainer, 'title-label');

		this.titleLabel = document.createElement('a');
		labelContainer.appendChild(this.titleLabel);
B
Benjamin Pasero 已提交
64

65 66
		this.titleDescription = document.createElement('span');
		labelContainer.appendChild(this.titleDescription);
B
Benjamin Pasero 已提交
67

68
		this.titleContainer.appendChild(labelContainer);
B
Benjamin Pasero 已提交
69 70

		// Right Actions Container
71 72 73 74
		const actionsContainer = document.createElement('div');
		DOM.addClass(actionsContainer, 'title-actions');

		this.editorActionsToolbar = this.doCreateToolbar(actionsContainer);
B
Benjamin Pasero 已提交
75

76
		this.titleContainer.appendChild(actionsContainer);
77 78

		// Context Menu
79
		this.toDispose.push(DOM.addDisposableListener(this.titleContainer, DOM.EventType.CONTEXT_MENU, (e: Event) => this.onContextMenu({ group: this.context, editor: this.context.activeEditor }, e, this.titleContainer)));
B
Benjamin Pasero 已提交
80 81 82 83 84 85 86 87 88
	}

	private onTitleDoubleClick(): void {
		if (!this.context) {
			return;
		}

		const group = this.context;

89
		this.editorGroupService.pinEditor(group, group.activeEditor);
B
Benjamin Pasero 已提交
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
	}

	private onTitleClick(e: MouseEvent): void {
		if (!this.context) {
			return;
		}

		const group = this.context;
		const position = this.stacks.positionOfGroup(group);

		// Close editor on middle mouse click
		if (e.button === 1 /* Middle Button */) {
			this.editorService.closeEditor(position, group.activeEditor).done(null, errors.onUnexpectedError);
		}

		// Focus editor group unless click on toolbar
B
Benjamin Pasero 已提交
106
		else if (this.stacks.groups.length === 1 && !DOM.isAncestor(<any>e.target || e.srcElement, this.editorActionsToolbar.getContainer().getHTMLElement())) {
107
			this.editorGroupService.focusGroup(group);
B
Benjamin Pasero 已提交
108 109 110
		}
	}

111
	protected doRefresh(): void {
B
Benjamin Pasero 已提交
112
		const group = this.context;
113
		const editor = group && group.activeEditor;
B
Benjamin Pasero 已提交
114
		if (!editor) {
115 116 117
			this.titleLabel.innerText = '';
			this.titleDescription.innerText = '';

B
Benjamin Pasero 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130
			this.editorActionsToolbar.setActions([], [])();

			this.currentPrimaryEditorActionIds = [];
			this.currentSecondaryEditorActionIds = [];

			return; // return early if we are being closed
		}

		const isPinned = group.isPinned(group.activeEditor);
		const isActive = this.stacks.isActive(group);

		// Pinned state
		if (isPinned) {
131
			DOM.addClass(this.titleContainer, 'pinned');
B
Benjamin Pasero 已提交
132
		} else {
133
			DOM.removeClass(this.titleContainer, 'pinned');
B
Benjamin Pasero 已提交
134 135 136 137
		}

		// Activity state
		if (isActive) {
138
			DOM.addClass(this.titleContainer, 'active');
B
Benjamin Pasero 已提交
139
		} else {
140
			DOM.removeClass(this.titleContainer, 'active');
B
Benjamin Pasero 已提交
141 142 143
		}

		// Editor Title
B
Benjamin Pasero 已提交
144 145
		const name = editor.getName() || '';
		const description = isActive ? (editor.getDescription() || '') : '';
B
Benjamin Pasero 已提交
146 147 148 149 150
		let verboseDescription = editor.getDescription(true) || '';
		if (description === verboseDescription) {
			verboseDescription = ''; // dont repeat what is already shown
		}

151 152
		this.titleLabel.innerText = name;
		this.titleLabel.title = verboseDescription;
B
Benjamin Pasero 已提交
153

154 155
		this.titleDescription.innerText = description;
		this.titleDescription.title = verboseDescription;
B
Benjamin Pasero 已提交
156 157 158

		// Editor Decoration
		if (editor.isDirty()) {
159
			DOM.addClass(this.titleDecoration, 'dirty');
B
Benjamin Pasero 已提交
160
		} else {
161
			DOM.removeClass(this.titleDecoration, 'dirty');
B
Benjamin Pasero 已提交
162 163 164
		}

		// Update Editor Actions Toolbar
165 166 167 168 169 170 171 172 173
		let primaryEditorActions: IAction[] = [];
		let secondaryEditorActions: IAction[] = [];
		if (isActive) {
			const editorActions = this.getEditorActions({ group, editor });
			primaryEditorActions = prepareActions(editorActions.primary);
			if (isActive && editor instanceof EditorInput && editor.supportsSplitEditor()) {
				primaryEditorActions.push(this.splitEditorAction);
			}
			secondaryEditorActions = prepareActions(editorActions.secondary);
174
		}
175

B
Benjamin Pasero 已提交
176
		const primaryEditorActionIds = primaryEditorActions.map(a => a.id);
177
		primaryEditorActionIds.push(this.closeEditorAction.id);
B
Benjamin Pasero 已提交
178 179 180 181
		const secondaryEditorActionIds = secondaryEditorActions.map(a => a.id);

		if (!arrays.equals(primaryEditorActionIds, this.currentPrimaryEditorActionIds) || !arrays.equals(secondaryEditorActionIds, this.currentSecondaryEditorActionIds)) {
			this.editorActionsToolbar.setActions(primaryEditorActions, secondaryEditorActions)();
B
Benjamin Pasero 已提交
182
			this.editorActionsToolbar.addPrimaryAction(this.closeEditorAction)();
183

B
Benjamin Pasero 已提交
184 185 186 187 188 189 190 191 192 193 194 195
			this.currentPrimaryEditorActionIds = primaryEditorActionIds;
			this.currentSecondaryEditorActionIds = secondaryEditorActionIds;
		}
	}

	public dispose(): void {
		super.dispose();

		// Toolbars
		this.editorActionsToolbar.dispose();
	}
}