Skip to content

Commit 3b366dc

Browse files
authored
Merge pull request #4738 from comintern/next
Track and restore unfiltered expanded state
2 parents 3a25a65 + 2131924 commit 3b366dc

10 files changed

+246
-17
lines changed

Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerCustomFolderViewModel.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ public override bool IsErrorState
6161

6262
public override Comparer<ICodeExplorerNode> SortComparer => CodeExplorerItemComparer.Name;
6363

64-
public override bool Filtered => false;
65-
6664
protected override void AddNewChildren(ref List<Declaration> declarations)
6765
{
6866
var children = declarations.Where(declaration => declaration.IsInFolderOrSubFolder(FullPath)).ToList();

Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerItemViewModelBase.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ protected CodeExplorerItemViewModelBase(ICodeExplorerNode parent, Declaration de
2121
{
2222
Parent = parent;
2323
_declaration = declaration;
24+
UnfilteredIsExpanded = IsExpanded;
25+
26+
if (parent != null)
27+
{
28+
Filter = parent.Filter;
29+
}
2430
}
2531

2632
private Declaration _declaration;
@@ -92,13 +98,12 @@ public bool IsExpanded
9298
get => _isExpanded;
9399
set
94100
{
95-
_isExpanded = value;
96-
97-
if (!Filtered)
101+
if (_isExpanded == value)
98102
{
99-
UnfilteredIsExpanded = _isExpanded;
103+
return;
100104
}
101105

106+
_isExpanded = value;
102107
OnPropertyChanged();
103108
}
104109
}
@@ -217,6 +222,11 @@ public string Filter
217222
get => _filter;
218223
set
219224
{
225+
if (string.IsNullOrEmpty(_filter))
226+
{
227+
UnfilteredIsExpanded = _isExpanded;
228+
}
229+
220230
var input = value ?? string.Empty;
221231
if (_filter.Equals(input))
222232
{
@@ -231,6 +241,7 @@ public string Filter
231241

232242
OnPropertyChanged();
233243
OnPropertyChanged(nameof(Filtered));
244+
IsExpanded = !string.IsNullOrEmpty(_filter) ? Children.Any(child => !child.Filtered) : UnfilteredIsExpanded;
234245
}
235246
}
236247

Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerReferenceViewModel.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ public override bool IsErrorState
4545

4646
public override Comparer<ICodeExplorerNode> SortComparer => CodeExplorerItemComparer.ReferencePriority;
4747

48-
public override bool Filtered => false;
49-
5048
public void Synchronize(Declaration project, List<ReferenceModel> updated)
5149
{
5250
Declaration = project;

Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ private void Synchronize(IEnumerable<Declaration> declarations)
270270

271271
foreach (var project in adding)
272272
{
273-
var model = new CodeExplorerProjectViewModel(project, ref updates, _state, _vbe);
273+
var model = new CodeExplorerProjectViewModel(project, ref updates, _state, _vbe) { Filter = Search };
274274
Projects.Add(model);
275275
}
276276

Rubberduck.Core/UI/Controls/BindableSelectedItemBehavior.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
using System;
2-
using System.Collections.Generic;
31
using System.Linq;
42
using System.Reflection;
53
using System.Windows;
64
using System.Windows.Controls;
75
using System.Windows.Interactivity;
8-
using System.Windows.Media;
96

107
namespace Rubberduck.UI.Controls
118
{

RubberduckTests/CodeExplorer/CodeExplorerComponentViewModelTests.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,34 @@ public void FilteredIsFalseForSubsetsOfName(string name)
170170
}
171171
}
172172

173+
[Test]
174+
[Category("Code Explorer")]
175+
[TestCase(CodeExplorerTestSetup.TestDocumentName)]
176+
[TestCase(CodeExplorerTestSetup.TestModuleName)]
177+
[TestCase(CodeExplorerTestSetup.TestClassName)]
178+
[TestCase(CodeExplorerTestSetup.TestUserFormName)]
179+
public void FilteredIsFalseIfMemberMatches(string name)
180+
{
181+
var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations.TestComponentDeclarations(name);
182+
var componentDeclaration = declarations
183+
.First(declaration => declaration.DeclarationType.HasFlag(DeclarationType.Module) && declaration.IdentifierName.Equals(name));
184+
185+
var component = new CodeExplorerComponentViewModel(null, componentDeclaration, ref declarations, null);
186+
var childName = component.Children.First().Name;
187+
188+
for (var characters = 1; characters <= childName.Length; characters++)
189+
{
190+
component.Filter = childName.Substring(0, characters);
191+
Assert.IsFalse(component.Filtered);
192+
}
193+
194+
for (var position = childName.Length - 2; position > 0; position--)
195+
{
196+
component.Filter = childName.Substring(position);
197+
Assert.IsFalse(component.Filtered);
198+
}
199+
}
200+
173201
[Test]
174202
[Category("Code Explorer")]
175203
[TestCase(CodeExplorerTestSetup.TestDocumentName)]
@@ -195,6 +223,29 @@ public void FilteredIsTrueForCharactersNotInName(string name)
195223
}
196224
}
197225

226+
[Test]
227+
[Category("Code Explorer")]
228+
[TestCase(CodeExplorerTestSetup.TestDocumentName)]
229+
[TestCase(CodeExplorerTestSetup.TestModuleName)]
230+
[TestCase(CodeExplorerTestSetup.TestClassName)]
231+
[TestCase(CodeExplorerTestSetup.TestUserFormName)]
232+
public void UnfilteredStateIsRestored(string name)
233+
{
234+
var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations.TestComponentDeclarations(name);
235+
var componentDeclaration = declarations
236+
.First(declaration => declaration.DeclarationType.HasFlag(DeclarationType.Module) && declaration.IdentifierName.Equals(name));
237+
238+
var component = new CodeExplorerComponentViewModel(null, componentDeclaration, ref declarations, null);
239+
var childName = component.Children.First().Name;
240+
241+
component.IsExpanded = false;
242+
component.Filter = childName;
243+
Assert.IsTrue(component.IsExpanded);
244+
245+
component.Filter = string.Empty;
246+
Assert.IsFalse(component.IsExpanded);
247+
}
248+
198249
[Test]
199250
[Category("Code Explorer")]
200251
[TestCase(CodeExplorerTestSetup.TestDocumentName)]

RubberduckTests/CodeExplorer/CodeExplorerCustomFolderViewModelTests.cs

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,23 +141,95 @@ public void Constructor_SetsFolderDepth(object[] parameters)
141141

142142
[Test]
143143
[Category("Code Explorer")]
144-
public void FilteredIsFalseForAnyCharacter()
144+
public void FilteredIsTrueForCharactersNotInName()
145145
{
146-
const string folderName = "Foo";
147146
const string testCharacters = "abcdefghijklmnopqrstuwxyz";
147+
const string folderName = "Asdf";
148148

149149
var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName);
150150
var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _);
151+
var children = declarations.SelectMany(declaration => declaration.IdentifierName.ToCharArray()).Distinct().ToList();
151152

152153
var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations);
153154

154-
foreach (var character in testCharacters.ToCharArray().Select(letter => letter.ToString()))
155+
var nonMatching = testCharacters.ToCharArray().Except(folderName.ToLowerInvariant().ToCharArray().Union(children));
156+
157+
foreach (var character in nonMatching.Select(letter => letter.ToString()))
155158
{
156159
folder.Filter = character;
160+
Assert.IsTrue(folder.Filtered);
161+
}
162+
}
163+
164+
[Test]
165+
[Category("Code Explorer")]
166+
public void FilteredIsFalseForSubsetsOfName()
167+
{
168+
const string folderName = "Foobar";
169+
170+
var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName);
171+
var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _);
172+
173+
var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations);
174+
175+
for (var characters = 1; characters <= folderName.Length; characters++)
176+
{
177+
folder.Filter = folderName.Substring(0, characters);
178+
Assert.IsFalse(folder.Filtered);
179+
}
180+
181+
for (var position = folderName.Length - 2; position > 0; position--)
182+
{
183+
folder.Filter = folderName.Substring(position);
157184
Assert.IsFalse(folder.Filtered);
158185
}
159186
}
160187

188+
[Test]
189+
[Category("Code Explorer")]
190+
public void FilteredIsFalseIfChildMatches()
191+
{
192+
const string folderName = "Foobar";
193+
194+
var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName);
195+
var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _);
196+
197+
var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations);
198+
var childName = folder.Children.First().Name;
199+
200+
for (var characters = 1; characters <= childName.Length; characters++)
201+
{
202+
folder.Filter = childName.Substring(0, characters);
203+
Assert.IsFalse(folder.Filtered);
204+
}
205+
206+
for (var position = childName.Length - 2; position > 0; position--)
207+
{
208+
folder.Filter = childName.Substring(position);
209+
Assert.IsFalse(folder.Filtered);
210+
}
211+
}
212+
213+
[Test]
214+
[Category("Code Explorer")]
215+
public void UnfilteredStateIsRestored()
216+
{
217+
const string folderName = "Foobar";
218+
219+
var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName);
220+
var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _);
221+
222+
var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations);
223+
var childName = folder.Children.First().Name;
224+
225+
folder.IsExpanded = false;
226+
folder.Filter = childName;
227+
Assert.IsTrue(folder.IsExpanded);
228+
229+
folder.Filter = string.Empty;
230+
Assert.IsFalse(folder.IsExpanded);
231+
}
232+
161233
[Test]
162234
[Category("Code Explorer")]
163235
[TestCase(CodeExplorerSortOrder.Undefined)]

RubberduckTests/CodeExplorer/CodeExplorerMemberViewModelTests.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,49 @@ public void FilteredIsTrueForCharactersNotInName(string name)
223223
}
224224
}
225225

226+
[Test]
227+
[Category("Code Explorer")]
228+
[TestCase(CodeExplorerTestCode.TestTypeName)]
229+
[TestCase(CodeExplorerTestCode.TestEnumName)]
230+
public void FilteredIsFalseIfChildMatches(string name)
231+
{
232+
var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations.TestMemberDeclarations(name, out var memberDeclaration);
233+
234+
var member = new CodeExplorerMemberViewModel(null, memberDeclaration, ref declarations);
235+
var childName = member.Children.First().Name;
236+
237+
for (var characters = 1; characters <= childName.Length; characters++)
238+
{
239+
member.Filter = childName.Substring(0, characters);
240+
Assert.IsFalse(member.Filtered);
241+
}
242+
243+
for (var position = childName.Length - 2; position > 0; position--)
244+
{
245+
member.Filter = childName.Substring(position);
246+
Assert.IsFalse(member.Filtered);
247+
}
248+
}
249+
250+
[Test]
251+
[Category("Code Explorer")]
252+
[TestCase(CodeExplorerTestCode.TestTypeName)]
253+
[TestCase(CodeExplorerTestCode.TestEnumName)]
254+
public void UnfilteredStateIsRestored(string name)
255+
{
256+
var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations.TestMemberDeclarations(name, out var memberDeclaration);
257+
258+
var member = new CodeExplorerMemberViewModel(null, memberDeclaration, ref declarations);
259+
var childName = member.Children.First().Name;
260+
261+
member.IsExpanded = false;
262+
member.Filter = childName;
263+
Assert.IsTrue(member.IsExpanded);
264+
265+
member.Filter = string.Empty;
266+
Assert.IsFalse(member.IsExpanded);
267+
}
268+
226269
[Test]
227270
[Category("Code Explorer")]
228271
[TestCase(CodeExplorerTestCode.TestSubName)]

RubberduckTests/CodeExplorer/CodeExplorerReferenceFolderViewModelTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,38 @@ public void FilteredIsFalseForAnyCharacter(ReferenceKind type)
176176
}
177177
}
178178

179+
[Test]
180+
[Category("Code Explorer")]
181+
public void UnfilteredStateIsRestored_TypeLibraries()
182+
{
183+
var references = AddRemoveReferencesSetup.DummyReferencesList;
184+
var folder = new CodeExplorerReferenceFolderViewModel(null, null, references, ReferenceKind.TypeLibrary);
185+
var childName = folder.Children.First().Name;
186+
187+
folder.IsExpanded = false;
188+
folder.Filter = childName;
189+
Assert.IsTrue(folder.IsExpanded);
190+
191+
folder.Filter = string.Empty;
192+
Assert.IsFalse(folder.IsExpanded);
193+
}
194+
195+
[Test]
196+
[Category("Code Explorer")]
197+
public void UnfilteredStateIsRestored_Projects()
198+
{
199+
var references = AddRemoveReferencesSetup.DummyProjectsList;
200+
var folder = new CodeExplorerReferenceFolderViewModel(null, null, references, ReferenceKind.Project);
201+
var childName = folder.Children.First().Name;
202+
203+
folder.IsExpanded = false;
204+
folder.Filter = childName;
205+
Assert.IsTrue(folder.IsExpanded);
206+
207+
folder.Filter = string.Empty;
208+
Assert.IsFalse(folder.IsExpanded);
209+
}
210+
179211
[Test]
180212
[Category("Code Explorer")]
181213
[TestCase(ReferenceKind.TypeLibrary)]

RubberduckTests/CodeExplorer/CodeExplorerReferenceViewModelTests.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,20 +148,47 @@ public void ReferenceLockedStateMatchesIsBuiltIn(ReferenceKind type, bool builtI
148148
[Category("Code Explorer")]
149149
[TestCase(ReferenceKind.TypeLibrary)]
150150
[TestCase(ReferenceKind.Project)]
151-
public void FilteredIsFalseForAnyCharacter(ReferenceKind type)
151+
public void FilteredIsTrueForCharactersNotInName(ReferenceKind type)
152152
{
153153
const string testCharacters = "abcdefghijklmnopqrstuwxyz";
154154

155155
var reference = type == ReferenceKind.TypeLibrary ? LibraryReference : ProjectReference;
156156
var viewModel = new CodeExplorerReferenceViewModel(null, reference);
157+
var name = viewModel.Name;
157158

158-
foreach (var character in testCharacters.ToCharArray().Select(letter => letter.ToString()))
159+
var nonMatching = testCharacters.ToCharArray().Except(name.ToLowerInvariant().ToCharArray());
160+
161+
foreach (var character in nonMatching.Select(letter => letter.ToString()))
159162
{
160163
viewModel.Filter = character;
164+
Assert.IsTrue(viewModel.Filtered);
165+
}
166+
}
167+
168+
[Test]
169+
[Category("Code Explorer")]
170+
[TestCase(ReferenceKind.TypeLibrary)]
171+
[TestCase(ReferenceKind.Project)]
172+
public void FilteredIsFalseForSubsetsOfName(ReferenceKind type)
173+
{
174+
var reference = type == ReferenceKind.TypeLibrary ? LibraryReference : ProjectReference;
175+
var viewModel = new CodeExplorerReferenceViewModel(null, reference);
176+
var name = viewModel.Name;
177+
178+
for (var characters = 1; characters <= name.Length; characters++)
179+
{
180+
viewModel.Filter = name.Substring(0, characters);
181+
Assert.IsFalse(viewModel.Filtered);
182+
}
183+
184+
for (var position = name.Length - 2; position > 0; position--)
185+
{
186+
viewModel.Filter = name.Substring(position);
161187
Assert.IsFalse(viewModel.Filtered);
162188
}
163189
}
164190

191+
165192
[Test]
166193
[Category("Code Explorer")]
167194
[TestCase(CodeExplorerSortOrder.Undefined)]

0 commit comments

Comments
 (0)