listWidget.ts 3.8 KB
Newer Older
J
Joao Moreno 已提交
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.
 *--------------------------------------------------------------------------------------------*/

import 'vs/css!./list';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { toggleClass } from 'vs/base/browser/dom';
J
Joao Moreno 已提交
9
import { IDelegate, IRenderer } from './list';
J
Joao Moreno 已提交
10 11 12 13 14 15 16 17 18 19 20 21
import { ListView } from './listView';

interface ITraitTemplateData<D> {
	container: HTMLElement;
	data: D;
}

class TraitRenderer<T, D> implements IRenderer<T, ITraitTemplateData<D>>
{
	private elements: { [id: string]: T };

	constructor(
J
Joao Moreno 已提交
22
		private controller: TraitController,
J
Joao Moreno 已提交
23 24 25 26 27 28 29 30 31 32 33 34
		private renderer: IRenderer<T,D>
	) {}

	public get templateId(): string {
		return this.renderer.templateId;
	}

	renderTemplate(container: HTMLElement): ITraitTemplateData<D> {
		const data = this.renderer.renderTemplate(container);
		return { container, data };
	}

J
Joao Moreno 已提交
35 36 37
	renderElement(element: T, index: number, templateData: ITraitTemplateData<D>): void {
		toggleClass(templateData.container, this.controller.trait, this.controller.contains(index));
		this.renderer.renderElement(element, index, templateData.data);
J
Joao Moreno 已提交
38 39 40 41 42 43 44
	}

	disposeTemplate(templateData: ITraitTemplateData<D>): void {
		return this.renderer.disposeTemplate(templateData.data);
	}
}

J
Joao Moreno 已提交
45
class TraitController {
J
Joao Moreno 已提交
46

J
Joao Moreno 已提交
47
	private indexes: number[];
J
Joao Moreno 已提交
48

J
Joao Moreno 已提交
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
	constructor(private _trait: string) {
		this.indexes = [];
	}

	splice(start: number, deleteCount: number, insertCount: number): void {
		const diff = insertCount - deleteCount;
		const end = start + deleteCount;
		const indexes = [];

		for (const index of indexes) {
			if (index >= start && index < end) {
				continue;
			}

			indexes.push(index > start ? index + diff : index);
		}

		this.indexes = indexes;
J
Joao Moreno 已提交
67 68 69 70 71 72
	}

	get trait(): string {
		return this._trait;
	}

J
Joao Moreno 已提交
73 74 75 76
	set(indexes: number[]): number[] {
		const result = this.indexes;
		this.indexes = indexes;
		return result;
J
Joao Moreno 已提交
77 78
	}

J
Joao Moreno 已提交
79 80 81
	add(index: number): void {
		if (this.contains(index)) {
			return;
J
Joao Moreno 已提交
82
		}
J
Joao Moreno 已提交
83 84

		this.indexes.push(index);
J
Joao Moreno 已提交
85 86
	}

J
Joao Moreno 已提交
87 88
	remove(index: number): void {
		this.indexes = this.indexes.filter(i => i === index);
J
Joao Moreno 已提交
89 90
	}

J
Joao Moreno 已提交
91 92
	contains(index: number): boolean {
		return this.indexes.some(i => i === index);
J
Joao Moreno 已提交
93 94
	}

J
Joao Moreno 已提交
95
	wrapRenderer<T, D>(renderer: IRenderer<T, D>): IRenderer<T, ITraitTemplateData<D>> {
J
Joao Moreno 已提交
96 97 98 99 100 101 102
		return new TraitRenderer<T, D>(this, renderer);
	}
}

export class List<T> implements IDisposable {

	private view: ListView<T>;
J
Joao Moreno 已提交
103 104
	private focus: TraitController;
	private selection: TraitController;
J
Joao Moreno 已提交
105 106 107 108

	constructor(
		container: HTMLElement,
		delegate: IDelegate<T>,
J
Joao Moreno 已提交
109
		renderers: IRenderer<T, any>[]
J
Joao Moreno 已提交
110
	) {
J
Joao Moreno 已提交
111 112
		this.focus = new TraitController('focused');
		this.selection = new TraitController('selected');
J
Joao Moreno 已提交
113 114 115 116 117 118 119 120 121 122 123

		renderers = renderers.map(r => {
			r = this.focus.wrapRenderer(r);
			r = this.selection.wrapRenderer(r);
			return r;
		});

		this.view = new ListView(container, delegate, renderers);
	}

	splice(start: number, deleteCount: number, ...elements: T[]): void {
J
Joao Moreno 已提交
124 125 126
		this.focus.splice(start, deleteCount, elements.length);
		this.selection.splice(start, deleteCount, elements.length);
		this.view.splice(start, deleteCount, ...elements);
J
Joao Moreno 已提交
127 128 129 130 131 132 133 134 135 136
	}

	get length(): number {
		return this.view.length;
	}

	layout(height?: number): void {
		this.view.layout(height);
	}

J
Joao Moreno 已提交
137 138 139
	setSelection(...indexes: number[]): void {
		indexes = indexes.concat(this.selection.set(indexes));
		indexes.forEach(i => this.view.splice(i, 1, this.view.element(i)));
J
Joao Moreno 已提交
140 141
	}

J
Joao Moreno 已提交
142 143 144
	setFocus(...indexes: number[]): void {
		indexes = indexes.concat(this.focus.set(indexes));
		indexes.forEach(i => this.view.splice(i, 1, this.view.element(i)));
J
Joao Moreno 已提交
145 146 147 148 149 150
	}

	dispose(): void {
		this.view = dispose(this.view);
	}
}