Skip to content

Commit 8252f74

Browse files
committed
Make the MoveToFolder dialog use the TextBoxErrorStyle
This allows error tooltips.
1 parent 91cc2c5 commit 8252f74

File tree

4 files changed

+170
-19
lines changed

4 files changed

+170
-19
lines changed

Rubberduck.Core/UI/Refactorings/MoveToFolder/MoveMultipleToFolderView.xaml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,12 @@
3333
Margin="0,0,5,0" />
3434
<TextBox Name="MoveToFolderTextBox"
3535
Grid.Column="1"
36+
Style="{StaticResource TextBoxErrorStyle}"
3637
Text="{Binding NewFolder, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
3738
Height="22"
3839
VerticalAlignment="Top"
3940
VerticalContentAlignment="Center"
4041
HorizontalAlignment="Stretch" />
41-
<Image Grid.Column="1"
42-
Source="{StaticResource InvalidTextImage}"
43-
Height="16"
44-
Margin="0,-8,-8,0"
45-
HorizontalAlignment="Right"
46-
VerticalAlignment="Top"
47-
Visibility="{Binding IsValidFolder, Converter={StaticResource BoolToHiddenVisibility}}"/>
4842
</Grid>
4943
<Grid Grid.Row="2" Background="{x:Static SystemColors.ControlDarkBrush}" Grid.IsSharedSizeScope="True">
5044
<Grid HorizontalAlignment="Right"

Rubberduck.Core/UI/Refactorings/MoveToFolder/MoveMultipleToFolderViewModel.cs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,39 @@ public string NewFolder
4343
set
4444
{
4545
Model.TargetFolder = value;
46+
ValidateFolder();
4647
OnPropertyChanged();
4748
OnPropertyChanged(nameof(IsValidFolder));
4849
}
4950
}
50-
51+
52+
private void ValidateFolder()
53+
{
54+
var errors = new List<string>();
55+
56+
if (string.IsNullOrEmpty(NewFolder))
57+
{
58+
errors.Add(RubberduckUI.MoveFolders_EmptyName);
59+
}
60+
else if (NewFolder.Any(char.IsControl))
61+
{
62+
errors.Add(RubberduckUI.MoveFolders_ControlCharacter);
63+
}
64+
65+
if (errors.Any())
66+
{
67+
SetErrors(nameof(NewFolder), errors);
68+
}
69+
else
70+
{
71+
ClearErrors();
72+
}
73+
}
74+
5175
public bool IsValidFolder => Targets != null
5276
&& Targets.Any()
53-
&& NewFolder != null
54-
&& !NewFolder.Any(char.IsControl);
55-
77+
&& !HasErrors;
78+
5679
protected override void DialogOk()
5780
{
5881
if (Targets == null || !Targets.Any())

RubberduckTests/Refactoring/MoveFolders/MoveMultipleToFolderViewModelTests.cs renamed to RubberduckTests/Refactoring/MoveFolders/MoveMultipleFoldersViewModelTests.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
namespace RubberduckTests.Refactoring.MoveFolders
2020
{
2121
[TestFixture]
22-
public class MoveMultipleToFolderViewModelTests
22+
public class MoveMultipleFoldersViewModelTests
2323
{
2424
[Test]
2525
[Category("Refactorings")]
@@ -259,13 +259,6 @@ private Mock<IMessageBox> MessageBoxMock(IList<bool> confirmsRequest)
259259
return messageBox;
260260
}
261261

262-
private MoveMultipleFoldersViewModel TestViewModel(ICollection<string> sourceFolders, IDeclarationFinderProvider declarationFinderProvider, IMessageBox messageBox)
263-
{
264-
var finder = declarationFinderProvider.DeclarationFinder;
265-
var model = TestModel(sourceFolders, finder);
266-
return TestViewModel(model, declarationFinderProvider, messageBox);
267-
}
268-
269262
private MoveMultipleFoldersViewModel TestViewModel(MoveMultipleFoldersModel model, IDeclarationFinderProvider declarationFinderProvider, IMessageBox messageBox)
270263
{
271264
return new MoveMultipleFoldersViewModel(model, messageBox, declarationFinderProvider);
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
using System.Linq;
2+
using NUnit.Framework;
3+
using Rubberduck.JunkDrawer.Extensions;
4+
using Rubberduck.Parsing.Symbols;
5+
using Rubberduck.Parsing.VBA.DeclarationCaching;
6+
using Rubberduck.Refactorings.MoveToFolder;
7+
using Rubberduck.UI.Refactorings.MoveToFolder;
8+
using Rubberduck.VBEditor.SafeComWrappers;
9+
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
10+
using RubberduckTests.Mocks;
11+
12+
namespace RubberduckTests.Refactoring.MoveToFolder
13+
{
14+
[TestFixture]
15+
public class MoveMultipleToFolderViewModelTests
16+
{
17+
[Test]
18+
[Category("Refactorings")]
19+
public void InitialFolderIsInitialTargetFromModel()
20+
{
21+
using (var state = MockParser.CreateAndParse(TestVbe()))
22+
{
23+
var model = TestModel("FooBar.Foo", state.DeclarationFinder);
24+
25+
var initialTargetFolder = model.TargetFolder;
26+
var viewModel = TestViewModel(model);
27+
28+
Assert.AreEqual(initialTargetFolder, viewModel.NewFolder);
29+
}
30+
}
31+
32+
[Test]
33+
[Category("Refactorings")]
34+
public void UpdatingTargetFolderUpdatesModel()
35+
{
36+
using (var state = MockParser.CreateAndParse(TestVbe()))
37+
{
38+
var model = TestModel("FooBar.Foo", state.DeclarationFinder);
39+
var viewModel = TestViewModel(model);
40+
41+
const string newTarget = "Test.Test.Test";
42+
viewModel.NewFolder = newTarget;
43+
44+
Assert.AreEqual(newTarget, model.TargetFolder);
45+
}
46+
}
47+
48+
[Test]
49+
[Category("Refactorings")]
50+
[TestCase(null)]
51+
[TestCase("")]
52+
public void EmptyTargetFolder_Error(string emptyFolderName)
53+
{
54+
using (var state = MockParser.CreateAndParse(TestVbe()))
55+
{
56+
var model = TestModel("FooBar.Foo", state.DeclarationFinder);
57+
var viewModel = TestViewModel(model);
58+
59+
viewModel.NewFolder = emptyFolderName;
60+
61+
Assert.IsTrue(viewModel.HasErrors);
62+
Assert.IsFalse(viewModel.IsValidFolder);
63+
}
64+
}
65+
66+
[Test]
67+
[Category("Refactorings")]
68+
[TestCase("raeraf afrwefe \n fefaef")]
69+
[TestCase("raeraf afrwefe \r fefaef")]
70+
[TestCase("raeraf afrwefe \u0000 fefaef")]
71+
public void TargetFolderWithControlCharacter_Error(string folderName)
72+
{
73+
using (var state = MockParser.CreateAndParse(TestVbe()))
74+
{
75+
var model = TestModel("FooBar.Foo", state.DeclarationFinder);
76+
var viewModel = TestViewModel(model);
77+
78+
viewModel.NewFolder = folderName;
79+
80+
Assert.IsTrue(viewModel.HasErrors);
81+
Assert.IsFalse(viewModel.IsValidFolder);
82+
}
83+
}
84+
85+
[Test]
86+
[Category("Refactorings")]
87+
public void NonEmptyTargetFolderWithoutControlCharacter_NoError()
88+
{
89+
using (var state = MockParser.CreateAndParse(TestVbe()))
90+
{
91+
var model = TestModel("FooBar.Foo" , state.DeclarationFinder);
92+
var viewModel = TestViewModel(model);
93+
94+
viewModel.NewFolder = ";oehaha .adaiafa.a@#$^%&#@$&%%$%^$.ad3.1010101. . . . rqrq";
95+
96+
Assert.IsFalse(viewModel.HasErrors);
97+
Assert.IsTrue(viewModel.IsValidFolder);
98+
}
99+
}
100+
101+
private MoveMultipleToFolderViewModel TestViewModel(MoveMultipleToFolderModel model)
102+
{
103+
return new MoveMultipleToFolderViewModel(model);
104+
}
105+
106+
private MoveMultipleToFolderModel TestModel(string sourceFolder, DeclarationFinder finder)
107+
{
108+
var modulesToMove = finder.UserDeclarations(DeclarationType.Module)
109+
.OfType<ModuleDeclaration>()
110+
.Where(module => module.CustomFolder.Equals(sourceFolder)
111+
|| module.CustomFolder.IsSubFolderOf(sourceFolder))
112+
.ToList();
113+
114+
var initialTarget = sourceFolder;
115+
116+
return new MoveMultipleToFolderModel(modulesToMove, initialTarget);
117+
}
118+
119+
private IVBE TestVbe()
120+
{
121+
const string targetFolderComponentCode = @"
122+
'@Folder ""Test.Foo.Bar.Test.Baz""";
123+
124+
const string component1Code = @"
125+
'@Folder ""FooBar.Foo.Barr.Foo.Test""";
126+
127+
const string component2Code = @"
128+
'@Folder ""FooBar.Foo.Barz.Test.Foo""";
129+
130+
return new MockVbeBuilder()
131+
.ProjectBuilder("TestProject", ProjectProtection.Unprotected)
132+
.AddComponent("TargetFolderComponent", ComponentType.ClassModule, targetFolderComponentCode)
133+
.AddComponent("Component1", ComponentType.ClassModule, component1Code)
134+
.AddComponent("Component2", ComponentType.ClassModule, component2Code)
135+
.AddProjectToVbeBuilder()
136+
.Build()
137+
.Object;
138+
}
139+
140+
}
141+
}

0 commit comments

Comments
 (0)