4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
6
import { IDragAndDropData } from 'vs/base/browser/dnd' ;
7
- import { $ , addDisposableListener , append , clearNode , createStyleSheet , getWindow , h , hasParentWithClass , isActiveElement } from 'vs/base/browser/dom' ;
7
+ import { $ , append , clearNode , createStyleSheet , getWindow , h , hasParentWithClass , isActiveElement } from 'vs/base/browser/dom' ;
8
8
import { DomEmitter } from 'vs/base/browser/event' ;
9
9
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent' ;
10
10
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar' ;
@@ -26,7 +26,7 @@ import { SetMap } from 'vs/base/common/map';
26
26
import { Emitter , Event , EventBufferer , Relay } from 'vs/base/common/event' ;
27
27
import { fuzzyScore , FuzzyScore } from 'vs/base/common/filters' ;
28
28
import { KeyCode } from 'vs/base/common/keyCodes' ;
29
- import { Disposable , DisposableStore , dispose , IDisposable , MutableDisposable , toDisposable } from 'vs/base/common/lifecycle' ;
29
+ import { Disposable , DisposableStore , dispose , IDisposable , toDisposable } from 'vs/base/common/lifecycle' ;
30
30
import { clamp } from 'vs/base/common/numbers' ;
31
31
import { ScrollEvent } from 'vs/base/common/scrollable' ;
32
32
import { ISpliceable } from 'vs/base/common/sequence' ;
@@ -1457,7 +1457,6 @@ class StickyScrollWidget<T, TFilterData, TRef> implements IDisposable {
1457
1457
1458
1458
private readonly _rootDomNode : HTMLElement ;
1459
1459
private _previousState : StickyScrollState < T , TFilterData , TRef > | undefined ;
1460
- private _mouseUpTimerDisposable = new MutableDisposable ( ) ;
1461
1460
1462
1461
constructor (
1463
1462
container : HTMLElement ,
@@ -1563,50 +1562,21 @@ class StickyScrollWidget<T, TFilterData, TRef> implements IDisposable {
1563
1562
const templateData = renderer . renderTemplate ( stickyElement ) ;
1564
1563
renderer . renderElement ( nodeCopy , stickyNode . startIndex , templateData , stickyNode . height ) ;
1565
1564
1566
- const mouseListenerDisposable = this . registerMouseListeners ( stickyElement , stickyNode , currentWidgetHeight ) ;
1567
-
1568
1565
// Remove the element from the DOM when state is disposed
1569
1566
const disposable = toDisposable ( ( ) => {
1570
1567
renderer . disposeElement ( nodeCopy , stickyNode . startIndex , templateData , stickyNode . height ) ;
1571
1568
renderer . disposeTemplate ( templateData ) ;
1572
- mouseListenerDisposable . dispose ( ) ;
1573
1569
stickyElement . remove ( ) ;
1574
1570
} ) ;
1575
1571
1576
1572
return { element : stickyElement , disposable } ;
1577
1573
}
1578
1574
1579
- private registerMouseListeners ( stickyElement : HTMLElement , stickyNode : StickyScrollNode < T , TFilterData > , currentWidgetHeight : number ) : IDisposable {
1580
-
1581
- return addDisposableListener ( stickyElement , 'mouseup' , ( e : MouseEvent ) => {
1582
- const isRightClick = e . button === 2 ;
1583
- if ( isRightClick ) {
1584
- return ;
1585
- }
1586
-
1587
- if ( isMonacoCustomToggle ( e . target as HTMLElement ) || isActionItem ( e . target as HTMLElement ) ) {
1588
- return ;
1589
- }
1590
-
1591
- // Timeout 0 ensures that the tree handles the click event first
1592
- this . _mouseUpTimerDisposable . value = disposableTimeout ( ( ) => {
1593
- const elementTop = this . view . getElementTop ( stickyNode . startIndex ) ;
1594
- // We can't rely on the current sticky node's position
1595
- // because the node might be partially scrolled under the widget
1596
- const previousStickyNodeBottom = currentWidgetHeight ;
1597
- this . view . scrollTop = elementTop - previousStickyNodeBottom ;
1598
- this . view . setFocus ( [ stickyNode . startIndex ] ) ;
1599
- this . view . setSelection ( [ stickyNode . startIndex ] ) ;
1600
- } , 0 ) ;
1601
- } ) ;
1602
- }
1603
-
1604
1575
private setVisible ( visible : boolean ) : void {
1605
1576
this . _rootDomNode . style . display = visible ? 'block' : 'none' ;
1606
1577
}
1607
1578
1608
1579
dispose ( ) : void {
1609
- this . _mouseUpTimerDisposable . dispose ( ) ;
1610
1580
this . _previousState ?. dispose ( ) ;
1611
1581
this . _rootDomNode . remove ( ) ;
1612
1582
}
@@ -1791,7 +1761,11 @@ class Trait<T> {
1791
1761
1792
1762
class TreeNodeListMouseController < T , TFilterData , TRef > extends MouseController < ITreeNode < T , TFilterData > > {
1793
1763
1794
- constructor ( list : TreeNodeList < T , TFilterData , TRef > , private tree : AbstractTree < T , TFilterData , TRef > ) {
1764
+ constructor (
1765
+ list : TreeNodeList < T , TFilterData , TRef > ,
1766
+ private tree : AbstractTree < T , TFilterData , TRef > ,
1767
+ private stickyScrollProvider : ( ) => StickyScrollController < T , TFilterData , TRef > | undefined
1768
+ ) {
1795
1769
super ( list ) ;
1796
1770
}
1797
1771
@@ -1840,6 +1814,8 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
1840
1814
if ( ! this . tree . expandOnDoubleClick && e . browserEvent . detail === 2 ) {
1841
1815
return super . onViewPointer ( e ) ;
1842
1816
}
1817
+ } else {
1818
+ this . handleStickyScrollMouseEvent ( e , node ) ;
1843
1819
}
1844
1820
1845
1821
if ( node . collapsible && ( ! isStickyElement || onTwistie ) ) {
@@ -1860,6 +1836,24 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
1860
1836
}
1861
1837
}
1862
1838
1839
+ private handleStickyScrollMouseEvent ( e : IListMouseEvent < ITreeNode < T , TFilterData > > , node : ITreeNode < T , TFilterData > ) : void {
1840
+ if ( isMonacoCustomToggle ( e . browserEvent . target as HTMLElement ) || isActionItem ( e . browserEvent . target as HTMLElement ) ) {
1841
+ return ;
1842
+ }
1843
+
1844
+ const stickyScrollController = this . stickyScrollProvider ( ) ;
1845
+ if ( ! stickyScrollController ) {
1846
+ throw new Error ( 'Sticky scroll controller not found' ) ;
1847
+ }
1848
+
1849
+ const nodeIndex = this . list . indexOf ( node ) ;
1850
+ const elementScrollTop = this . list . getElementTop ( nodeIndex ) ;
1851
+ const elementTargetViewTop = stickyScrollController . nodePositionTopBelowWidget ( node ) ;
1852
+ this . tree . scrollTop = elementScrollTop - elementTargetViewTop ;
1853
+ this . list . setFocus ( [ nodeIndex ] ) ;
1854
+ this . list . setSelection ( [ nodeIndex ] ) ;
1855
+ }
1856
+
1863
1857
protected override onDoubleClick ( e : IListMouseEvent < ITreeNode < T , TFilterData > > ) : void {
1864
1858
const onTwistie = ( e . browserEvent . target as HTMLElement ) . classList . contains ( 'monaco-tl-twistie' ) ;
1865
1859
@@ -1877,6 +1871,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
1877
1871
1878
1872
interface ITreeNodeListOptions < T , TFilterData , TRef > extends IListOptions < ITreeNode < T , TFilterData > > {
1879
1873
readonly tree : AbstractTree < T , TFilterData , TRef > ;
1874
+ readonly stickyScrollProvider : ( ) => StickyScrollController < T , TFilterData , TRef > | undefined ;
1880
1875
}
1881
1876
1882
1877
/**
@@ -1899,7 +1894,7 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
1899
1894
}
1900
1895
1901
1896
protected override createMouseController ( options : ITreeNodeListOptions < T , TFilterData , TRef > ) : MouseController < ITreeNode < T , TFilterData > > {
1902
- return new TreeNodeListMouseController ( this , options . tree ) ;
1897
+ return new TreeNodeListMouseController ( this , options . tree , options . stickyScrollProvider ) ;
1903
1898
}
1904
1899
1905
1900
override splice ( start : number , deleteCount : number , elements : readonly ITreeNode < T , TFilterData > [ ] = [ ] ) : void {
@@ -2058,7 +2053,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
2058
2053
this . focus = new Trait ( ( ) => this . view . getFocusedElements ( ) [ 0 ] , _options . identityProvider ) ;
2059
2054
this . selection = new Trait ( ( ) => this . view . getSelectedElements ( ) [ 0 ] , _options . identityProvider ) ;
2060
2055
this . anchor = new Trait ( ( ) => this . view . getAnchorElement ( ) , _options . identityProvider ) ;
2061
- this . view = new TreeNodeList ( _user , container , this . treeDelegate , this . renderers , this . focus , this . selection , this . anchor , { ...asListOptions ( ( ) => this . model , _options ) , tree : this } ) ;
2056
+ this . view = new TreeNodeList ( _user , container , this . treeDelegate , this . renderers , this . focus , this . selection , this . anchor , { ...asListOptions ( ( ) => this . model , _options ) , tree : this , stickyScrollProvider : ( ) => this . stickyScrollController } ) ;
2062
2057
2063
2058
this . model = this . createModel ( _user , this . view , _options ) ;
2064
2059
onDidChangeCollapseStateRelay . input = this . model . onDidChangeCollapseState ;
0 commit comments