@@ -630,79 +630,16 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
630630 this . _register ( focusTracker . onDidBlur ( ( ) => this . focused = false ) ) ;
631631 }
632632
633- private updateCheckboxes ( items : ITreeItem [ ] ) {
634- const additionalItems : ITreeItem [ ] = [ ] ;
635-
636- if ( ! this . manuallyManageCheckboxes ) {
637- for ( const item of items ) {
638- if ( item . checkbox !== undefined ) {
639-
640- function checkChildren ( currentItem : ITreeItem ) {
641- for ( const child of ( currentItem . children ?? [ ] ) ) {
642- if ( ( child . checkbox !== undefined ) && ( currentItem . checkbox !== undefined ) && ( child . checkbox . isChecked !== currentItem . checkbox . isChecked ) ) {
643- child . checkbox . isChecked = currentItem . checkbox . isChecked ;
644- additionalItems . push ( child ) ;
645- checkChildren ( child ) ;
646- }
647- }
648- }
649- checkChildren ( item ) ;
650-
651- const visitedParents : Set < ITreeItem > = new Set ( ) ;
652- function checkParents ( currentItem : ITreeItem ) {
653- if ( currentItem . parent && ( currentItem . parent . checkbox !== undefined ) && currentItem . parent . children ) {
654- if ( visitedParents . has ( currentItem . parent ) ) {
655- return ;
656- } else {
657- visitedParents . add ( currentItem . parent ) ;
658- }
659-
660- let someUnchecked = false ;
661- let someChecked = false ;
662- for ( const child of currentItem . parent . children ) {
663- if ( someUnchecked && someChecked ) {
664- break ;
665- }
666- if ( child . checkbox !== undefined ) {
667- if ( child . checkbox . isChecked ) {
668- someChecked = true ;
669- } else {
670- someUnchecked = true ;
671- }
672- }
673- }
674- if ( someChecked && ! someUnchecked && ( currentItem . parent . checkbox . isChecked !== true ) ) {
675- currentItem . parent . checkbox . isChecked = true ;
676- additionalItems . push ( currentItem . parent ) ;
677- checkParents ( currentItem . parent ) ;
678- } else if ( someUnchecked && ( currentItem . parent . checkbox . isChecked !== false ) ) {
679- currentItem . parent . checkbox . isChecked = false ;
680- additionalItems . push ( currentItem . parent ) ;
681- checkParents ( currentItem . parent ) ;
682- }
683- }
684- }
685- checkParents ( item ) ;
686- }
687- }
688- }
689- items = items . concat ( additionalItems ) ;
690- items . forEach ( item => this . tree ?. rerender ( item ) ) ;
691- this . _onDidChangeCheckboxState . fire ( items ) ;
692- }
693-
694-
695633 protected createTree ( ) {
696634 const actionViewItemProvider = createActionViewItem . bind ( undefined , this . instantiationService ) ;
697635 const treeMenus = this . _register ( this . instantiationService . createInstance ( TreeMenus , this . id ) ) ;
698636 this . treeLabels = this . _register ( this . instantiationService . createInstance ( ResourceLabels , this ) ) ;
699637 const dataSource = this . instantiationService . createInstance ( TreeDataSource , this , < T > ( task : Promise < T > ) => this . progressService . withProgress ( { location : this . id } , ( ) => task ) ) ;
700638 const aligner = new Aligner ( this . themeService ) ;
701639 const checkboxStateHandler = this . _register ( new CheckboxStateHandler ( ) ) ;
702- this . _register ( checkboxStateHandler . onDidChangeCheckboxState ( items => {
703- this . updateCheckboxes ( items ) ;
704- } ) ) ;
705- const renderer = this . instantiationService . createInstance ( TreeRenderer , this . id , treeMenus , this . treeLabels , actionViewItemProvider , aligner , checkboxStateHandler ) ;
640+ const renderer = this . instantiationService . createInstance ( TreeRenderer , this . id , treeMenus , this . treeLabels , actionViewItemProvider , aligner , checkboxStateHandler , this . manuallyManageCheckboxes ) ;
641+ this . _register ( renderer . onDidChangeCheckboxState ( e => this . _onDidChangeCheckboxState . fire ( e ) ) ) ;
642+
706643 const widgetAriaLabel = this . _title ;
707644
708645 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<ITreeItem, FuzzyS
11251062 static readonly ITEM_HEIGHT = 22 ;
11261063 static readonly TREE_TEMPLATE_ID = 'treeExplorer' ;
11271064
1065+ private readonly _onDidChangeCheckboxState : Emitter < readonly ITreeItem [ ] > = this . _register ( new Emitter < readonly ITreeItem [ ] > ( ) ) ;
1066+ readonly onDidChangeCheckboxState : Event < readonly ITreeItem [ ] > = this . _onDidChangeCheckboxState . event ;
1067+
11281068 private _actionRunner : MultipleSelectionActionRunner | undefined ;
11291069 private _hoverDelegate : IHoverDelegate ;
11301070 private _hasCheckbox : boolean = false ;
1131- private _renderedElements = new Map < ITreeNode < ITreeItem , FuzzyScore > , ITreeExplorerTemplateData > ( ) ;
1071+ private _renderedElements = new Map < string , { original : ITreeNode < ITreeItem , FuzzyScore > ; rendered : ITreeExplorerTemplateData } > ( ) ; // tree item handle to template data
11321072
11331073 constructor (
11341074 private treeViewId : string ,
@@ -1137,6 +1077,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
11371077 private actionViewItemProvider : IActionViewItemProvider ,
11381078 private aligner : Aligner ,
11391079 private checkboxStateHandler : CheckboxStateHandler ,
1080+ private readonly manuallyManageCheckboxes : boolean ,
11401081 @IThemeService private readonly themeService : IThemeService ,
11411082 @IConfigurationService private readonly configurationService : IConfigurationService ,
11421083 @ILabelService private readonly labelService : ILabelService ,
@@ -1151,6 +1092,9 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
11511092 } ;
11521093 this . _register ( this . themeService . onDidFileIconThemeChange ( ( ) => this . rerender ( ) ) ) ;
11531094 this . _register ( this . themeService . onDidColorThemeChange ( ( ) => this . rerender ( ) ) ) ;
1095+ this . _register ( checkboxStateHandler . onDidChangeCheckboxState ( items => {
1096+ this . updateCheckboxes ( items ) ;
1097+ } ) ) ;
11541098 }
11551099
11561100 get templateId ( ) : string {
@@ -1302,7 +1246,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
13021246 this . treeViewsService . addRenderedTreeItemElement ( node , templateData . container ) ;
13031247
13041248 // remember rendered element
1305- this . _renderedElements . set ( element , templateData ) ;
1249+ this . _renderedElements . set ( element . element . handle , { original : element , rendered : templateData } ) ;
13061250 }
13071251
13081252 private rerender ( ) {
@@ -1312,8 +1256,8 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
13121256 for ( const key of keys ) {
13131257 const value = this . _renderedElements . get ( key ) ;
13141258 if ( value ) {
1315- this . disposeElement ( key , 0 , value ) ;
1316- this . renderElement ( key , 0 , value ) ;
1259+ this . disposeElement ( value . original , 0 , value . rendered ) ;
1260+ this . renderElement ( value . original , 0 , value . rendered ) ;
13171261 }
13181262 }
13191263 }
@@ -1381,10 +1325,76 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
13811325 return node . collapsibleState === TreeItemCollapsibleState . Collapsed || node . collapsibleState === TreeItemCollapsibleState . Expanded ? FileKind . FOLDER : FileKind . FILE ;
13821326 }
13831327
1328+ private updateCheckboxes ( items : ITreeItem [ ] ) {
1329+ const additionalItems : ITreeItem [ ] = [ ] ;
1330+
1331+ if ( ! this . manuallyManageCheckboxes ) {
1332+ for ( const item of items ) {
1333+ if ( item . checkbox !== undefined ) {
1334+
1335+ function checkChildren ( currentItem : ITreeItem ) {
1336+ for ( const child of ( currentItem . children ?? [ ] ) ) {
1337+ if ( ( child . checkbox !== undefined ) && ( currentItem . checkbox !== undefined ) && ( child . checkbox . isChecked !== currentItem . checkbox . isChecked ) ) {
1338+ child . checkbox . isChecked = currentItem . checkbox . isChecked ;
1339+ additionalItems . push ( child ) ;
1340+ checkChildren ( child ) ;
1341+ }
1342+ }
1343+ }
1344+ checkChildren ( item ) ;
1345+
1346+ const visitedParents : Set < ITreeItem > = new Set ( ) ;
1347+ function checkParents ( currentItem : ITreeItem ) {
1348+ if ( currentItem . parent && ( currentItem . parent . checkbox !== undefined ) && currentItem . parent . children ) {
1349+ if ( visitedParents . has ( currentItem . parent ) ) {
1350+ return ;
1351+ } else {
1352+ visitedParents . add ( currentItem . parent ) ;
1353+ }
1354+
1355+ let someUnchecked = false ;
1356+ let someChecked = false ;
1357+ for ( const child of currentItem . parent . children ) {
1358+ if ( someUnchecked && someChecked ) {
1359+ break ;
1360+ }
1361+ if ( child . checkbox !== undefined ) {
1362+ if ( child . checkbox . isChecked ) {
1363+ someChecked = true ;
1364+ } else {
1365+ someUnchecked = true ;
1366+ }
1367+ }
1368+ }
1369+ if ( someChecked && ! someUnchecked && ( currentItem . parent . checkbox . isChecked !== true ) ) {
1370+ currentItem . parent . checkbox . isChecked = true ;
1371+ additionalItems . push ( currentItem . parent ) ;
1372+ checkParents ( currentItem . parent ) ;
1373+ } else if ( someUnchecked && ( currentItem . parent . checkbox . isChecked !== false ) ) {
1374+ currentItem . parent . checkbox . isChecked = false ;
1375+ additionalItems . push ( currentItem . parent ) ;
1376+ checkParents ( currentItem . parent ) ;
1377+ }
1378+ }
1379+ }
1380+ checkParents ( item ) ;
1381+ }
1382+ }
1383+ }
1384+ items = items . concat ( additionalItems ) ;
1385+ items . forEach ( item => {
1386+ const renderedItem = this . _renderedElements . get ( item . handle ) ;
1387+ if ( renderedItem ) {
1388+ renderedItem . rendered . checkbox ?. render ( item ) ;
1389+ }
1390+ } ) ;
1391+ this . _onDidChangeCheckboxState . fire ( items ) ;
1392+ }
1393+
13841394 disposeElement ( resource : ITreeNode < ITreeItem , FuzzyScore > , index : number , templateData : ITreeExplorerTemplateData ) : void {
13851395 templateData . elementDisposable . clear ( ) ;
13861396
1387- this . _renderedElements . delete ( resource ) ;
1397+ this . _renderedElements . delete ( resource . element . handle ) ;
13881398 this . treeViewsService . removeRenderedTreeItemElement ( resource . element ) ;
13891399
13901400 templateData . checkbox ?. dispose ( ) ;
0 commit comments