@@ -12,10 +12,11 @@ public class Welcome : ObservableObject
1212 {
1313 public static Welcome Instance => _instance ;
1414
15- public AvaloniaList < RepositoryNode > RepositoryNodes
15+ public AvaloniaList < RepositoryNode > Rows
1616 {
17- get => Preference . Instance . RepositoryNodes ;
18- }
17+ get ;
18+ private set ;
19+ } = [ ] ;
1920
2021 public string SearchFilter
2122 {
@@ -27,6 +28,60 @@ public string SearchFilter
2728 }
2829 }
2930
31+ public Welcome ( )
32+ {
33+ Refresh ( ) ;
34+ }
35+
36+ public void Refresh ( )
37+ {
38+ if ( string . IsNullOrWhiteSpace ( _searchFilter ) )
39+ {
40+ foreach ( var node in Preference . Instance . RepositoryNodes )
41+ ResetVisibility ( node ) ;
42+ }
43+ else
44+ {
45+ foreach ( var node in Preference . Instance . RepositoryNodes )
46+ SetVisibilityBySearch ( node ) ;
47+ }
48+
49+ var rows = new List < RepositoryNode > ( ) ;
50+ MakeTreeRows ( rows , Preference . Instance . RepositoryNodes ) ;
51+ Rows . Clear ( ) ;
52+ Rows . AddRange ( rows ) ;
53+ }
54+
55+ public void ToggleNodeIsExpanded ( RepositoryNode node )
56+ {
57+ node . IsExpanded = ! node . IsExpanded ;
58+
59+ var depth = node . Depth ;
60+ var idx = Rows . IndexOf ( node ) ;
61+ if ( idx == - 1 )
62+ return ;
63+
64+ if ( node . IsExpanded )
65+ {
66+ var subrows = new List < RepositoryNode > ( ) ;
67+ MakeTreeRows ( subrows , node . SubNodes , depth + 1 ) ;
68+ Rows . InsertRange ( idx + 1 , subrows ) ;
69+ }
70+ else
71+ {
72+ var removeCount = 0 ;
73+ for ( int i = idx + 1 ; i < Rows . Count ; i ++ )
74+ {
75+ var row = Rows [ i ] ;
76+ if ( row . Depth <= depth )
77+ break ;
78+
79+ removeCount ++ ;
80+ }
81+ Rows . RemoveRange ( idx + 1 , removeCount ) ;
82+ }
83+ }
84+
3085 public void InitRepository ( string path , RepositoryNode parent )
3186 {
3287 if ( ! Preference . Instance . IsGitConfigured ( ) )
@@ -36,9 +91,7 @@ public void InitRepository(string path, RepositoryNode parent)
3691 }
3792
3893 if ( PopupHost . CanCreatePopup ( ) )
39- {
4094 PopupHost . ShowPopup ( new Init ( path , parent ) ) ;
41- }
4295 }
4396
4497 public void Clone ( )
@@ -75,30 +128,7 @@ public void AddRootNode()
75128 public void MoveNode ( RepositoryNode from , RepositoryNode to )
76129 {
77130 Preference . Instance . MoveNode ( from , to ) ;
78- }
79-
80- public RepositoryNode GetPrevVisible ( RepositoryNode node )
81- {
82- var visibleRows = new List < RepositoryNode > ( ) ;
83- CollectVisibleRows ( visibleRows , RepositoryNodes ) ;
84-
85- var idx = visibleRows . IndexOf ( node ) ;
86- if ( idx <= 1 )
87- return null ;
88-
89- return visibleRows [ idx - 1 ] ;
90- }
91-
92- public RepositoryNode GetNextVisible ( RepositoryNode node )
93- {
94- var visibleRows = new List < RepositoryNode > ( ) ;
95- CollectVisibleRows ( visibleRows , RepositoryNodes ) ;
96-
97- var idx = visibleRows . IndexOf ( node ) ;
98- if ( idx < 0 || idx >= visibleRows . Count - 1 )
99- return null ;
100-
101- return visibleRows [ idx + 1 ] ;
131+ Refresh ( ) ;
102132 }
103133
104134 public ContextMenu CreateContextMenu ( RepositoryNode node )
@@ -178,20 +208,6 @@ public ContextMenu CreateContextMenu(RepositoryNode node)
178208 return menu ;
179209 }
180210
181- private void Refresh ( )
182- {
183- if ( string . IsNullOrWhiteSpace ( _searchFilter ) )
184- {
185- foreach ( var node in RepositoryNodes )
186- ResetVisibility ( node ) ;
187- }
188- else
189- {
190- foreach ( var node in RepositoryNodes )
191- SetVisibilityBySearch ( node ) ;
192- }
193- }
194-
195211 private void ResetVisibility ( RepositoryNode node )
196212 {
197213 node . IsVisible = true ;
@@ -226,6 +242,23 @@ private void SetVisibilityBySearch(RepositoryNode node)
226242 }
227243 }
228244
245+ private void MakeTreeRows ( List < RepositoryNode > rows , AvaloniaList < RepositoryNode > nodes , int depth = 0 )
246+ {
247+ foreach ( var node in nodes )
248+ {
249+ if ( ! node . IsVisible )
250+ continue ;
251+
252+ node . Depth = depth ;
253+ rows . Add ( node ) ;
254+
255+ if ( node . IsRepository || ! node . IsExpanded )
256+ continue ;
257+
258+ MakeTreeRows ( rows , node . SubNodes , depth + 1 ) ;
259+ }
260+ }
261+
229262 private void OpenAllInNode ( Launcher launcher , RepositoryNode node )
230263 {
231264 foreach ( var subNode in node . SubNodes )
@@ -237,20 +270,6 @@ private void OpenAllInNode(Launcher launcher, RepositoryNode node)
237270 }
238271 }
239272
240- private void CollectVisibleRows ( List < RepositoryNode > visible , AvaloniaList < RepositoryNode > collection )
241- {
242- foreach ( var node in collection )
243- {
244- if ( node . IsVisible )
245- {
246- visible . Add ( node ) ;
247-
248- if ( ! node . IsRepository )
249- CollectVisibleRows ( visible , node . SubNodes ) ;
250- }
251- }
252- }
253-
254273 private static Welcome _instance = new Welcome ( ) ;
255274 private string _searchFilter = string . Empty ;
256275 }
0 commit comments