activitybarPart.ts 8.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 19 20
import {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions, Viewlet} from 'vs/workbench/browser/viewlet';
import {CompositeDescriptor, Composite} from 'vs/workbench/browser/composite';
import {Panel} from 'vs/workbench/browser/panel';
E
Erich Gamma 已提交
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';
I
isidor 已提交
24
import {IPanelService} from 'vs/workbench/services/panel/common/panelService';
E
Erich Gamma 已提交
25 26 27 28
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 已提交
29
import {IMessageService} from 'vs/platform/message/common/message';
E
Erich Gamma 已提交
30
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
31
import {IKeybindingService} from 'vs/platform/keybinding/common/keybinding';
E
Erich Gamma 已提交
32 33

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

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

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

		this.registerListeners();
	}

	private registerListeners(): void {

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

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

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

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

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

	public showActivity(viewletId: string, badge: IBadge, clazz?: string): void {
I
isidor 已提交
86
		let action = this.viewletIdToActions[viewletId];
E
Erich Gamma 已提交
87 88 89 90 91 92 93 94 95 96 97 98 99
		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 已提交
100 101
		let $el = $(parent);
		let $result = $('.content').appendTo($el);
E
Erich Gamma 已提交
102 103 104 105 106 107 108 109 110 111 112

		// 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, {
113
			actionItemProvider: (action: Action) => this.activityActionItems[action.id],
114 115
			orientation: ActionsOrientation.VERTICAL,
			ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher")
E
Erich Gamma 已提交
116 117 118
		});
		this.viewletSwitcherBar.getContainer().addClass('position-top');

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

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

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

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

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

			return action;
		};

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

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

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

		super.dispose();
	}
}

I
isidor 已提交
168
abstract class CompositeActivityAction<T extends Composite> extends ActivityAction {
E
Erich Gamma 已提交
169
	private static preventDoubleClickDelay = 300;
170
	private lastRun: number = 0;
E
Erich Gamma 已提交
171

I
isidor 已提交
172
	protected composite: CompositeDescriptor<T>;
E
Erich Gamma 已提交
173 174

	constructor(
I
isidor 已提交
175 176 177 178
		id: string, composite: CompositeDescriptor<T>,
		@IViewletService protected viewletService: IViewletService,
		@IPanelService protected panelService: IPanelService,
		@IPartService protected partService: IPartService
E
Erich Gamma 已提交
179
	) {
I
isidor 已提交
180
		super(id, composite.name, composite.cssClass);
E
Erich Gamma 已提交
181

I
isidor 已提交
182
		this.composite = composite;
E
Erich Gamma 已提交
183 184
	}

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

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

I
isidor 已提交
194 195 196 197 198 199 200 201 202 203 204 205 206
		this.toggleComposite();

		return TPromise.as(true);
	}

	protected abstract toggleComposite(): void;
}

class ViewletActivityAction extends CompositeActivityAction<Viewlet> {

	protected toggleComposite(): void {
		const sideBarHidden = this.partService.isSideBarHidden();
		const activeViewlet = this.viewletService.getActiveViewlet();
E
Erich Gamma 已提交
207 208

		// Hide sidebar if selected viewlet already visible
I
isidor 已提交
209
		if (!sideBarHidden && activeViewlet && activeViewlet.getId() === this.composite.id) {
E
Erich Gamma 已提交
210
			this.partService.setSideBarHidden(true);
I
isidor 已提交
211 212 213
		} else {
			this.viewletService.openViewlet(this.composite.id, true).done(null, errors.onUnexpectedError);
			this.activate();
E
Erich Gamma 已提交
214
		}
I
isidor 已提交
215 216 217 218 219 220
	}
}

class PanelActivityAction extends CompositeActivityAction<Panel> {

	protected toggleComposite(): void {
E
Erich Gamma 已提交
221

I
isidor 已提交
222 223 224 225 226 227 228 229
		const panelHidden = this.partService.isPanelHidden();
		const activePanel = this.panelService.getActivePanel();

		// Hide panel if selected panel already visible
		if (!panelHidden && activePanel && activePanel.getId() === this.composite.id) {
			this.partService.setPanelHidden(true);
		} else {
			this.panelService.openPanel(this.composite.id, true).done(null, errors.onUnexpectedError);
E
Erich Gamma 已提交
230 231 232
			this.activate();
		}
	}
I
isidor 已提交
233
}