diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index df837b853b2..5cacc80e6ba 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -630,68 +630,6 @@ abstract class AbstractTreeView extends Disposable implements ITreeView { this._register(focusTracker.onDidBlur(() => this.focused = false)); } - private updateCheckboxes(items: ITreeItem[]) { - const additionalItems: ITreeItem[] = []; - - if (!this.manuallyManageCheckboxes) { - for (const item of items) { - if (item.checkbox !== undefined) { - - function checkChildren(currentItem: ITreeItem) { - for (const child of (currentItem.children ?? [])) { - if ((child.checkbox !== undefined) && (currentItem.checkbox !== undefined) && (child.checkbox.isChecked !== currentItem.checkbox.isChecked)) { - child.checkbox.isChecked = currentItem.checkbox.isChecked; - additionalItems.push(child); - checkChildren(child); - } - } - } - checkChildren(item); - - const visitedParents: Set = new Set(); - function checkParents(currentItem: ITreeItem) { - if (currentItem.parent && (currentItem.parent.checkbox !== undefined) && currentItem.parent.children) { - if (visitedParents.has(currentItem.parent)) { - return; - } else { - visitedParents.add(currentItem.parent); - } - - let someUnchecked = false; - let someChecked = false; - for (const child of currentItem.parent.children) { - if (someUnchecked && someChecked) { - break; - } - if (child.checkbox !== undefined) { - if (child.checkbox.isChecked) { - someChecked = true; - } else { - someUnchecked = true; - } - } - } - if (someChecked && !someUnchecked && (currentItem.parent.checkbox.isChecked !== true)) { - currentItem.parent.checkbox.isChecked = true; - additionalItems.push(currentItem.parent); - checkParents(currentItem.parent); - } else if (someUnchecked && (currentItem.parent.checkbox.isChecked !== false)) { - currentItem.parent.checkbox.isChecked = false; - additionalItems.push(currentItem.parent); - checkParents(currentItem.parent); - } - } - } - checkParents(item); - } - } - } - items = items.concat(additionalItems); - items.forEach(item => this.tree?.rerender(item)); - this._onDidChangeCheckboxState.fire(items); - } - - protected createTree() { const actionViewItemProvider = createActionViewItem.bind(undefined, this.instantiationService); const treeMenus = this._register(this.instantiationService.createInstance(TreeMenus, this.id)); @@ -699,10 +637,9 @@ abstract class AbstractTreeView extends Disposable implements ITreeView { const dataSource = this.instantiationService.createInstance(TreeDataSource, this, (task: Promise) => this.progressService.withProgress({ location: this.id }, () => task)); const aligner = new Aligner(this.themeService); const checkboxStateHandler = this._register(new CheckboxStateHandler()); - this._register(checkboxStateHandler.onDidChangeCheckboxState(items => { - this.updateCheckboxes(items); - })); - const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, treeMenus, this.treeLabels, actionViewItemProvider, aligner, checkboxStateHandler); + const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, treeMenus, this.treeLabels, actionViewItemProvider, aligner, checkboxStateHandler, this.manuallyManageCheckboxes); + this._register(renderer.onDidChangeCheckboxState(e => this._onDidChangeCheckboxState.fire(e))); + const widgetAriaLabel = this._title; this.tree = this._register(this.instantiationService.createInstance(Tree, this.id, this.treeContainer!, new TreeViewDelegate(), [renderer], @@ -1125,10 +1062,13 @@ class TreeRenderer extends Disposable implements ITreeRenderer = this._register(new Emitter()); + readonly onDidChangeCheckboxState: Event = this._onDidChangeCheckboxState.event; + private _actionRunner: MultipleSelectionActionRunner | undefined; private _hoverDelegate: IHoverDelegate; private _hasCheckbox: boolean = false; - private _renderedElements = new Map, ITreeExplorerTemplateData>(); + private _renderedElements = new Map; rendered: ITreeExplorerTemplateData }>(); // tree item handle to template data constructor( private treeViewId: string, @@ -1137,6 +1077,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer this.rerender())); this._register(this.themeService.onDidColorThemeChange(() => this.rerender())); + this._register(checkboxStateHandler.onDidChangeCheckboxState(items => { + this.updateCheckboxes(items); + })); } get templateId(): string { @@ -1302,7 +1246,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer = new Set(); + function checkParents(currentItem: ITreeItem) { + if (currentItem.parent && (currentItem.parent.checkbox !== undefined) && currentItem.parent.children) { + if (visitedParents.has(currentItem.parent)) { + return; + } else { + visitedParents.add(currentItem.parent); + } + + let someUnchecked = false; + let someChecked = false; + for (const child of currentItem.parent.children) { + if (someUnchecked && someChecked) { + break; + } + if (child.checkbox !== undefined) { + if (child.checkbox.isChecked) { + someChecked = true; + } else { + someUnchecked = true; + } + } + } + if (someChecked && !someUnchecked && (currentItem.parent.checkbox.isChecked !== true)) { + currentItem.parent.checkbox.isChecked = true; + additionalItems.push(currentItem.parent); + checkParents(currentItem.parent); + } else if (someUnchecked && (currentItem.parent.checkbox.isChecked !== false)) { + currentItem.parent.checkbox.isChecked = false; + additionalItems.push(currentItem.parent); + checkParents(currentItem.parent); + } + } + } + checkParents(item); + } + } + } + items = items.concat(additionalItems); + items.forEach(item => { + const renderedItem = this._renderedElements.get(item.handle); + if (renderedItem) { + renderedItem.rendered.checkbox?.render(item); + } + }); + this._onDidChangeCheckboxState.fire(items); + } + disposeElement(resource: ITreeNode, index: number, templateData: ITreeExplorerTemplateData): void { templateData.elementDisposable.clear(); - this._renderedElements.delete(resource); + this._renderedElements.delete(resource.element.handle); this.treeViewsService.removeRenderedTreeItemElement(resource.element); templateData.checkbox?.dispose();