activitybarPart.ts 7.0 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

B
Benjamin Pasero 已提交
8
import 'vs/css!./media/activitybarpart';
9
import nls = require('vs/nls');
A
Alex Dima 已提交
10
import {TPromise} from 'vs/base/common/winjs.base';
E
Erich Gamma 已提交
11
import {Builder, $} from 'vs/base/browser/builder';
A
tslint  
Alex Dima 已提交
12
import {Action} from 'vs/base/common/actions';
E
Erich Gamma 已提交
13 14
import errors = require('vs/base/common/errors');
import {ActionsOrientation, ActionBar, IActionItem} from 'vs/base/browser/ui/actionbar/actionbar';
15
import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar';
E
Erich Gamma 已提交
16
import {Registry} from 'vs/platform/platform';
17
import {IViewlet} from 'vs/workbench/common/viewlet';
I
isidor 已提交
18
import {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions} from 'vs/workbench/browser/viewlet';
E
Erich Gamma 已提交
19 20 21 22 23 24 25
import {Part} from 'vs/workbench/browser/part';
import {ActivityAction, ActivityActionItem} from 'vs/workbench/browser/parts/activitybar/activityAction';
import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletService';
import {IActivityService, IBadge} from 'vs/workbench/services/activity/common/activityService';
import {IPartService} from 'vs/workbench/services/part/common/partService';
import {IContextMenuService} from 'vs/platform/contextview/browser/contextView';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
A
tslint  
Alex Dima 已提交
26
import {IMessageService} from 'vs/platform/message/common/message';
E
Erich Gamma 已提交
27
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
28
import {IKeybindingService} from 'vs/platform/keybinding/common/keybinding';
E
Erich Gamma 已提交
29 30

export class ActivitybarPart extends Part implements IActivityService {
31
	public _serviceBrand: any;
E
Erich Gamma 已提交
32 33 34 35 36 37
	private viewletSwitcherBar: ActionBar;
	private globalToolBar: ToolBar;
	private activityActionItems: { [actionId: string]: IActionItem; };
	private viewletIdToActions: { [viewletId: string]: ActivityAction; };

	constructor(
38 39 40 41 42
		id: string,
		@IViewletService private viewletService: IViewletService,
		@IMessageService private messageService: IMessageService,
		@ITelemetryService private telemetryService: ITelemetryService,
		@IContextMenuService private contextMenuService: IContextMenuService,
43 44
		@IKeybindingService private keybindingService: IKeybindingService,
		@IInstantiationService private instantiationService: IInstantiationService
E
Erich Gamma 已提交
45 46 47 48 49 50 51 52 53 54 55 56
	) {
		super(id);

		this.activityActionItems = {};
		this.viewletIdToActions = {};

		this.registerListeners();
	}

	private registerListeners(): void {

		// Activate viewlet action on opening of a viewlet
57
		this.toUnbind.push(this.viewletService.onDidViewletOpen(viewlet => this.onActiveViewletChanged(viewlet)));
E
Erich Gamma 已提交
58 59

		// Deactivate viewlet action on close
60
		this.toUnbind.push(this.viewletService.onDidViewletClose(viewlet => this.onViewletClosed(viewlet)));
E
Erich Gamma 已提交
61 62
	}

63 64 65
	private onActiveViewletChanged(viewlet: IViewlet): void {
		if (this.viewletIdToActions[viewlet.getId()]) {
			this.viewletIdToActions[viewlet.getId()].activate();
E
Erich Gamma 已提交
66 67

			// There can only be one active viewlet action
I
isidor 已提交
68
			for (let key in this.viewletIdToActions) {
69
				if (this.viewletIdToActions.hasOwnProperty(key) && key !== viewlet.getId()) {
E
Erich Gamma 已提交
70 71 72 73 74 75
					this.viewletIdToActions[key].deactivate();
				}
			}
		}
	}

76 77 78
	private onViewletClosed(viewlet: IViewlet): void {
		if (this.viewletIdToActions[viewlet.getId()]) {
			this.viewletIdToActions[viewlet.getId()].deactivate();
E
Erich Gamma 已提交
79 80 81 82
		}
	}

	public showActivity(viewletId: string, badge: IBadge, clazz?: string): void {
I
isidor 已提交
83
		let action = this.viewletIdToActions[viewletId];
E
Erich Gamma 已提交
84 85 86 87 88 89 90 91 92 93 94 95 96
		if (action) {
			action.setBadge(badge);
			if (clazz) {
				action.class = clazz;
			}
		}
	}

	public clearActivity(viewletId: string): void {
		this.showActivity(viewletId, null);
	}

	public createContentArea(parent: Builder): Builder {
I
isidor 已提交
97 98
		let $el = $(parent);
		let $result = $('.content').appendTo($el);
E
Erich Gamma 已提交
99 100 101 102 103 104 105 106 107 108 109

		// Top Actionbar with action items for each viewlet action
		this.createViewletSwitcher($result.clone());

		return $result;
	}

	private createViewletSwitcher(div: Builder): void {

		// Viewlet switcher is on top
		this.viewletSwitcherBar = new ActionBar(div, {
110
			actionItemProvider: (action: Action) => this.activityActionItems[action.id],
111 112
			orientation: ActionsOrientation.VERTICAL,
			ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher")
E
Erich Gamma 已提交
113 114 115
		});
		this.viewletSwitcherBar.getContainer().addClass('position-top');

J
Joao Moreno 已提交
116 117
		// Build Viewlet Actions in correct order
		const activeViewlet = this.viewletService.getActiveViewlet();
I
isidor 已提交
118
		const registry = (<ViewletRegistry>Registry.as(ViewletExtensions.Viewlets));
J
Joao Moreno 已提交
119 120 121 122
		const allViewletActions = registry.getViewlets();
		const actionOptions = { label: true, icon: true };

		const toAction = (viewlet: ViewletDescriptor) => {
I
isidor 已提交
123
			let action = this.instantiationService.createInstance(ViewletActivityAction, viewlet.id + '.activity-bar-action', viewlet);
J
Joao Moreno 已提交
124 125

			let keybinding: string = null;
I
isidor 已提交
126
			let keys = this.keybindingService.lookupKeybindings(viewlet.id).map(k => this.keybindingService.getLabelFor(k));
J
Joao Moreno 已提交
127 128 129
			if (keys && keys.length) {
				keybinding = keys[0];
			}
E
Erich Gamma 已提交
130

J
Joao Moreno 已提交
131 132
			this.activityActionItems[action.id] = new ActivityActionItem(action, viewlet.name, keybinding);
			this.viewletIdToActions[viewlet.id] = action;
E
Erich Gamma 已提交
133

J
Joao Moreno 已提交
134 135 136
			// Mark active viewlet action as active
			if (activeViewlet && activeViewlet.getId() === viewlet.id) {
				action.activate();
E
Erich Gamma 已提交
137
			}
J
Joao Moreno 已提交
138 139 140 141 142 143 144 145 146

			return action;
		};

		// Add to viewlet switcher
		this.viewletSwitcherBar.push(allViewletActions
			.filter(v => !v.isGlobal)
			.sort((v1, v2) => v1.order - v2.order)
			.map(toAction)
147
			, actionOptions);
J
Joao Moreno 已提交
148 149
	}

E
Erich Gamma 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
	public dispose(): void {
		if (this.viewletSwitcherBar) {
			this.viewletSwitcherBar.dispose();
			this.viewletSwitcherBar = null;
		}

		if (this.globalToolBar) {
			this.globalToolBar.dispose();
			this.globalToolBar = null;
		}

		super.dispose();
	}
}

class ViewletActivityAction extends ActivityAction {
	private static preventDoubleClickDelay = 300;
167
	private lastRun: number = 0;
E
Erich Gamma 已提交
168 169 170 171 172 173 174 175 176 177 178 179 180

	private viewlet: ViewletDescriptor;

	constructor(
		id: string, viewlet: ViewletDescriptor,
		@IViewletService private viewletService: IViewletService,
		@IPartService private partService: IPartService
	) {
		super(id, viewlet.name, viewlet.cssClass);

		this.viewlet = viewlet;
	}

A
Alex Dima 已提交
181
	public run(): TPromise<any> {
E
Erich Gamma 已提交
182

183
		// prevent accident trigger on a doubleclick (to help nervous people)
I
isidor 已提交
184
		let now = Date.now();
185
		if (now - this.lastRun < ViewletActivityAction.preventDoubleClickDelay) {
A
Alex Dima 已提交
186
			return TPromise.as(true);
E
Erich Gamma 已提交
187
		}
188
		this.lastRun = now;
E
Erich Gamma 已提交
189

I
isidor 已提交
190 191
		let sideBarHidden = this.partService.isSideBarHidden();
		let activeViewlet = this.viewletService.getActiveViewlet();
E
Erich Gamma 已提交
192 193 194 195 196 197 198 199 200 201 202 203

		// Hide sidebar if selected viewlet already visible
		if (!sideBarHidden && activeViewlet && activeViewlet.getId() === this.viewlet.id) {
			this.partService.setSideBarHidden(true);
		}

		// Open viewlet and focus it
		else {
			this.viewletService.openViewlet(this.viewlet.id, true).done(null, errors.onUnexpectedError);
			this.activate();
		}

A
Alex Dima 已提交
204
		return TPromise.as(true);
E
Erich Gamma 已提交
205 206
	}
}