explorerViewlet.ts 7.4 KB
Newer Older
E
Erich Gamma 已提交
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/explorerviewlet';
9
import {IDisposable} from 'vs/base/common/lifecycle';
I
isidor 已提交
10
import {IAction} from 'vs/base/common/actions';
11
import {TPromise} from 'vs/base/common/winjs.base';
E
Erich Gamma 已提交
12 13
import {Dimension, Builder} from 'vs/base/browser/builder';
import {Scope} from 'vs/workbench/common/memento';
I
isidor 已提交
14 15
import {VIEWLET_ID, IFilesConfiguration} from 'vs/workbench/parts/files/common/files';
import {IViewletView, Viewlet} from 'vs/workbench/browser/viewlet';
E
Erich Gamma 已提交
16
import {IActionRunner} from 'vs/base/common/actions';
I
isidor 已提交
17 18
import {SplitView, Orientation} from 'vs/base/browser/ui/splitview/splitview';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
E
Erich Gamma 已提交
19 20 21
import {ActionRunner, FileViewletState} from 'vs/workbench/parts/files/browser/views/explorerViewer';
import {ExplorerView} from 'vs/workbench/parts/files/browser/views/explorerView';
import {EmptyView} from 'vs/workbench/parts/files/browser/views/emptyView';
I
isidor 已提交
22
import {OpenEditorsView} from 'vs/workbench/parts/files/browser/views/openEditorsView';
E
Erich Gamma 已提交
23 24 25 26 27 28 29 30 31 32 33
import {IStorageService} from 'vs/platform/storage/common/storage';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';

export class ExplorerViewlet extends Viewlet {
	private viewletContainer: Builder;
	private splitView: SplitView;
	private views: IViewletView[];

	private explorerView: ExplorerView;
I
isidor 已提交
34
	private openEditorsView: OpenEditorsView;
I
isidor 已提交
35
	private openEditorsVisible: boolean;
I
isidor 已提交
36
	private lastFocusedView: ExplorerView | OpenEditorsView | EmptyView;
37
	private focusListener: IDisposable;
E
Erich Gamma 已提交
38 39 40 41 42 43 44 45

	private viewletSettings: any;
	private viewletState: FileViewletState;

	constructor(
		@ITelemetryService telemetryService: ITelemetryService,
		@IWorkspaceContextService private contextService: IWorkspaceContextService,
		@IStorageService private storageService: IStorageService,
I
isidor 已提交
46
		@IConfigurationService private configurationService: IConfigurationService,
E
Erich Gamma 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
		@IInstantiationService private instantiationService: IInstantiationService
	) {
		super(VIEWLET_ID, telemetryService);

		this.views = [];
		this.viewletState = new FileViewletState();

		this.viewletSettings = this.getMemento(storageService, Scope.WORKSPACE);
	}

	public create(parent: Builder): TPromise<void> {
		super.create(parent);

		this.viewletContainer = parent.div().addClass('explorer-viewlet');

I
isidor 已提交
62
		return this.configurationService.loadConfiguration().then((config:IFilesConfiguration) => {
63
			// Open editors view should always be visible in no folder workspace.
64
			this.openEditorsVisible = !this.contextService.getWorkspace() || config.explorer.openEditors.visible !== 0;
I
isidor 已提交
65 66
			if (this.openEditorsVisible) {
				this.splitView = new SplitView(this.viewletContainer.getHTMLElement());
E
Erich Gamma 已提交
67

I
isidor 已提交
68 69
				// Open editors view
				this.addOpenEditorsView();
E
Erich Gamma 已提交
70

I
isidor 已提交
71 72 73 74 75 76 77 78 79
				// Track focus
				this.focusListener = this.splitView.onFocus((view: ExplorerView | OpenEditorsView | EmptyView) => {
					this.lastFocusedView = view;
				});
			}

			// Explorer view
			this.addExplorerView();
			this.lastFocusedView = this.explorerView;
E
Erich Gamma 已提交
80

I
isidor 已提交
81
			return TPromise.join(this.views.map((view) => view.create())).then(() => void 0);
82
		});
I
isidor 已提交
83
	}
84

I
isidor 已提交
85 86 87 88 89 90
	public getActions(): IAction[] {
		if (this.openEditorsVisible) {
			return [];
		} else {
			return this.explorerView.getActions();
		}
E
Erich Gamma 已提交
91 92
	}

I
isidor 已提交
93 94
	private addOpenEditorsView(): void {
		this.openEditorsView = this.instantiationService.createInstance(OpenEditorsView, this.getActionRunner(), this.viewletSettings);
95
		this.splitView.addView(this.openEditorsView);
E
Erich Gamma 已提交
96

I
isidor 已提交
97
		this.views.push(this.openEditorsView);
E
Erich Gamma 已提交
98 99 100
	}

	private addExplorerView(): void {
I
isidor 已提交
101
		let explorerView: ExplorerView | EmptyView;
E
Erich Gamma 已提交
102 103 104

		// With a Workspace
		if (this.contextService.getWorkspace()) {
I
isidor 已提交
105 106 107
			// If open editors are not visible set header size explicitly to 0, otherwise let it be computed by super class.
			const headerSize = this.openEditorsVisible ? undefined : 0;
			this.explorerView = explorerView = this.instantiationService.createInstance(ExplorerView, this.viewletState, this.getActionRunner(), this.viewletSettings, headerSize);
E
Erich Gamma 已提交
108 109 110 111 112 113 114
		}

		// No workspace
		else {
			explorerView = this.instantiationService.createInstance(EmptyView);
		}

I
isidor 已提交
115
		if (this.openEditorsVisible) {
116
			this.splitView.addView(explorerView);
I
isidor 已提交
117
		} else {
I
isidor 已提交
118
			explorerView.render(this.viewletContainer.getHTMLElement(), Orientation.VERTICAL);
I
isidor 已提交
119
		}
E
Erich Gamma 已提交
120 121 122 123 124 125 126
		this.views.push(explorerView);
	}

	public getExplorerView(): ExplorerView {
		return this.explorerView;
	}

I
isidor 已提交
127 128
	public getOpenEditorsView(): OpenEditorsView {
		return this.openEditorsView;
129 130
	}

E
Erich Gamma 已提交
131 132
	public setVisible(visible: boolean): TPromise<void> {
		return super.setVisible(visible).then(() => {
133
			return TPromise.join(this.views.map((view) => view.setVisible(visible))).then(() => void 0);
E
Erich Gamma 已提交
134 135 136 137 138 139
		});
	}

	public focus(): void {
		super.focus();

140
		if (this.lastFocusedView && this.lastFocusedView.isExpanded() && this.hasSelectionOrFocus(this.lastFocusedView)) {
141 142 143 144
			this.lastFocusedView.focusBody();
			return;
		}

I
isidor 已提交
145 146
		if (this.hasSelectionOrFocus(this.openEditorsView)) {
			return this.openEditorsView.focusBody();
147 148
		}

149
		if (this.hasSelectionOrFocus(this.explorerView)) {
150
			return this.explorerView.focusBody();
E
Erich Gamma 已提交
151
		}
152

I
isidor 已提交
153 154
		if (this.openEditorsView && this.openEditorsView.isExpanded()) {
			return this.openEditorsView.focusBody();
155 156 157 158 159 160
		}

		if (this.explorerView && this.explorerView.isExpanded()) {
			return this.explorerView.focusBody();
		}

I
isidor 已提交
161
		return this.openEditorsView.focus();
162 163
	}

I
isidor 已提交
164
	private hasSelectionOrFocus(view: ExplorerView | OpenEditorsView | EmptyView): boolean {
165 166 167 168 169 170 171 172
		if (!view) {
			return false;
		}

		if (!view.isExpanded()) {
			return false;
		}

I
isidor 已提交
173
		if (view instanceof ExplorerView || view instanceof OpenEditorsView) {
174 175 176 177 178 179 180
			const viewer = view.getViewer();
			if (!viewer) {
				return false;
			}

			return !!viewer.getFocus() || (viewer.getSelection() && viewer.getSelection().length > 0);

181 182
		}

183
		return false;
E
Erich Gamma 已提交
184 185 186
	}

	public layout(dimension: Dimension): void {
I
isidor 已提交
187 188 189 190 191
		if (this.openEditorsVisible) {
			this.splitView.layout(dimension.height);
		} else if (this.explorerView) {
			this.explorerView.layout(dimension.height, Orientation.VERTICAL);
		}
E
Erich Gamma 已提交
192 193 194 195 196 197 198 199 200 201
	}

	public getActionRunner(): IActionRunner {
		if (!this.actionRunner) {
			this.actionRunner = new ActionRunner(this.viewletState);
		}

		return this.actionRunner;
	}

M
Maxime Quandalle 已提交
202 203
	public getOptimalWidth(): number {
		let additionalMargin = 16;
B
Benjamin Pasero 已提交
204
		let openedEditorsViewWidth = this.openEditorsView.getOptimalWidth();
M
Maxime Quandalle 已提交
205 206
		let explorerView = this.getExplorerView();
		let explorerViewWidth = explorerView ? explorerView.getOptimalWidth() : 0;
B
Benjamin Pasero 已提交
207
		let optimalWidth = Math.max(openedEditorsViewWidth, explorerViewWidth);
M
Maxime Quandalle 已提交
208 209 210
		return optimalWidth + additionalMargin;
	}

E
Erich Gamma 已提交
211 212 213 214 215 216 217 218 219
	public shutdown(): void {
		this.views.forEach((view) => view.shutdown());

		super.shutdown();
	}

	public dispose(): void {
		if (this.splitView) {
			this.splitView.dispose();
220 221
			this.splitView = null;
		}
I
isidor 已提交
222 223 224 225
		if (this.explorerView) {
			this.explorerView.dispose();
			this.explorerView = null;
		}
226 227 228 229

		if (this.focusListener) {
			this.focusListener.dispose();
			this.focusListener = null;
E
Erich Gamma 已提交
230 231 232
		}
	}
}