Skip to content

Commit

Permalink
Merge pull request #4738 from comintern/next
Browse files Browse the repository at this point in the history
Track and restore unfiltered expanded state
  • Loading branch information
retailcoder committed Jan 25, 2019
2 parents 3a25a65 + 2131924 commit 3b366dc
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 17 deletions.
Expand Up @@ -61,8 +61,6 @@ public override bool IsErrorState

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

public override bool Filtered => false;

protected override void AddNewChildren(ref List<Declaration> declarations)
{
var children = declarations.Where(declaration => declaration.IsInFolderOrSubFolder(FullPath)).ToList();
Expand Down
Expand Up @@ -21,6 +21,12 @@ protected CodeExplorerItemViewModelBase(ICodeExplorerNode parent, Declaration de
{
Parent = parent;
_declaration = declaration;
UnfilteredIsExpanded = IsExpanded;

if (parent != null)
{
Filter = parent.Filter;
}
}

private Declaration _declaration;
Expand Down Expand Up @@ -92,13 +98,12 @@ public bool IsExpanded
get => _isExpanded;
set
{
_isExpanded = value;

if (!Filtered)
if (_isExpanded == value)
{
UnfilteredIsExpanded = _isExpanded;
return;
}

_isExpanded = value;
OnPropertyChanged();
}
}
Expand Down Expand Up @@ -217,6 +222,11 @@ public string Filter
get => _filter;
set
{
if (string.IsNullOrEmpty(_filter))
{
UnfilteredIsExpanded = _isExpanded;
}

var input = value ?? string.Empty;
if (_filter.Equals(input))
{
Expand All @@ -231,6 +241,7 @@ public string Filter

OnPropertyChanged();
OnPropertyChanged(nameof(Filtered));
IsExpanded = !string.IsNullOrEmpty(_filter) ? Children.Any(child => !child.Filtered) : UnfilteredIsExpanded;
}
}

Expand Down
Expand Up @@ -45,8 +45,6 @@ public override bool IsErrorState

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

public override bool Filtered => false;

public void Synchronize(Declaration project, List<ReferenceModel> updated)
{
Declaration = project;
Expand Down
Expand Up @@ -270,7 +270,7 @@ private void Synchronize(IEnumerable<Declaration> declarations)
foreach (var project in adding)
{
var model = new CodeExplorerProjectViewModel(project, ref updates, _state, _vbe);
var model = new CodeExplorerProjectViewModel(project, ref updates, _state, _vbe) { Filter = Search };
Projects.Add(model);
}
Expand Down
3 changes: 0 additions & 3 deletions Rubberduck.Core/UI/Controls/BindableSelectedItemBehavior.cs
@@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Media;

namespace Rubberduck.UI.Controls
{
Expand Down
Expand Up @@ -170,6 +170,34 @@ public void FilteredIsFalseForSubsetsOfName(string name)
}
}

[Test]
[Category("Code Explorer")]
[TestCase(CodeExplorerTestSetup.TestDocumentName)]
[TestCase(CodeExplorerTestSetup.TestModuleName)]
[TestCase(CodeExplorerTestSetup.TestClassName)]
[TestCase(CodeExplorerTestSetup.TestUserFormName)]
public void FilteredIsFalseIfMemberMatches(string name)
{
var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations.TestComponentDeclarations(name);
var componentDeclaration = declarations
.First(declaration => declaration.DeclarationType.HasFlag(DeclarationType.Module) && declaration.IdentifierName.Equals(name));

var component = new CodeExplorerComponentViewModel(null, componentDeclaration, ref declarations, null);
var childName = component.Children.First().Name;

for (var characters = 1; characters <= childName.Length; characters++)
{
component.Filter = childName.Substring(0, characters);
Assert.IsFalse(component.Filtered);
}

for (var position = childName.Length - 2; position > 0; position--)
{
component.Filter = childName.Substring(position);
Assert.IsFalse(component.Filtered);
}
}

[Test]
[Category("Code Explorer")]
[TestCase(CodeExplorerTestSetup.TestDocumentName)]
Expand All @@ -195,6 +223,29 @@ public void FilteredIsTrueForCharactersNotInName(string name)
}
}

[Test]
[Category("Code Explorer")]
[TestCase(CodeExplorerTestSetup.TestDocumentName)]
[TestCase(CodeExplorerTestSetup.TestModuleName)]
[TestCase(CodeExplorerTestSetup.TestClassName)]
[TestCase(CodeExplorerTestSetup.TestUserFormName)]
public void UnfilteredStateIsRestored(string name)
{
var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations.TestComponentDeclarations(name);
var componentDeclaration = declarations
.First(declaration => declaration.DeclarationType.HasFlag(DeclarationType.Module) && declaration.IdentifierName.Equals(name));

var component = new CodeExplorerComponentViewModel(null, componentDeclaration, ref declarations, null);
var childName = component.Children.First().Name;

component.IsExpanded = false;
component.Filter = childName;
Assert.IsTrue(component.IsExpanded);

component.Filter = string.Empty;
Assert.IsFalse(component.IsExpanded);
}

[Test]
[Category("Code Explorer")]
[TestCase(CodeExplorerTestSetup.TestDocumentName)]
Expand Down
Expand Up @@ -141,23 +141,95 @@ public void Constructor_SetsFolderDepth(object[] parameters)

[Test]
[Category("Code Explorer")]
public void FilteredIsFalseForAnyCharacter()
public void FilteredIsTrueForCharactersNotInName()
{
const string folderName = "Foo";
const string testCharacters = "abcdefghijklmnopqrstuwxyz";
const string folderName = "Asdf";

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

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

foreach (var character in testCharacters.ToCharArray().Select(letter => letter.ToString()))
var nonMatching = testCharacters.ToCharArray().Except(folderName.ToLowerInvariant().ToCharArray().Union(children));

foreach (var character in nonMatching.Select(letter => letter.ToString()))
{
folder.Filter = character;
Assert.IsTrue(folder.Filtered);
}
}

[Test]
[Category("Code Explorer")]
public void FilteredIsFalseForSubsetsOfName()
{
const string folderName = "Foobar";

var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName);
var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _);

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

for (var characters = 1; characters <= folderName.Length; characters++)
{
folder.Filter = folderName.Substring(0, characters);
Assert.IsFalse(folder.Filtered);
}

for (var position = folderName.Length - 2; position > 0; position--)
{
folder.Filter = folderName.Substring(position);
Assert.IsFalse(folder.Filtered);
}
}

[Test]
[Category("Code Explorer")]
public void FilteredIsFalseIfChildMatches()
{
const string folderName = "Foobar";

var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName);
var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _);

var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations);
var childName = folder.Children.First().Name;

for (var characters = 1; characters <= childName.Length; characters++)
{
folder.Filter = childName.Substring(0, characters);
Assert.IsFalse(folder.Filtered);
}

for (var position = childName.Length - 2; position > 0; position--)
{
folder.Filter = childName.Substring(position);
Assert.IsFalse(folder.Filtered);
}
}

[Test]
[Category("Code Explorer")]
public void UnfilteredStateIsRestored()
{
const string folderName = "Foobar";

var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName);
var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _);

var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations);
var childName = folder.Children.First().Name;

folder.IsExpanded = false;
folder.Filter = childName;
Assert.IsTrue(folder.IsExpanded);

folder.Filter = string.Empty;
Assert.IsFalse(folder.IsExpanded);
}

[Test]
[Category("Code Explorer")]
[TestCase(CodeExplorerSortOrder.Undefined)]
Expand Down
43 changes: 43 additions & 0 deletions RubberduckTests/CodeExplorer/CodeExplorerMemberViewModelTests.cs
Expand Up @@ -223,6 +223,49 @@ public void FilteredIsTrueForCharactersNotInName(string name)
}
}

[Test]
[Category("Code Explorer")]
[TestCase(CodeExplorerTestCode.TestTypeName)]
[TestCase(CodeExplorerTestCode.TestEnumName)]
public void FilteredIsFalseIfChildMatches(string name)
{
var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations.TestMemberDeclarations(name, out var memberDeclaration);

var member = new CodeExplorerMemberViewModel(null, memberDeclaration, ref declarations);
var childName = member.Children.First().Name;

for (var characters = 1; characters <= childName.Length; characters++)
{
member.Filter = childName.Substring(0, characters);
Assert.IsFalse(member.Filtered);
}

for (var position = childName.Length - 2; position > 0; position--)
{
member.Filter = childName.Substring(position);
Assert.IsFalse(member.Filtered);
}
}

[Test]
[Category("Code Explorer")]
[TestCase(CodeExplorerTestCode.TestTypeName)]
[TestCase(CodeExplorerTestCode.TestEnumName)]
public void UnfilteredStateIsRestored(string name)
{
var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations.TestMemberDeclarations(name, out var memberDeclaration);

var member = new CodeExplorerMemberViewModel(null, memberDeclaration, ref declarations);
var childName = member.Children.First().Name;

member.IsExpanded = false;
member.Filter = childName;
Assert.IsTrue(member.IsExpanded);

member.Filter = string.Empty;
Assert.IsFalse(member.IsExpanded);
}

[Test]
[Category("Code Explorer")]
[TestCase(CodeExplorerTestCode.TestSubName)]
Expand Down
Expand Up @@ -176,6 +176,38 @@ public void FilteredIsFalseForAnyCharacter(ReferenceKind type)
}
}

[Test]
[Category("Code Explorer")]
public void UnfilteredStateIsRestored_TypeLibraries()
{
var references = AddRemoveReferencesSetup.DummyReferencesList;
var folder = new CodeExplorerReferenceFolderViewModel(null, null, references, ReferenceKind.TypeLibrary);
var childName = folder.Children.First().Name;

folder.IsExpanded = false;
folder.Filter = childName;
Assert.IsTrue(folder.IsExpanded);

folder.Filter = string.Empty;
Assert.IsFalse(folder.IsExpanded);
}

[Test]
[Category("Code Explorer")]
public void UnfilteredStateIsRestored_Projects()
{
var references = AddRemoveReferencesSetup.DummyProjectsList;
var folder = new CodeExplorerReferenceFolderViewModel(null, null, references, ReferenceKind.Project);
var childName = folder.Children.First().Name;

folder.IsExpanded = false;
folder.Filter = childName;
Assert.IsTrue(folder.IsExpanded);

folder.Filter = string.Empty;
Assert.IsFalse(folder.IsExpanded);
}

[Test]
[Category("Code Explorer")]
[TestCase(ReferenceKind.TypeLibrary)]
Expand Down
Expand Up @@ -148,20 +148,47 @@ public void ReferenceLockedStateMatchesIsBuiltIn(ReferenceKind type, bool builtI
[Category("Code Explorer")]
[TestCase(ReferenceKind.TypeLibrary)]
[TestCase(ReferenceKind.Project)]
public void FilteredIsFalseForAnyCharacter(ReferenceKind type)
public void FilteredIsTrueForCharactersNotInName(ReferenceKind type)
{
const string testCharacters = "abcdefghijklmnopqrstuwxyz";

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

foreach (var character in testCharacters.ToCharArray().Select(letter => letter.ToString()))
var nonMatching = testCharacters.ToCharArray().Except(name.ToLowerInvariant().ToCharArray());

foreach (var character in nonMatching.Select(letter => letter.ToString()))
{
viewModel.Filter = character;
Assert.IsTrue(viewModel.Filtered);
}
}

[Test]
[Category("Code Explorer")]
[TestCase(ReferenceKind.TypeLibrary)]
[TestCase(ReferenceKind.Project)]
public void FilteredIsFalseForSubsetsOfName(ReferenceKind type)
{
var reference = type == ReferenceKind.TypeLibrary ? LibraryReference : ProjectReference;
var viewModel = new CodeExplorerReferenceViewModel(null, reference);
var name = viewModel.Name;

for (var characters = 1; characters <= name.Length; characters++)
{
viewModel.Filter = name.Substring(0, characters);
Assert.IsFalse(viewModel.Filtered);
}

for (var position = name.Length - 2; position > 0; position--)
{
viewModel.Filter = name.Substring(position);
Assert.IsFalse(viewModel.Filtered);
}
}


[Test]
[Category("Code Explorer")]
[TestCase(CodeExplorerSortOrder.Undefined)]
Expand Down

0 comments on commit 3b366dc

Please sign in to comment.