@@ -19,7 +19,7 @@ public partial class RepoObjectsTree : GitModuleControl
19
19
new TranslationString ( "Filter the revision grid to show this branch only\n To show all branches, right click the revision grid, select 'view' and then the 'show all branches'" ) ;
20
20
21
21
private readonly List < Tree > _rootNodes = new List < Tree > ( ) ;
22
- private SearchControl < string > _txtBranchCriterion ;
22
+ private readonly SearchControl < string > _txtBranchCriterion ;
23
23
private readonly CancellationTokenSequence _reloadCancellation = new CancellationTokenSequence ( ) ;
24
24
private CancellationToken _currentToken ;
25
25
private TreeNode _tagTreeRootNode ;
@@ -34,9 +34,10 @@ public RepoObjectsTree()
34
34
_currentToken = _reloadCancellation . Next ( ) ;
35
35
InitializeComponent ( ) ;
36
36
InitImageList ( ) ;
37
- InitializeSearchBox ( ) ;
38
- treeMain . PreviewKeyDown += OnPreviewKeyDown ;
37
+ _txtBranchCriterion = CreateSearchBox ( ) ;
38
+ branchSearchPanel . Controls . Add ( _txtBranchCriterion , 1 , 0 ) ;
39
39
40
+ treeMain . PreviewKeyDown += OnPreviewKeyDown ;
40
41
btnSearch . PreviewKeyDown += OnPreviewKeyDown ;
41
42
PreviewKeyDown += OnPreviewKeyDown ;
42
43
InitializeComplete ( ) ;
@@ -49,6 +50,97 @@ public RepoObjectsTree()
49
50
treeMain . NodeMouseDoubleClick += OnNodeDoubleClick ;
50
51
mnubtnFilterRemoteBranchInRevisionGrid . ToolTipText = _showBranchOnly . Text ;
51
52
mnubtnFilterLocalBranchInRevisionGrid . ToolTipText = _showBranchOnly . Text ;
53
+
54
+ void InitImageList ( )
55
+ {
56
+ const int rowPadding = 1 ; // added to top and bottom, so doubled -- this value is scaled *after*, so consider 96dpi here
57
+
58
+ treeMain . ImageList = new ImageList
59
+ {
60
+ ImageSize = DpiUtil . Scale ( new Size ( 16 , 16 + rowPadding + rowPadding ) ) , // Scale ImageSize and images scale automatically
61
+ Images =
62
+ {
63
+ { nameof ( Images . BranchDocument ) , Pad ( Images . BranchDocument ) } ,
64
+ { nameof ( Images . Branch ) , Pad ( Images . Branch ) } ,
65
+ { nameof ( Images . Remote ) , Pad ( Images . RemoteRepo ) } ,
66
+ { nameof ( Images . BitBucket ) , Pad ( Images . BitBucket ) } ,
67
+ { nameof ( Images . GitHub ) , Pad ( Images . GitHub ) } ,
68
+ { nameof ( Images . BranchLocalRoot ) , Pad ( Images . BranchLocalRoot ) } ,
69
+ { nameof ( Images . BranchRemoteRoot ) , Pad ( Images . BranchRemoteRoot ) } ,
70
+ { nameof ( Images . BranchRemote ) , Pad ( Images . BranchRemote ) } ,
71
+ { nameof ( Images . BranchFolder ) , Pad ( Images . BranchFolder ) } ,
72
+ { nameof ( Images . TagHorizontal ) , Pad ( Images . TagHorizontal ) } ,
73
+ }
74
+ } ;
75
+ treeMain . SelectedImageKey = treeMain . ImageKey ;
76
+
77
+ Image Pad ( Image image )
78
+ {
79
+ var padded = new Bitmap ( image . Width , image . Height + rowPadding + rowPadding , PixelFormat . Format32bppArgb ) ;
80
+ using ( var g = Graphics . FromImage ( padded ) )
81
+ {
82
+ g . DrawImageUnscaled ( image , 0 , rowPadding ) ;
83
+ return padded ;
84
+ }
85
+ }
86
+ }
87
+
88
+ SearchControl < string > CreateSearchBox ( )
89
+ {
90
+ var search = new SearchControl < string > ( SearchForBranch , i => { } )
91
+ {
92
+ Anchor = AnchorStyles . Left | AnchorStyles . Right ,
93
+ Name = "txtBranchCritierion" ,
94
+ TabIndex = 1
95
+ } ;
96
+ search . OnTextEntered += ( ) =>
97
+ {
98
+ OnBranchCriterionChanged ( null , null ) ;
99
+ OnBtnSearchClicked ( null , null ) ;
100
+ } ;
101
+ search . TextChanged += OnBranchCriterionChanged ;
102
+ search . KeyDown += TxtBranchCriterion_KeyDown ;
103
+ search . PreviewKeyDown += OnPreviewKeyDown ;
104
+ return search ;
105
+
106
+ IEnumerable < string > SearchForBranch ( string arg )
107
+ {
108
+ return CollectFilterCandidates ( )
109
+ . Where ( r => r . IndexOf ( arg , StringComparison . OrdinalIgnoreCase ) != - 1 ) ;
110
+ }
111
+
112
+ IEnumerable < string > CollectFilterCandidates ( )
113
+ {
114
+ var list = new List < string > ( ) ;
115
+
116
+ foreach ( TreeNode rootNode in treeMain . Nodes )
117
+ {
118
+ CollectFromNodes ( rootNode . Nodes ) ;
119
+ }
120
+
121
+ return list ;
122
+
123
+ void CollectFromNodes ( TreeNodeCollection nodes )
124
+ {
125
+ foreach ( TreeNode node in nodes )
126
+ {
127
+ if ( node . Tag is BaseBranchNode branch )
128
+ {
129
+ if ( branch . Nodes . Count == 0 )
130
+ {
131
+ list . Add ( branch . FullPath ) ;
132
+ }
133
+ }
134
+ else
135
+ {
136
+ list . Add ( node . Text ) ;
137
+ }
138
+
139
+ CollectFromNodes ( node . Nodes ) ;
140
+ }
141
+ }
142
+ }
143
+ }
52
144
}
53
145
54
146
public void SetBranchFilterer ( FilterBranchHelper filterBranchHelper )
@@ -149,133 +241,92 @@ private CancellationToken CancelBackgroundTasks()
149
241
return _currentToken ;
150
242
}
151
243
152
- private IEnumerable < string > CollectFilterCandidates ( )
244
+ private void DoSearch ( )
153
245
{
154
- var list = new List < string > ( ) ;
246
+ _txtBranchCriterion . CloseDropdown ( ) ;
155
247
156
- foreach ( TreeNode rootNode in treeMain . Nodes )
248
+ if ( _searchCriteriaChanged && _searchResult != null && _searchResult . Any ( ) )
157
249
{
158
- CollectFromNodes ( rootNode . Nodes ) ;
159
- }
250
+ _searchCriteriaChanged = false ;
251
+ foreach ( var coloredNode in _searchResult )
252
+ {
253
+ coloredNode . BackColor = SystemColors . Window ;
254
+ }
160
255
161
- return list ;
256
+ _searchResult = null ;
257
+ if ( _txtBranchCriterion . Text . IsNullOrWhiteSpace ( ) )
258
+ {
259
+ _txtBranchCriterion . Focus ( ) ;
260
+ return ;
261
+ }
262
+ }
162
263
163
- void CollectFromNodes ( TreeNodeCollection nodes )
264
+ if ( _searchResult == null || ! _searchResult . Any ( ) )
164
265
{
165
- foreach ( TreeNode node in nodes )
266
+ if ( _txtBranchCriterion . Text . IsNotNullOrWhitespace ( ) )
166
267
{
167
- if ( node . Tag is BaseBranchNode branch )
168
- {
169
- if ( branch . Nodes . Count == 0 )
170
- {
171
- list . Add ( branch . FullPath ) ;
172
- }
173
- }
174
- else
175
- {
176
- list . Add ( node . Text ) ;
177
- }
178
-
179
- CollectFromNodes ( node . Nodes ) ;
268
+ _searchResult = SearchTree ( _txtBranchCriterion . Text , treeMain . Nodes . Cast < TreeNode > ( ) ) ;
180
269
}
181
270
}
182
- }
183
271
184
- private TreeNode GetNextSearchResult ( )
185
- {
186
- if ( _searchResult == null || ! _searchResult . Any ( ) )
272
+ var node = GetNextSearchResult ( ) ;
273
+
274
+ if ( node == null )
187
275
{
188
- return null ;
276
+ return ;
189
277
}
190
278
191
- var node = _searchResult . First ( ) ;
192
- _searchResult . RemoveAt ( 0 ) ;
193
- _searchResult . Add ( node ) ;
194
- return node ;
195
- }
279
+ node . EnsureVisible ( ) ;
280
+ treeMain . SelectedNode = node ;
196
281
197
- private void InitImageList ( )
198
- {
199
- const int rowPadding = 1 ; // added to top and bottom, so doubled -- this value is scaled *after*, so consider 96dpi here
282
+ return ;
200
283
201
- treeMain . ImageList = new ImageList
284
+ TreeNode GetNextSearchResult ( )
202
285
{
203
- ImageSize = DpiUtil . Scale ( new Size ( 16 , 16 + rowPadding + rowPadding ) ) , // Scale ImageSize and images scale automatically
204
- Images =
205
- {
206
- { nameof ( Images . BranchDocument ) , Pad ( Images . BranchDocument ) } ,
207
- { nameof ( Images . Branch ) , Pad ( Images . Branch ) } ,
208
- { nameof ( Images . Remote ) , Pad ( Images . RemoteRepo ) } ,
209
- { nameof ( Images . BitBucket ) , Pad ( Images . BitBucket ) } ,
210
- { nameof ( Images . GitHub ) , Pad ( Images . GitHub ) } ,
211
- { nameof ( Images . BranchLocalRoot ) , Pad ( Images . BranchLocalRoot ) } ,
212
- { nameof ( Images . BranchRemoteRoot ) , Pad ( Images . BranchRemoteRoot ) } ,
213
- { nameof ( Images . BranchRemote ) , Pad ( Images . BranchRemote ) } ,
214
- { nameof ( Images . BranchFolder ) , Pad ( Images . BranchFolder ) } ,
215
- { nameof ( Images . TagHorizontal ) , Pad ( Images . TagHorizontal ) } ,
216
- }
217
- } ;
218
- treeMain . SelectedImageKey = treeMain . ImageKey ;
286
+ var first = _searchResult ? . FirstOrDefault ( ) ;
219
287
220
- Image Pad ( Image image )
221
- {
222
- var padded = new Bitmap ( image . Width , image . Height + rowPadding + rowPadding , PixelFormat . Format32bppArgb ) ;
223
- using ( var g = Graphics . FromImage ( padded ) )
288
+ if ( first == null )
224
289
{
225
- g . DrawImageUnscaled ( image , 0 , rowPadding ) ;
226
- return padded ;
290
+ return null ;
227
291
}
292
+
293
+ _searchResult . RemoveAt ( 0 ) ;
294
+ _searchResult . Add ( first ) ;
295
+ return first ;
228
296
}
229
- }
230
297
231
- private void InitializeSearchBox ( )
232
- {
233
- _txtBranchCriterion = new SearchControl < string > ( SearchForBranch , i => { } ) ;
234
- _txtBranchCriterion . OnTextEntered += ( ) =>
298
+ List < TreeNode > SearchTree ( string text , IEnumerable < TreeNode > nodes )
235
299
{
236
- OnBranchCriterionChanged ( null , null ) ;
237
- OnBtnSearchClicked ( null , null ) ;
238
- } ;
239
- _txtBranchCriterion . Anchor = AnchorStyles . Left | AnchorStyles . Right ;
240
- _txtBranchCriterion . Name = "txtBranchCritierion" ;
241
- _txtBranchCriterion . TabIndex = 1 ;
242
- _txtBranchCriterion . TextChanged += OnBranchCriterionChanged ;
243
- _txtBranchCriterion . KeyDown += TxtBranchCriterion_KeyDown ;
244
- branchSearchPanel . Controls . Add ( _txtBranchCriterion , 1 , 0 ) ;
245
-
246
- _txtBranchCriterion . PreviewKeyDown += OnPreviewKeyDown ;
247
- }
300
+ var queue = new Queue < TreeNode > ( nodes ) ;
301
+ var ret = new List < TreeNode > ( ) ;
248
302
249
- private IEnumerable < string > SearchForBranch ( string arg )
250
- {
251
- return CollectFilterCandidates ( )
252
- . Where ( r => r . IndexOf ( arg , StringComparison . OrdinalIgnoreCase ) != - 1 ) ;
253
- }
254
-
255
- private static List < TreeNode > SearchTree ( string text , TreeNodeCollection nodes )
256
- {
257
- var ret = new List < TreeNode > ( ) ;
258
- foreach ( TreeNode node in nodes )
259
- {
260
- if ( node . Tag is BaseBranchNode branch )
303
+ while ( queue . Count != 0 )
261
304
{
262
- if ( branch . FullPath . IndexOf ( text , StringComparison . InvariantCultureIgnoreCase ) != - 1 )
305
+ var n = queue . Dequeue ( ) ;
306
+
307
+ if ( n . Tag is BaseBranchNode branch )
263
308
{
264
- AddTreeNodeToSearchResult ( ret , node ) ;
309
+ if ( branch . FullPath . IndexOf ( text , StringComparison . InvariantCultureIgnoreCase ) != - 1 )
310
+ {
311
+ AddTreeNodeToSearchResult ( ret , n ) ;
312
+ }
265
313
}
266
- }
267
- else
268
- {
269
- if ( node . Text . IndexOf ( text , StringComparison . InvariantCultureIgnoreCase ) != - 1 )
314
+ else
315
+ {
316
+ if ( n . Text . IndexOf ( text , StringComparison . InvariantCultureIgnoreCase ) != - 1 )
317
+ {
318
+ AddTreeNodeToSearchResult ( ret , n ) ;
319
+ }
320
+ }
321
+
322
+ foreach ( TreeNode subNode in n . Nodes )
270
323
{
271
- AddTreeNodeToSearchResult ( ret , node ) ;
324
+ queue . Enqueue ( subNode ) ;
272
325
}
273
326
}
274
327
275
- ret . AddRange ( SearchTree ( text , node . Nodes ) ) ;
328
+ return ret ;
276
329
}
277
-
278
- return ret ;
279
330
}
280
331
281
332
private void OnPreviewKeyDown ( object sender , PreviewKeyDownEventArgs e )
@@ -308,39 +359,7 @@ private void ShowTagsToolStripMenuItem_Click(object sender, EventArgs e)
308
359
309
360
private void OnBtnSearchClicked ( object sender , EventArgs e )
310
361
{
311
- _txtBranchCriterion . CloseDropdown ( ) ;
312
- if ( _searchCriteriaChanged && _searchResult != null && _searchResult . Any ( ) )
313
- {
314
- _searchCriteriaChanged = false ;
315
- foreach ( var coloredNode in _searchResult )
316
- {
317
- coloredNode . BackColor = SystemColors . Window ;
318
- }
319
-
320
- _searchResult = null ;
321
- if ( _txtBranchCriterion . Text . IsNullOrWhiteSpace ( ) )
322
- {
323
- _txtBranchCriterion . Focus ( ) ;
324
- return ;
325
- }
326
- }
327
-
328
- if ( _searchResult == null || ! _searchResult . Any ( ) )
329
- {
330
- if ( _txtBranchCriterion . Text . IsNotNullOrWhitespace ( ) )
331
- {
332
- _searchResult = SearchTree ( _txtBranchCriterion . Text , treeMain . Nodes ) ;
333
- }
334
- }
335
-
336
- var node = GetNextSearchResult ( ) ;
337
- if ( node == null )
338
- {
339
- return ;
340
- }
341
-
342
- node . EnsureVisible ( ) ;
343
- treeMain . SelectedNode = node ;
362
+ DoSearch ( ) ;
344
363
}
345
364
346
365
private void OnBranchCriterionChanged ( object sender , EventArgs e )
0 commit comments