Skip to content

Commit 8a992ee

Browse files
committed
Add MoveToFolderRefactoring
Also correctly converts folder annotation arguments to the string content and back. This also removes the parentheses around folders.
1 parent a425932 commit 8a992ee

28 files changed

+574
-33
lines changed

Rubberduck.Core/Navigation/Folders/FolderExtensions.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ public static class FolderExtensions
1010

1111
public static string RootFolder(this Declaration declaration)
1212
{
13-
return (declaration?.CustomFolder?.Trim('"') ?? string.Empty).Split(FolderDelimiter).FirstOrDefault()
13+
return (declaration?.CustomFolder ?? string.Empty).Split(FolderDelimiter).FirstOrDefault()
1414
?? declaration?.ProjectName
1515
?? string.Empty;
1616
}
1717

1818
public static string SubFolderRoot(this string folder, string subfolder)
1919
{
20-
if (folder is null || subfolder is null || !folder.Trim('"').StartsWith(subfolder.Trim('"')))
20+
if (folder is null || subfolder is null || !folder.StartsWith(subfolder))
2121
{
2222
return string.Empty;
2323
}
2424

25-
var subPath = folder.Trim('"').Substring(subfolder.Length + 1);
25+
var subPath = folder.Substring(subfolder.Length + 1);
2626
return subPath.Split(FolderDelimiter).FirstOrDefault() ?? string.Empty;
2727
}
2828

@@ -33,7 +33,7 @@ public static bool IsInFolder(this Declaration declaration, string folder)
3333
return false;
3434
}
3535

36-
return declaration.CustomFolder.Trim('"').Equals(folder.Trim('"'), StringComparison.Ordinal);
36+
return declaration.CustomFolder.Equals(folder, StringComparison.Ordinal);
3737
}
3838

3939
public static bool IsInSubFolder(this Declaration declaration, string folder)
@@ -43,8 +43,8 @@ public static bool IsInSubFolder(this Declaration declaration, string folder)
4343
return false;
4444
}
4545

46-
var folderPath = folder.Trim('"').Split(FolderDelimiter);
47-
var declarationPath = declaration.CustomFolder.Trim('"').Split(FolderDelimiter);
46+
var folderPath = folder.Split(FolderDelimiter);
47+
var declarationPath = declaration.CustomFolder.Split(FolderDelimiter);
4848

4949
if (folderPath.Length >= declarationPath.Length)
5050
{
@@ -61,8 +61,8 @@ public static bool IsInFolderOrSubFolder(this Declaration declaration, string fo
6161
return false;
6262
}
6363

64-
var folderPath = folder.Trim('"').Split(FolderDelimiter);
65-
var declarationPath = declaration.CustomFolder.Trim('"').Split(FolderDelimiter);
64+
var folderPath = folder.Split(FolderDelimiter);
65+
var declarationPath = declaration.CustomFolder.Split(FolderDelimiter);
6666

6767
for (var depth = 0; depth < folderPath.Length && depth < declarationPath.Length; depth++)
6868
{

Rubberduck.Core/Rubberduck.Core.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@
117117
<DesignTime>True</DesignTime>
118118
<AutoGen>True</AutoGen>
119119
</Compile>
120+
<Compile Update="UI\Refactorings\MoveToFolder\MoveMultipleToFolderView.xaml.cs">
121+
<DependentUpon>MoveMultipleToFolderView.xaml</DependentUpon>
122+
</Compile>
120123
</ItemGroup>
121124
<ItemGroup>
122125
<EmbeddedResource Update="Properties\Resources.resx">

Rubberduck.Core/UI/CodeExplorer/CodeExplorerAddComponentService.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,7 @@ private string Folder(CodeExplorerItemViewModel node)
101101
return ActiveProjectFolder();
102102
}
103103

104-
var customFolder = declaration.CustomFolder;
105-
if (customFolder != null)
106-
{
107-
return customFolder.Replace("\"", string.Empty);
108-
}
109-
110-
return ProjectFolder(declaration.ProjectName);
104+
return declaration.CustomFolder ?? ProjectFolder(declaration.ProjectName);
111105
}
112106

113107
private string ActiveProjectFolder()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Rubberduck.Parsing.VBA;
2+
using Rubberduck.UI.Command.MenuItems.ParentMenus;
3+
using Rubberduck.UI.Command.Refactorings;
4+
5+
namespace Rubberduck.UI.Command.MenuItems
6+
{
7+
public class CodePaneRefactorMoveToFolderCommandMenuItem : CommandMenuItemBase
8+
{
9+
public CodePaneRefactorMoveToFolderCommandMenuItem(CodePaneRefactorMoveToFolderCommand command)
10+
: base(command)
11+
{}
12+
13+
public override string Key => "RefactorMenu_MoveToFolder";
14+
public override int DisplayOrder => (int)RefactoringsMenuItemDisplayOrder.MoveToFolder;
15+
public override bool BeginGroup => true;
16+
17+
public override bool EvaluateCanExecute(RubberduckParserState state)
18+
{
19+
return state != null && Command.CanExecute(null);
20+
}
21+
}
22+
}

Rubberduck.Core/UI/Command/MenuItems/ParentMenus/RefactoringsParentMenu.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public enum RefactoringsMenuItemDisplayOrder
2424
EncapsulateField,
2525
IntroduceParameter,
2626
IntroduceField,
27+
MoveToFolder,
2728
AddRemoveReferences
2829
}
2930
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using Rubberduck.Parsing.Symbols;
2+
using Rubberduck.Parsing.VBA;
3+
using Rubberduck.Refactorings.MoveToFolder;
4+
using Rubberduck.UI.Command.Refactorings.Notifiers;
5+
using Rubberduck.VBEditor.Utility;
6+
7+
namespace Rubberduck.UI.Command.Refactorings
8+
{
9+
public class CodePaneRefactorMoveToFolderCommand : RefactorCodePaneCommandBase
10+
{
11+
private readonly RubberduckParserState _state;
12+
private readonly ISelectedDeclarationProvider _selectedDeclarationProvider;
13+
14+
public CodePaneRefactorMoveToFolderCommand(
15+
MoveToFolderRefactoring refactoring,
16+
MoveToFolderRefactoringFailedNotifier failureNotifier,
17+
ISelectionProvider selectionProvider,
18+
RubberduckParserState state,
19+
ISelectedDeclarationProvider selectedDeclarationProvider)
20+
: base(refactoring, failureNotifier, selectionProvider, state)
21+
{
22+
_selectedDeclarationProvider = selectedDeclarationProvider;
23+
_state = state;
24+
25+
AddToCanExecuteEvaluation(SpecializedEvaluateCanExecute);
26+
}
27+
28+
private bool SpecializedEvaluateCanExecute(object parameter)
29+
{
30+
var target = GetTarget();
31+
32+
return target != null
33+
&& target is ModuleDeclaration
34+
&& !_state.IsNewOrModified(target.QualifiedModuleName);
35+
}
36+
37+
private Declaration GetTarget()
38+
{
39+
return _selectedDeclarationProvider.SelectedModule();
40+
}
41+
}
42+
}

Rubberduck.Core/UI/Command/Refactorings/Notifiers/MoveCloserToUsageFailedNotifier.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public class MoveCloserToUsageFailedNotifier : RefactoringFailureNotifierBase
99
{
1010
public MoveCloserToUsageFailedNotifier(IMessageBox messageBox)
1111
: base(messageBox)
12-
{ }
12+
{}
1313

1414
protected override string Caption => Resources.RubberduckUI.MoveCloserToUsage_Caption;
1515

@@ -45,7 +45,7 @@ protected override string Message(RefactoringException exception)
4545
case InvalidDeclarationTypeException invalidDeclarationType:
4646
Logger.Warn(invalidDeclarationType);
4747
return string.Format(Resources.RubberduckUI.RefactoringFailure_InvalidDeclarationType,
48-
invalidDeclarationType.TargetDeclaration.QualifiedModuleName,
48+
invalidDeclarationType.TargetDeclaration.QualifiedName,
4949
invalidDeclarationType.TargetDeclaration.DeclarationType,
5050
DeclarationType.Variable);
5151
default:
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using Rubberduck.Interaction;
2+
using Rubberduck.Parsing.Symbols;
3+
using Rubberduck.Refactorings.Exceptions;
4+
5+
namespace Rubberduck.UI.Command.Refactorings.Notifiers
6+
{
7+
public class MoveToFolderRefactoringFailedNotifier : RefactoringFailureNotifierBase
8+
{
9+
public MoveToFolderRefactoringFailedNotifier(IMessageBox messageBox)
10+
: base(messageBox)
11+
{}
12+
13+
protected override string Caption => Resources.RubberduckUI.MoveToFolderDialog_Caption;
14+
15+
protected override string Message(RefactoringException exception)
16+
{
17+
switch (exception)
18+
{
19+
case InvalidDeclarationTypeException invalidDeclarationType:
20+
Logger.Warn(invalidDeclarationType);
21+
return string.Format(Resources.RubberduckUI.RefactoringFailure_InvalidDeclarationType,
22+
invalidDeclarationType.TargetDeclaration.QualifiedName,
23+
invalidDeclarationType.TargetDeclaration.DeclarationType,
24+
DeclarationType.Module);
25+
default:
26+
return base.Message(exception);
27+
}
28+
}
29+
}
30+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Rubberduck.Refactorings.MoveToFolder;
2+
using Rubberduck.Resources;
3+
4+
namespace Rubberduck.UI.Refactorings.MoveToFolder
5+
{
6+
internal class MoveMultipleToFolderPresenter : RefactoringPresenterBase<MoveMultipleToFolderModel>, IMoveMultipleToFolderPresenter
7+
{
8+
private static readonly DialogData DialogData = DialogData.Create(RubberduckUI.MoveToFolderDialog_Caption, 164, 684);
9+
10+
public MoveMultipleToFolderPresenter(MoveMultipleToFolderModel model, IRefactoringDialogFactory dialogFactory) :
11+
base(DialogData, model, dialogFactory)
12+
{}
13+
}
14+
}
15+
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<UserControl x:Class="Rubberduck.UI.Refactorings.MoveToFolder.MoveMultipleToFolderView"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:converters="clr-namespace:Rubberduck.UI.Converters"
7+
mc:Ignorable="d"
8+
d:DesignHeight="300" d:DesignWidth="300">
9+
<UserControl.Resources>
10+
<ResourceDictionary>
11+
<ResourceDictionary.MergedDictionaries>
12+
<ResourceDictionary Source="../../Controls/ToolBar.xaml"/>
13+
</ResourceDictionary.MergedDictionaries>
14+
15+
<BitmapImage x:Key="InvalidFolderImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/cross-circle.png" />
16+
</ResourceDictionary>
17+
</UserControl.Resources>
18+
<Grid>
19+
<Grid.RowDefinitions>
20+
<RowDefinition Height="50" />
21+
<RowDefinition Height="*" />
22+
<RowDefinition Height="40" />
23+
</Grid.RowDefinitions>
24+
<StackPanel Background="{StaticResource BackgroundLightBrush}">
25+
<Label Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=MoveToFolderDialog_TitleText}" FontWeight="Bold" />
26+
<TextBlock Text="{Binding Instructions}" Margin="5,0" />
27+
</StackPanel>
28+
<Grid Grid.Row="1" Margin="5,10,10,5">
29+
<Grid.ColumnDefinitions>
30+
<ColumnDefinition Width="auto" />
31+
<ColumnDefinition Width="*" />
32+
</Grid.ColumnDefinitions>
33+
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=MoveToFolderDialog_FolderLabelText}"
34+
VerticalAlignment="Top"
35+
Margin="0,0,5,0" />
36+
<TextBox Name="MoveToFolderTextBox"
37+
Grid.Column="1"
38+
Text="{Binding NewFolder, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
39+
Height="22"
40+
VerticalAlignment="Top"
41+
VerticalContentAlignment="Center"
42+
HorizontalAlignment="Stretch" />
43+
<Image Grid.Column="1"
44+
Source="{StaticResource InvalidFolderImage}"
45+
Height="16"
46+
Margin="0,-8,-8,0"
47+
HorizontalAlignment="Right"
48+
VerticalAlignment="Top"
49+
Visibility="{Binding IsValidFolder, Converter={StaticResource BoolToHiddenVisibility}}"/>
50+
</Grid>
51+
<Grid Grid.Row="2" Background="{x:Static SystemColors.ControlDarkBrush}" Grid.IsSharedSizeScope="True">
52+
<Grid HorizontalAlignment="Right"
53+
Margin="5,0">
54+
<Grid.ColumnDefinitions>
55+
<ColumnDefinition SharedSizeGroup="SettingsButtons" />
56+
<ColumnDefinition SharedSizeGroup="SettingsButtons" />
57+
</Grid.ColumnDefinitions>
58+
<Button Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=OK}"
59+
Grid.Column="0"
60+
Height="20"
61+
Margin="5,0"
62+
Padding="10,0"
63+
IsEnabled="{Binding IsValidFolder}"
64+
IsDefault="True"
65+
Command="{Binding OkButtonCommand}" />
66+
<Button Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=CancelButtonText}"
67+
Grid.Column="1"
68+
Height="20"
69+
Margin="5,0"
70+
Padding="10,0"
71+
IsCancel="True"
72+
Command="{Binding CancelButtonCommand}">
73+
</Button>
74+
</Grid>
75+
</Grid>
76+
</Grid>
77+
</UserControl>

0 commit comments

Comments
 (0)