activitybarPart.ts 10.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 * as nls from 'vs/nls';
J
Johannes Rieken 已提交
10
import { illegalArgument } from 'vs/base/common/errors';
11
import { $ } from 'vs/base/browser/builder';
12
import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
B
Benjamin Pasero 已提交
13
import { GlobalActivityExtensions, IGlobalActivityRegistry } from 'vs/workbench/common/activity';
14
import { Registry } from 'vs/platform/registry/common/platform';
J
Johannes Rieken 已提交
15
import { Part } from 'vs/workbench/browser/part';
16
import { GlobalActivityActionItem, GlobalActivityAction, ViewletActivityAction, ToggleViewletAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
B
Benjamin Pasero 已提交
17
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
I
isidor 已提交
18
import { IBadge } from 'vs/workbench/services/activity/common/activity';
I
isidor 已提交
19
import { IPartService, Parts, Position as SideBarPosition } from 'vs/workbench/services/part/common/partService';
J
Johannes Rieken 已提交
20
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
21
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
22
import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/toggleActivityBarVisibility';
23
import { IThemeService } from 'vs/platform/theme/common/themeService';
I
isidor 已提交
24
import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
25
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
26
import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar';
27
import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions';
28 29
import { ViewLocation, ViewsRegistry } from 'vs/workbench/common/views';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
30
import { Dimension } from 'vs/base/browser/dom';
E
Erich Gamma 已提交
31

I
isidor 已提交
32
export class ActivitybarPart extends Part {
33

34
	private static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets';
35
	private static readonly COLORS = {
I
isidor 已提交
36 37 38 39 40
		backgroundColor: ACTIVITY_BAR_FOREGROUND,
		badgeBackground: ACTIVITY_BAR_BADGE_BACKGROUND,
		badgeForeground: ACTIVITY_BAR_BADGE_FOREGROUND,
		dragAndDropBackground: ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND
	};
I
isidor 已提交
41
	private static readonly ACTION_HEIGHT = 50;
42

43
	public _serviceBrand: any;
P
Pine Wu 已提交
44

45 46
	private dimension: Dimension;

47 48 49
	private globalActionBar: ActionBar;
	private globalActivityIdToActions: { [globalActivityId: string]: GlobalActivityAction; };

50
	private compositeBar: CompositeBar;
51

E
Erich Gamma 已提交
52
	constructor(
53 54
		id: string,
		@IViewletService private viewletService: IViewletService,
I
isidor 已提交
55
		@IInstantiationService private instantiationService: IInstantiationService,
B
Benjamin Pasero 已提交
56
		@IPartService private partService: IPartService,
57
		@IThemeService themeService: IThemeService
E
Erich Gamma 已提交
58
	) {
B
Benjamin Pasero 已提交
59
		super(id, { hasTitle: false }, themeService);
E
Erich Gamma 已提交
60

J
Joao Moreno 已提交
61
		this.globalActivityIdToActions = Object.create(null);
62

63
		this.compositeBar = this.instantiationService.createInstance(CompositeBar, {
I
isidor 已提交
64
			icon: true,
65 66
			storageId: ActivitybarPart.PINNED_VIEWLETS,
			orientation: ActionsOrientation.VERTICAL,
67
			composites: this.viewletService.getViewlets().filter(v => this.canShow(v)),
68
			openComposite: (compositeId: string) => this.viewletService.openViewlet(compositeId, true),
69
			getActivityAction: (compositeId: string) => this.instantiationService.createInstance(ViewletActivityAction, this.viewletService.getViewlet(compositeId)),
70
			getCompositePinnedAction: (compositeId: string) => new ToggleCompositePinnedAction(this.viewletService.getViewlet(compositeId), this.compositeBar),
71
			getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, this.viewletService.getViewlet(compositeId)),
72
			getContextMenuActions: () => [this.instantiationService.createInstance(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, nls.localize('hideActivitBar', "Hide Activity Bar"))],
73
			getDefaultCompositeId: () => this.viewletService.getDefaultViewletId(),
I
isidor 已提交
74
			hidePart: () => this.partService.setSideBarHidden(true),
75
			compositeSize: 50,
I
isidor 已提交
76
			colors: ActivitybarPart.COLORS,
I
isidor 已提交
77
			overflowActionSize: ActivitybarPart.ACTION_HEIGHT
78
		});
79

E
Erich Gamma 已提交
80
		this.registerListeners();
81
		this.updateCompositebar();
E
Erich Gamma 已提交
82 83 84 85
	}

	private registerListeners(): void {

86 87 88
		this.toUnbind.push(this.viewletService.onDidViewletRegister(() => this.updateCompositebar()));
		this.toUnbind.push(ViewsRegistry.onViewsRegistered(() => this.updateCompositebar()));
		this.toUnbind.push(ViewsRegistry.onViewsDeregistered(() => this.updateCompositebar()));
89

E
Erich Gamma 已提交
90
		// Activate viewlet action on opening of a viewlet
91
		this.toUnbind.push(this.viewletService.onDidViewletOpen(viewlet => this.compositeBar.activateComposite(viewlet.getId())));
E
Erich Gamma 已提交
92 93

		// Deactivate viewlet action on close
94
		this.toUnbind.push(this.viewletService.onDidViewletClose(viewlet => this.compositeBar.deactivateComposite(viewlet.getId())));
I
isidor 已提交
95
		this.toUnbind.push(this.viewletService.onDidViewletEnablementChange(({ id, enabled }) => {
96
			if (enabled) {
97
				this.compositeBar.addComposite(this.viewletService.getViewlet(id), true);
98 99
			} else {
				this.compositeBar.removeComposite(id);
100 101
			}
		}));
E
Erich Gamma 已提交
102 103
	}

J
Joao Moreno 已提交
104
	public showActivity(viewletOrActionId: string, badge: IBadge, clazz?: string, priority?: number): IDisposable {
B
Benjamin Pasero 已提交
105
		if (this.viewletService.getViewlet(viewletOrActionId)) {
J
Joao Moreno 已提交
106
			return this.compositeBar.showActivity(viewletOrActionId, badge, clazz, priority);
B
Benjamin Pasero 已提交
107 108
		}

109
		return this.showGlobalActivity(viewletOrActionId, badge, clazz);
B
Benjamin Pasero 已提交
110 111
	}

112
	private showGlobalActivity(globalActivityId: string, badge: IBadge, clazz?: string): IDisposable {
J
Joao Moreno 已提交
113 114 115 116 117 118 119 120 121
		if (!badge) {
			throw illegalArgument('badge');
		}

		const action = this.globalActivityIdToActions[globalActivityId];
		if (!action) {
			throw illegalArgument('globalActivityId');
		}

122
		action.setBadge(badge, clazz);
B
Benjamin Pasero 已提交
123

J
Joao Moreno 已提交
124 125 126
		return toDisposable(() => action.setBadge(undefined));
	}

127
	public createContentArea(parent: HTMLElement): HTMLElement {
128 129
		const $el = $(parent);
		const $result = $('.content').appendTo($el);
E
Erich Gamma 已提交
130 131

		// Top Actionbar with action items for each viewlet action
I
isidor 已提交
132
		this.compositeBar.create($result.getHTMLElement());
E
Erich Gamma 已提交
133

134
		// Top Actionbar with action items for each viewlet action
I
isidor 已提交
135
		this.createGlobalActivityActionBar($('.global-activity').appendTo($result).getHTMLElement());
136

137
		return $result.getHTMLElement();
E
Erich Gamma 已提交
138 139
	}

140 141 142 143
	public updateStyles(): void {
		super.updateStyles();

		// Part container
144
		const container = $(this.getContainer());
145 146
		const background = this.getColor(ACTIVITY_BAR_BACKGROUND);
		container.style('background-color', background);
147

148
		const borderColor = this.getColor(ACTIVITY_BAR_BORDER) || this.getColor(contrastBorder);
149
		const isPositionLeft = this.partService.getSideBarPosition() === SideBarPosition.LEFT;
150 151 152 153 154 155 156
		container.style('box-sizing', borderColor && isPositionLeft ? 'border-box' : null);
		container.style('border-right-width', borderColor && isPositionLeft ? '1px' : null);
		container.style('border-right-style', borderColor && isPositionLeft ? 'solid' : null);
		container.style('border-right-color', isPositionLeft ? borderColor : null);
		container.style('border-left-width', borderColor && !isPositionLeft ? '1px' : null);
		container.style('border-left-style', borderColor && !isPositionLeft ? 'solid' : null);
		container.style('border-left-color', !isPositionLeft ? borderColor : null);
157 158
	}

J
Joao Moreno 已提交
159
	private createGlobalActivityActionBar(container: HTMLElement): void {
J
Joao Moreno 已提交
160
		const activityRegistry = Registry.as<IGlobalActivityRegistry>(GlobalActivityExtensions);
161 162 163 164 165
		const descriptors = activityRegistry.getActivities();
		const actions = descriptors
			.map(d => this.instantiationService.createInstance(d))
			.map(a => new GlobalActivityAction(a));

166
		this.globalActionBar = new ActionBar(container, {
I
isidor 已提交
167
			actionItemProvider: a => this.instantiationService.createInstance(GlobalActivityActionItem, a, ActivitybarPart.COLORS),
168 169 170 171
			orientation: ActionsOrientation.VERTICAL,
			ariaLabel: nls.localize('globalActions', "Global Actions"),
			animated: false
		});
B
Benjamin Pasero 已提交
172
		this.toUnbind.push(this.globalActionBar);
173

J
Joao Moreno 已提交
174 175
		actions.forEach(a => {
			this.globalActivityIdToActions[a.id] = a;
176
			this.globalActionBar.push(a);
J
Joao Moreno 已提交
177
		});
178 179
	}

180 181 182 183 184 185
	private updateCompositebar(): void {
		const viewlets = this.viewletService.getViewlets();
		for (const viewlet of viewlets) {
			const canShow = this.canShow(viewlet);
			if (canShow) {
				this.compositeBar.addComposite(viewlet, false);
S
Sandeep Somavarapu 已提交
186 187 188 189 190
				const activeViewlet = this.viewletService.getActiveViewlet();
				if (activeViewlet && activeViewlet.getId() === viewlet.id) {
					this.compositeBar.pin(viewlet.id);
					this.compositeBar.activateComposite(viewlet.id);
				}
191 192 193 194 195 196 197 198
			} else {
				this.compositeBar.removeComposite(viewlet.id);
			}
		}
	}

	private canShow(viewlet: ViewletDescriptor): boolean {
		const viewLocation = ViewLocation.get(viewlet.id);
S
Sandeep Somavarapu 已提交
199
		if (viewLocation) {
200 201 202 203 204
			return ViewsRegistry.getViews(viewLocation).length > 0;
		}
		return true;
	}

205
	public getPinned(): string[] {
206
		return this.viewletService.getViewlets().map(v => v.id).filter(id => this.compositeBar.isPinned(id));
207 208
	}

209 210 211 212
	/**
	 * Layout title, content and status area in the given dimension.
	 */
	public layout(dimension: Dimension): Dimension[] {
I
isidor 已提交
213 214 215
		if (!this.partService.isVisible(Parts.ACTIVITYBAR_PART)) {
			return [dimension];
		}
216 217 218 219 220 221

		// Pass to super
		const sizes = super.layout(dimension);

		this.dimension = sizes[1];

222 223 224
		let availableHeight = this.dimension.height;
		if (this.globalActionBar) {
			// adjust height for global actions showing
I
isidor 已提交
225
			availableHeight -= (this.globalActionBar.items.length * ActivitybarPart.ACTION_HEIGHT);
226 227
		}
		this.compositeBar.layout(new Dimension(dimension.width, availableHeight));
228 229 230

		return sizes;
	}
I
isidor 已提交
231

232 233 234 235 236
	public shutdown(): void {
		this.compositeBar.shutdown();
		super.shutdown();
	}

E
Erich Gamma 已提交
237
	public dispose(): void {
238 239 240
		if (this.compositeBar) {
			this.compositeBar.dispose();
			this.compositeBar = null;
I
isidor 已提交
241 242
		}

B
Benjamin Pasero 已提交
243 244 245 246 247
		if (this.globalActionBar) {
			this.globalActionBar.dispose();
			this.globalActionBar = null;
		}

E
Erich Gamma 已提交
248 249
		super.dispose();
	}
250
}