activitybarPart.ts 6.2 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 15
import errors = require('vs/base/common/errors');
import {ActionsOrientation, ActionBar, IActionItem} from 'vs/base/browser/ui/actionbar/actionbar';
import {Registry} from 'vs/platform/platform';
16
import {IComposite} from 'vs/workbench/common/composite';
I
isidor 已提交
17
import {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions} from 'vs/workbench/browser/viewlet';
E
Erich Gamma 已提交
18 19 20 21 22 23
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 {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
24
import {IKeybindingService} from 'vs/platform/keybinding/common/keybinding';
E
Erich Gamma 已提交
25 26

export class ActivitybarPart extends Part implements IActivityService {
27
	public _serviceBrand: any;
I
isidor 已提交
28
	private viewletSwitcherBar: ActionBar;
E
Erich Gamma 已提交
29
	private activityActionItems: { [actionId: string]: IActionItem; };
30
	private compositeIdToActions: { [compositeId: string]: ActivityAction; };
E
Erich Gamma 已提交
31 32

	constructor(
33 34
		id: string,
		@IViewletService private viewletService: IViewletService,
35
		@IKeybindingService private keybindingService: IKeybindingService,
I
isidor 已提交
36
		@IInstantiationService private instantiationService: IInstantiationService,
I
isidor 已提交
37
		@IPartService private partService: IPartService
E
Erich Gamma 已提交
38 39 40 41
	) {
		super(id);

		this.activityActionItems = {};
42
		this.compositeIdToActions = {};
E
Erich Gamma 已提交
43 44 45 46 47 48 49

		this.registerListeners();
	}

	private registerListeners(): void {

		// Activate viewlet action on opening of a viewlet
50
		this.toUnbind.push(this.viewletService.onDidViewletOpen(viewlet => this.onActiveCompositeChanged(viewlet)));
E
Erich Gamma 已提交
51 52

		// Deactivate viewlet action on close
53
		this.toUnbind.push(this.viewletService.onDidViewletClose(viewlet => this.onCompositeClosed(viewlet)));
E
Erich Gamma 已提交
54 55
	}

56 57 58
	private onActiveCompositeChanged(composite: IComposite): void {
		if (this.compositeIdToActions[composite.getId()]) {
			this.compositeIdToActions[composite.getId()].activate();
E
Erich Gamma 已提交
59 60 61
		}
	}

62 63 64
	private onCompositeClosed(composite: IComposite): void {
		if (this.compositeIdToActions[composite.getId()]) {
			this.compositeIdToActions[composite.getId()].deactivate();
E
Erich Gamma 已提交
65 66 67
		}
	}

68 69
	public showActivity(compositeId: string, badge: IBadge, clazz?: string): void {
		const action = this.compositeIdToActions[compositeId];
E
Erich Gamma 已提交
70 71 72 73 74 75 76 77
		if (action) {
			action.setBadge(badge);
			if (clazz) {
				action.class = clazz;
			}
		}
	}

78 79
	public clearActivity(compositeId: string): void {
		this.showActivity(compositeId, null);
E
Erich Gamma 已提交
80 81 82
	}

	public createContentArea(parent: Builder): Builder {
83 84
		const $el = $(parent);
		const $result = $('.content').appendTo($el);
E
Erich Gamma 已提交
85 86

		// Top Actionbar with action items for each viewlet action
I
isidor 已提交
87
		this.createViewletSwitcher($result.clone());
E
Erich Gamma 已提交
88 89 90 91

		return $result;
	}

I
isidor 已提交
92
	private createViewletSwitcher(div: Builder): void {
E
Erich Gamma 已提交
93

94
		// Composite switcher is on top
I
isidor 已提交
95
		this.viewletSwitcherBar = new ActionBar(div, {
96
			actionItemProvider: (action: Action) => this.activityActionItems[action.id],
97 98
			orientation: ActionsOrientation.VERTICAL,
			ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher")
E
Erich Gamma 已提交
99
		});
I
isidor 已提交
100
		this.viewletSwitcherBar.getContainer().addClass('position-top');
E
Erich Gamma 已提交
101

J
Joao Moreno 已提交
102
		// Build Viewlet Actions in correct order
I
isidor 已提交
103
		const allViewlets = (<ViewletRegistry>Registry.as(ViewletExtensions.Viewlets)).getViewlets();
I
isidor 已提交
104
		const viewletActions = allViewlets.sort((v1, v2) => v1.order - v2.order).map(viewlet => this.toAction(viewlet));
J
Joao Moreno 已提交
105

I
isidor 已提交
106 107
		this.viewletSwitcherBar.push(viewletActions, { label: true, icon: true });
	}
J
Joao Moreno 已提交
108

I
isidor 已提交
109
	private toAction(composite: ViewletDescriptor): ActivityAction {
I
isidor 已提交
110
		const activeViewlet = this.viewletService.getActiveViewlet();
I
isidor 已提交
111
		const action = this.instantiationService.createInstance(ViewletActivityAction, composite.id + '.activity-bar-action', composite);
I
isidor 已提交
112

113
		this.activityActionItems[action.id] = new ActivityActionItem(action, composite.name, this.getKeybindingLabel(composite.id));
I
isidor 已提交
114 115
		this.compositeIdToActions[composite.id] = action;

I
isidor 已提交
116 117
		// Mark active viewlet as active
		if (activeViewlet && activeViewlet.getId() === composite.id) {
I
isidor 已提交
118 119 120 121 122 123
			action.activate();
		}

		return action;
	};

124 125 126 127 128 129 130 131 132
	private getKeybindingLabel(id: string): string {
		const keys = this.keybindingService.lookupKeybindings(id).map(k => this.keybindingService.getLabelFor(k));
		if (keys && keys.length) {
			return keys[0];
		}

		return null;
	}

E
Erich Gamma 已提交
133
	public dispose(): void {
I
isidor 已提交
134 135 136 137 138
		if (this.viewletSwitcherBar) {
			this.viewletSwitcherBar.dispose();
			this.viewletSwitcherBar = null;
		}

E
Erich Gamma 已提交
139 140 141 142
		super.dispose();
	}
}

143
class ViewletActivityAction extends ActivityAction {
E
Erich Gamma 已提交
144
	private static preventDoubleClickDelay = 300;
145
	private lastRun: number = 0;
E
Erich Gamma 已提交
146 147

	constructor(
148 149 150
		id: string, private viewlet: ViewletDescriptor,
		@IViewletService private viewletService: IViewletService,
		@IPartService private partService: IPartService
E
Erich Gamma 已提交
151
	) {
152
		super(id, viewlet.name, viewlet.cssClass);
E
Erich Gamma 已提交
153 154
	}

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

157
		// prevent accident trigger on a doubleclick (to help nervous people)
158
		const now = Date.now();
159
		if (now - this.lastRun < ViewletActivityAction.preventDoubleClickDelay) {
A
Alex Dima 已提交
160
			return TPromise.as(true);
E
Erich Gamma 已提交
161
		}
162
		this.lastRun = now;
E
Erich Gamma 已提交
163

I
isidor 已提交
164 165
		const sideBarHidden = this.partService.isSideBarHidden();
		const activeViewlet = this.viewletService.getActiveViewlet();
E
Erich Gamma 已提交
166 167

		// Hide sidebar if selected viewlet already visible
168
		if (!sideBarHidden && activeViewlet && activeViewlet.getId() === this.viewlet.id) {
E
Erich Gamma 已提交
169
			this.partService.setSideBarHidden(true);
I
isidor 已提交
170
		} else {
171
			this.viewletService.openViewlet(this.viewlet.id, true).done(null, errors.onUnexpectedError);
I
isidor 已提交
172
			this.activate();
E
Erich Gamma 已提交
173
		}
174 175

		return TPromise.as(true);
I
isidor 已提交
176 177
	}
}