tabsTitleControl.ts 6.6 KB
Newer Older
B
wip  
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/tabstitle';
B
Benjamin Pasero 已提交
9
import nls = require('vs/nls');
B
wip  
Benjamin Pasero 已提交
10 11
import {prepareActions} from 'vs/workbench/browser/actionBarRegistry';
import arrays = require('vs/base/common/arrays');
B
Benjamin Pasero 已提交
12 13
import errors = require('vs/base/common/errors');
import DOM = require('vs/base/browser/dom');
B
wip  
Benjamin Pasero 已提交
14 15 16
import {Builder, $} from 'vs/base/browser/builder';
import {IEditorGroup} from 'vs/workbench/common/editor';
import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar';
B
Benjamin Pasero 已提交
17
import {ActionBar} from 'vs/base/browser/ui/actionbar/actionbar';
B
wip  
Benjamin Pasero 已提交
18 19 20 21 22 23 24 25
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IContextMenuService} from 'vs/platform/contextview/browser/contextView';
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
import {IMessageService} from 'vs/platform/message/common/message';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {TitleControl} from 'vs/workbench/browser/parts/editor/titleControl';
B
Benjamin Pasero 已提交
26
import {IEditorInput} from 'vs/platform/editor/common/editor';
B
wip  
Benjamin Pasero 已提交
27 28 29

export class TabsTitleControl extends TitleControl {
	private titleContainer: Builder;
B
Benjamin Pasero 已提交
30
	private tabsContainer: Builder;
B
wip  
Benjamin Pasero 已提交
31 32

	private groupActionsToolbar: ToolBar;
B
Benjamin Pasero 已提交
33
	private tabActionBars: ActionBar[];
B
wip  
Benjamin Pasero 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

	private currentPrimaryGroupActionIds: string[];
	private currentSecondaryGroupActionIds: string[];

	constructor(
		@IContextMenuService contextMenuService: IContextMenuService,
		@IInstantiationService instantiationService: IInstantiationService,
		@IWorkbenchEditorService editorService: IWorkbenchEditorService,
		@IEditorGroupService editorGroupService: IEditorGroupService,
		@IKeybindingService keybindingService: IKeybindingService,
		@ITelemetryService telemetryService: ITelemetryService,
		@IMessageService messageService: IMessageService
	) {
		super(contextMenuService, instantiationService, editorService, editorGroupService, keybindingService, telemetryService, messageService);

		this.currentPrimaryGroupActionIds = [];
		this.currentSecondaryGroupActionIds = [];
B
Benjamin Pasero 已提交
51 52

		this.tabActionBars = [];
B
wip  
Benjamin Pasero 已提交
53 54 55 56 57 58 59 60 61 62 63
	}

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

		this.groupActionsToolbar.context = { group };
	}

	public create(parent: Builder): void {
		this.titleContainer = $(parent);

64 65 66 67
		// Tabs Container
		parent.div({
			'class': 'tabs-container'
		}, (div) => {
B
Benjamin Pasero 已提交
68
			this.tabsContainer = div;
69 70
		});

B
Benjamin Pasero 已提交
71
		// Group Actions
B
wip  
Benjamin Pasero 已提交
72
		parent.div({
73
			'class': 'group-actions'
B
wip  
Benjamin Pasero 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
		}, (div) => {
			this.groupActionsToolbar = this.doCreateToolbar(div);
		});
	}

	public refresh(): void {
		if (!this.context) {
			return;
		}

		const group = this.context;
		const editor = group.activeEditor;
		if (!editor) {
			this.groupActionsToolbar.setActions([], [])();

			this.currentPrimaryGroupActionIds = [];
			this.currentSecondaryGroupActionIds = [];

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

95
		// Activity state
B
Benjamin Pasero 已提交
96
		const isActive = this.stacks.isActive(group);
97
		if (isActive) {
B
Benjamin Pasero 已提交
98
			this.titleContainer.addClass('active');
99
		} else {
B
Benjamin Pasero 已提交
100
			this.titleContainer.removeClass('active');
101 102
		}

B
Benjamin Pasero 已提交
103 104 105
		// Refresh Tabs
		this.refreshTabs(group);

B
wip  
Benjamin Pasero 已提交
106 107 108 109 110 111 112 113 114 115 116 117 118 119
		// Update Group Actions Toolbar
		const groupActions = this.getGroupActions(group);
		const primaryGroupActions = prepareActions(groupActions.primary);
		const secondaryGroupActions = prepareActions(groupActions.secondary);
		const primaryGroupActionIds = primaryGroupActions.map(a => a.id);
		const secondaryGroupActionIds = secondaryGroupActions.map(a => a.id);

		if (!arrays.equals(primaryGroupActionIds, this.currentPrimaryGroupActionIds) || !arrays.equals(secondaryGroupActionIds, this.currentSecondaryGroupActionIds)) {
			this.groupActionsToolbar.setActions(primaryGroupActions, secondaryGroupActions)();
			this.currentPrimaryGroupActionIds = primaryGroupActionIds;
			this.currentSecondaryGroupActionIds = secondaryGroupActionIds;
		}
	}

B
Benjamin Pasero 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
	private refreshTabs(group: IEditorGroup): void {

		// Empty container first
		this.tabsContainer.empty();
		while(this.tabActionBars.length) {
			this.tabActionBars.pop().dispose();
		}

		// Add a tab for each opened editor
		this.context.getEditors().forEach(editor => {
			const isPinned = group.isPinned(editor);
			const isActive = group.isActive(editor);
			const isDirty = editor.isDirty();

			$(this.tabsContainer).div({ 'class': 'tab monaco-editor-background' }, tab => {

				// Eventing
				this.hookTabListeners(tab, editor, group);

				// Pinned state
				if (isPinned) {
					tab.addClass('pinned');
				} else {
					tab.removeClass('pinned');
				}

				// Active state
				if (isActive) {
B
Benjamin Pasero 已提交
148
					tab.addClass('active');
B
Benjamin Pasero 已提交
149
				} else {
B
Benjamin Pasero 已提交
150
					tab.removeClass('active');
B
Benjamin Pasero 已提交
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
				}

				// Dirty State
				if (isDirty) {
					tab.addClass('dirty');
				} else {
					tab.removeClass('dirty');
				}

				// Tab Label
				tab.div({
					'class': 'tab-label'
				}, (div) => {
					$(div).a().safeInnerHtml(editor.getName()).title(editor.getDescription(true));
				});

				// Tab Close
				tab.div({
					'class': 'tab-close'
				}, (div) => {
B
Benjamin Pasero 已提交
171
					const bar = new ActionBar(div, { context: { editor, group }, ariaLabel: nls.localize('araLabelTabActions', "Tab actions") });
B
Benjamin Pasero 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
					bar.push(this.closeEditorAction, { icon: true, label: false });

					this.tabActionBars.push(bar);
				});
			});
		});
	}

	private hookTabListeners(tab: Builder, editor: IEditorInput, group: IEditorGroup): void {
		const position = this.stacks.positionOfGroup(group);

		// Open on Click
		tab.on(DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => {
			DOM.EventHelper.stop(e);

			if (!DOM.findParentWithClass(<any>e.target || e.srcElement, 'monaco-action-bar', 'tab')) {
				this.editorService.openEditor(editor, null, position).done(null, errors.onUnexpectedError);
			}
		});

		// Pin on double click
		tab.on(DOM.EventType.DBLCLICK, (e: MouseEvent) => {
			DOM.EventHelper.stop(e);

			this.editorGroupService.pinEditor(position, editor);
		});

		// Close on mouse middle click
		tab.on(DOM.EventType.MOUSE_UP, (e: MouseEvent) => {
			DOM.EventHelper.stop(e);

			if (e.button === 1 /* Middle Button */) {
				this.editorService.closeEditor(position, editor).done(null, errors.onUnexpectedError);
			}
		});
	}

B
wip  
Benjamin Pasero 已提交
209 210 211
	public dispose(): void {
		super.dispose();

B
Benjamin Pasero 已提交
212
		// Toolbar
B
wip  
Benjamin Pasero 已提交
213 214 215
		this.groupActionsToolbar.dispose();
	}
}