protected createEditor()

in src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts [247:483]


	protected createEditor(parent: HTMLElement): void {
		addClass(parent, 'runtime-extensions-editor');

		const TEMPLATE_ID = 'runtimeExtensionElementTemplate';

		const delegate = new class implements IListVirtualDelegate<IRuntimeExtension>{
			getHeight(element: IRuntimeExtension): number {
				return 62;
			}
			getTemplateId(element: IRuntimeExtension): string {
				return TEMPLATE_ID;
			}
		};

		interface IRuntimeExtensionTemplateData {
			root: HTMLElement;
			element: HTMLElement;
			icon: HTMLImageElement;
			name: HTMLElement;
			version: HTMLElement;
			msgContainer: HTMLElement;
			actionbar: ActionBar;
			activationTime: HTMLElement;
			profileTime: HTMLElement;
			disposables: IDisposable[];
			elementDisposables: IDisposable[];
		}

		const renderer: IListRenderer<IRuntimeExtension, IRuntimeExtensionTemplateData> = {
			templateId: TEMPLATE_ID,
			renderTemplate: (root: HTMLElement): IRuntimeExtensionTemplateData => {
				const element = append(root, $('.extension'));
				const iconContainer = append(element, $('.icon-container'));
				const icon = append(iconContainer, $<HTMLImageElement>('img.icon'));

				const desc = append(element, $('div.desc'));
				const headerContainer = append(desc, $('.header-container'));
				const header = append(headerContainer, $('.header'));
				const name = append(header, $('div.name'));
				const version = append(header, $('span.version'));

				const msgContainer = append(desc, $('div.msg'));

				const actionbar = new ActionBar(desc, { animated: false });
				actionbar.onDidRun(({ error }) => error && this._notificationService.error(error));


				const timeContainer = append(element, $('.time'));
				const activationTime = append(timeContainer, $('div.activation-time'));
				const profileTime = append(timeContainer, $('div.profile-time'));

				const disposables = [actionbar];

				return {
					root,
					element,
					icon,
					name,
					version,
					actionbar,
					activationTime,
					profileTime,
					msgContainer,
					disposables,
					elementDisposables: [],
				};
			},

			renderElement: (element: IRuntimeExtension, index: number, data: IRuntimeExtensionTemplateData): void => {

				data.elementDisposables = dispose(data.elementDisposables);

				toggleClass(data.root, 'odd', index % 2 === 1);

				const onError = Event.once(domEvent(data.icon, 'error'));
				onError(() => data.icon.src = element.marketplaceInfo.iconUrlFallback, null, data.elementDisposables);
				data.icon.src = element.marketplaceInfo.iconUrl;

				if (!data.icon.complete) {
					data.icon.style.visibility = 'hidden';
					data.icon.onload = () => data.icon.style.visibility = 'inherit';
				} else {
					data.icon.style.visibility = 'inherit';
				}
				data.name.textContent = element.marketplaceInfo ? element.marketplaceInfo.displayName : element.description.displayName || '';
				data.version.textContent = element.description.version;

				const activationTimes = element.status.activationTimes!;
				let syncTime = activationTimes.codeLoadingTime + activationTimes.activateCallTime;
				data.activationTime.textContent = activationTimes.activationReason.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`;

				data.actionbar.clear();
				if (element.unresponsiveProfile) {
					data.actionbar.push(this._instantiationService.createInstance(SlowExtensionAction, element.description, element.unresponsiveProfile), { icon: true, label: true });
				}
				if (isNonEmptyArray(element.status.runtimeErrors)) {
					data.actionbar.push(new ReportExtensionIssueAction(element, this._openerService, this._clipboardService, this._productService), { icon: true, label: true });
				}

				let title: string;
				const activationId = activationTimes.activationReason.extensionId.value;
				const activationEvent = activationTimes.activationReason.activationEvent;
				if (activationEvent === '*') {
					title = nls.localize('starActivation', "Activated by {0} on start-up", activationId);
				} else if (/^workspaceContains:/.test(activationEvent)) {
					let fileNameOrGlob = activationEvent.substr('workspaceContains:'.length);
					if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) {
						title = nls.localize({
							key: 'workspaceContainsGlobActivation',
							comment: [
								'{0} will be a glob pattern'
							]
						}, "Activated by {1} because a file matching {1} exists in your workspace", fileNameOrGlob, activationId);
					} else {
						title = nls.localize({
							key: 'workspaceContainsFileActivation',
							comment: [
								'{0} will be a file name'
							]
						}, "Activated by {1} because file {0} exists in your workspace", fileNameOrGlob, activationId);
					}
				} else if (/^workspaceContainsTimeout:/.test(activationEvent)) {
					const glob = activationEvent.substr('workspaceContainsTimeout:'.length);
					title = nls.localize({
						key: 'workspaceContainsTimeout',
						comment: [
							'{0} will be a glob pattern'
						]
					}, "Activated by {1} because searching for {0} took too long", glob, activationId);
				} else if (activationEvent === 'onStartupFinished') {
					title = nls.localize({
						key: 'startupFinishedActivation',
						comment: [
							'This refers to an extension. {0} will be an activation event.'
						]
					}, "Activated by {0} after start-up finished", activationId);
				} else if (/^onLanguage:/.test(activationEvent)) {
					let language = activationEvent.substr('onLanguage:'.length);
					title = nls.localize('languageActivation', "Activated by {1} because you opened a {0} file", language, activationId);
				} else {
					title = nls.localize({
						key: 'workspaceGenericActivation',
						comment: [
							'The {0} placeholder will be an activation event, like e.g. \'language:typescript\', \'debug\', etc.'
						]
					}, "Activated by {1} on {0}", activationEvent, activationId);
				}
				data.activationTime.title = title;

				clearNode(data.msgContainer);

				if (this._extensionHostProfileService.getUnresponsiveProfile(element.description.identifier)) {
					const el = $('span');
					el.innerHTML = renderCodicons(escape(` $(alert) Unresponsive`));
					el.title = nls.localize('unresponsive.title', "Extension has caused the extension host to freeze.");
					data.msgContainer.appendChild(el);
				}

				if (isNonEmptyArray(element.status.runtimeErrors)) {
					const el = $('span');
					el.innerHTML = renderCodicons(escape(`$(bug) ${nls.localize('errors', "{0} uncaught errors", element.status.runtimeErrors.length)}`));
					data.msgContainer.appendChild(el);
				}

				if (element.status.messages && element.status.messages.length > 0) {
					const el = $('span');
					el.innerHTML = renderCodicons(escape(`$(alert) ${element.status.messages[0].message}`));
					data.msgContainer.appendChild(el);
				}

				if (element.description.extensionLocation.scheme !== 'file') {
					const el = $('span');
					el.innerHTML = renderCodicons(escape(`$(remote) ${element.description.extensionLocation.authority}`));
					data.msgContainer.appendChild(el);

					const hostLabel = this._labelService.getHostLabel(REMOTE_HOST_SCHEME, this._environmentService.configuration.remoteAuthority);
					if (hostLabel) {
						el.innerHTML = renderCodicons(escape(`$(remote) ${hostLabel}`));
					}
				}

				if (this._profileInfo && element.profileInfo) {
					data.profileTime.textContent = `Profile: ${(element.profileInfo.totalTime / 1000).toFixed(2)}ms`;
				} else {
					data.profileTime.textContent = '';
				}

			},

			disposeTemplate: (data: IRuntimeExtensionTemplateData): void => {
				data.disposables = dispose(data.disposables);
			}
		};

		this._list = <WorkbenchList<IRuntimeExtension>>this._instantiationService.createInstance(WorkbenchList,
			'RuntimeExtensions',
			parent, delegate, [renderer], {
			multipleSelectionSupport: false,
			setRowLineHeight: false,
			horizontalScrolling: false,
			overrideStyles: {
				listBackground: editorBackground
			},
			accessibilityProvider: new RuntimeExtensionsEditorAccessibilityProvider()
		});

		this._list.splice(0, this._list.length, this._elements || undefined);

		this._list.onContextMenu((e) => {
			if (!e.element) {
				return;
			}

			const actions: IAction[] = [];

			actions.push(new ReportExtensionIssueAction(e.element, this._openerService, this._clipboardService, this._productService));
			actions.push(new Separator());

			if (e.element.marketplaceInfo) {
				actions.push(new Action('runtimeExtensionsEditor.action.disableWorkspace', nls.localize('disable workspace', "Disable (Workspace)"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledWorkspace)));
				actions.push(new Action('runtimeExtensionsEditor.action.disable', nls.localize('disable', "Disable"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledGlobally)));
				actions.push(new Separator());
			}
			const state = this._extensionHostProfileService.state;
			if (state === ProfileSessionState.Running) {
				actions.push(this._instantiationService.createInstance(StopExtensionHostProfileAction, StopExtensionHostProfileAction.ID, StopExtensionHostProfileAction.LABEL));
			} else {
				actions.push(this._instantiationService.createInstance(StartExtensionHostProfileAction, StartExtensionHostProfileAction.ID, StartExtensionHostProfileAction.LABEL));
			}
			actions.push(this.saveExtensionHostProfileAction);

			this._contextMenuService.showContextMenu({
				getAnchor: () => e.anchor,
				getActions: () => actions
			});
		});
	}