tocTree.ts 6.0 KB
Newer Older
R
Rob Lourens 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import * as DOM from 'vs/base/browser/dom';
R
Rob Lourens 已提交
7 8 9 10
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IObjectTreeOptions, ObjectTree } from 'vs/base/browser/ui/tree/objectTree';
import { ITreeElement, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree';
import { Iterator } from 'vs/base/common/iterator';
11
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
12
import { editorBackground } from 'vs/platform/theme/common/colorRegistry';
13
import { attachStyler } from 'vs/platform/theme/common/styler';
14
import { IThemeService } from 'vs/platform/theme/common/themeService';
R
Rob Lourens 已提交
15
import { SettingsTreeFilter } from 'vs/workbench/parts/preferences/browser/settingsTree';
16
import { ISettingsEditorViewState, SearchResultModel, SettingsTreeElement, SettingsTreeGroupElement, SettingsTreeSettingElement } from 'vs/workbench/parts/preferences/browser/settingsTreeModels';
17
import { settingsHeaderForeground } from 'vs/workbench/parts/preferences/browser/settingsWidgets';
R
Rob Lourens 已提交
18 19 20

const $ = DOM.$;

21
export class TOCTreeModel {
22

23 24 25
	private _currentSearchModel: SearchResultModel;
	private _settingsTreeRoot: SettingsTreeGroupElement;

26 27
	constructor(private _viewState: ISettingsEditorViewState) {
	}
28

29 30
	public get settingsTreeRoot(): SettingsTreeGroupElement {
		return this._settingsTreeRoot;
31 32
	}

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
	public set settingsTreeRoot(value: SettingsTreeGroupElement) {
		this._settingsTreeRoot = value;
		this.update();
	}

	public set currentSearchModel(model: SearchResultModel) {
		this._currentSearchModel = model;
		this.update();
	}

	public get children(): SettingsTreeElement[] {
		return this._settingsTreeRoot.children;
	}

	public update(): void {
48 49 50
		if (this._settingsTreeRoot) {
			this.updateGroupCount(this._settingsTreeRoot);
		}
51 52 53 54 55 56 57 58
	}

	private updateGroupCount(group: SettingsTreeGroupElement): void {
		group.children.forEach(child => {
			if (child instanceof SettingsTreeGroupElement) {
				this.updateGroupCount(child);
			}
		});
59

60 61 62
		const childCount = group.children
			.filter(child => child instanceof SettingsTreeGroupElement)
			.reduce((acc, cur) => acc + (<SettingsTreeGroupElement>cur).count, 0);
63

64
		group.count = childCount + this.getGroupCount(group);
65 66
	}

67 68 69 70 71
	private getGroupCount(group: SettingsTreeGroupElement): number {
		return group.children.filter(child => {
			if (!(child instanceof SettingsTreeSettingElement)) {
				return false;
			}
72

73
			if (this._currentSearchModel && !this._currentSearchModel.root.containsSetting(child.setting.key)) {
74 75
				return false;
			}
76 77 78 79

			// Check everything that the SettingsFilter checks except whether it's filtered by a category
			return child.matchesScope(this._viewState.settingsTarget) && child.matchesAllTags(this._viewState.tagFilters);
		}).length;
80 81 82
	}
}

R
Rob Lourens 已提交
83 84 85
const TOC_ENTRY_TEMPLATE_ID = 'settings.toc.entry';

interface ITOCEntryTemplate {
86 87
	labelElement: HTMLElement;
	countElement: HTMLElement;
R
Rob Lourens 已提交
88 89
}

R
Rob Lourens 已提交
90
export class TOCRenderer implements ITreeRenderer<SettingsTreeGroupElement, never, ITOCEntryTemplate> {
R
Rob Lourens 已提交
91

R
Rob Lourens 已提交
92
	templateId = TOC_ENTRY_TEMPLATE_ID;
R
Rob Lourens 已提交
93

R
Rob Lourens 已提交
94
	renderTemplate(container: HTMLElement): ITOCEntryTemplate {
R
Rob Lourens 已提交
95
		return {
96 97
			labelElement: DOM.append(container, $('.settings-toc-entry')),
			countElement: DOM.append(container, $('.settings-toc-count'))
R
Rob Lourens 已提交
98 99 100
		};
	}

R
Rob Lourens 已提交
101 102
	renderElement(node: ITreeNode<SettingsTreeGroupElement>, index: number, template: ITOCEntryTemplate): void {
		const element = node.element;
103
		const count = element.count;
104
		const label = element.label;
105

106 107
		DOM.toggleClass(template.labelElement, 'no-results', count === 0);
		template.labelElement.textContent = label;
108

109
		if (count) {
110 111 112
			template.countElement.textContent = ` (${count})`;
		} else {
			template.countElement.textContent = '';
113
		}
R
Rob Lourens 已提交
114 115
	}

R
Rob Lourens 已提交
116 117 118 119 120 121 122 123 124 125 126
	disposeTemplate(templateData: ITOCEntryTemplate): void {
	}
}

class TOCTreeDelegate implements IListVirtualDelegate<SettingsTreeElement> {
	getTemplateId(element: SettingsTreeElement): string {
		return TOC_ENTRY_TEMPLATE_ID;
	}

	getHeight(element: SettingsTreeElement): number {
		return 22;
R
Rob Lourens 已提交
127 128
	}
}
129

R
Rob Lourens 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
export function createTOCIterator(model: TOCTreeModel | SettingsTreeGroupElement): Iterator<ITreeElement<SettingsTreeGroupElement>> {
	const groupChildren = <SettingsTreeGroupElement[]>model.children.filter(c => c instanceof SettingsTreeGroupElement);
	const groupsIt = Iterator.fromArray(groupChildren);

	return Iterator.map(groupsIt, g => {
		return {
			element: g,
			children: g instanceof SettingsTreeGroupElement ?
				createTOCIterator(g) :
				undefined
		};
	});
}

export class TOCTree extends ObjectTree<SettingsTreeGroupElement> {
145 146 147 148
	constructor(
		container: HTMLElement,
		viewState: ISettingsEditorViewState,
		@IThemeService themeService: IThemeService,
R
Rob Lourens 已提交
149
		@IInstantiationService instantiationService: IInstantiationService
150
	) {
R
Rob Lourens 已提交
151
		// test open mode
152

153
		const filter = instantiationService.createInstance(SettingsTreeFilter, viewState);
R
Rob Lourens 已提交
154
		const options: IObjectTreeOptions<SettingsTreeGroupElement> = {
155
			filter,
R
Rob Lourens 已提交
156 157 158 159 160
			identityProvider: {
				getId(e) {
					return e.id;
				}
			}
161 162 163
		};

		super(container,
R
Rob Lourens 已提交
164 165 166
			new TOCTreeDelegate(),
			[new TOCRenderer()],
			options);
167

R
Rob Lourens 已提交
168
		const treeClass = 'settings-toc-tree';
169 170 171 172 173 174 175 176 177
		this.getHTMLElement().classList.add(treeClass);

		this.disposables.push(attachStyler(themeService, {
			listActiveSelectionBackground: editorBackground,
			listActiveSelectionForeground: settingsHeaderForeground,
			listFocusAndSelectionBackground: editorBackground,
			listFocusAndSelectionForeground: settingsHeaderForeground,
			listFocusBackground: editorBackground,
			listFocusForeground: settingsHeaderForeground,
178
			listHoverForeground: settingsHeaderForeground,
179 180 181 182 183 184 185 186
			listHoverBackground: editorBackground,
			listInactiveSelectionBackground: editorBackground,
			listInactiveSelectionForeground: settingsHeaderForeground,
		}, colors => {
			this.style(colors);
		}));
	}
}