Skip to content

Commit 5f24969

Browse files
committed
Add UI for AnnotateDeclarationRefactoring
Also adds INotifyErrorInfo to ViewModelBase in order to allow more idiomatic validation in the UI.
1 parent 9ba3d0f commit 5f24969

27 files changed

+1777
-11
lines changed

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\AnnotateDeclaration\AnnotateDeclarationView.xaml.cs">
121+
<DependentUpon>AnnotateDeclarationView.xaml</DependentUpon>
122+
</Compile>
120123
<Compile Update="UI\Refactorings\MoveFolder\MoveMultipleFoldersView.xaml.cs">
121124
<DependentUpon>MoveMultipleFoldersView.xaml</DependentUpon>
122125
</Compile>

Rubberduck.Core/UI/Converters/BoolToVisibleVisibilityConverter.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Globalization;
4-
using System.Linq;
5-
using System.Text;
6-
using System.Threading.Tasks;
73
using System.Windows;
84
using System.Windows.Data;
95

Rubberduck.Core/UI/Converters/DeclarationToMemberSignatureConverter.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Collections.Generic;
55
using System.Globalization;
66
using System.Linq;
7-
using System.Windows;
87
using System.Windows.Data;
98

109
namespace Rubberduck.UI.Converters
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Windows;
4+
using System.Windows.Data;
5+
using Rubberduck.Parsing.Symbols;
6+
7+
namespace Rubberduck.UI.Converters
8+
{
9+
public class DeclarationToQualifiedNameConverter : IValueConverter
10+
{
11+
private readonly IValueConverter _declarationTypeConverter;
12+
13+
public DeclarationToQualifiedNameConverter()
14+
{
15+
_declarationTypeConverter = new EnumToLocalizedStringConverter
16+
{
17+
ResourcePrefix = "DeclarationType_"
18+
};
19+
20+
}
21+
22+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
23+
{
24+
if (!(value is Declaration declaration))
25+
{
26+
throw new ArgumentException("The value must be an instance of Declaration.", "value");
27+
}
28+
29+
var qualifiedNameText = declaration.QualifiedName.ToString();
30+
var declarationTypeText = _declarationTypeConverter.Convert(declaration.DeclarationType, targetType, null, culture);
31+
32+
return $"{qualifiedNameText} ({declarationTypeText})";
33+
}
34+
35+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
36+
{
37+
return DependencyProperty.UnsetValue;
38+
}
39+
}
40+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Windows.Data;
4+
using Rubberduck.Resources;
5+
6+
namespace Rubberduck.UI.Converters
7+
{
8+
//Based on https://stackoverflow.com/a/29659265 by Yoh Deadfall
9+
public class EnumToLocalizedStringConverter : IValueConverter
10+
{
11+
public string ResourcePrefix { get; set; }
12+
13+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
14+
{
15+
if (value == null)
16+
{
17+
throw new ArgumentException("The value cannot be null.", "value");
18+
}
19+
20+
//TODO: Make this independent of the resource used.
21+
return RubberduckUI.ResourceManager.GetString(ResourcePrefix + value.ToString(), culture);
22+
}
23+
24+
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
25+
{
26+
var str = (string)value;
27+
28+
foreach (var enumValue in Enum.GetValues(targetType))
29+
{
30+
//TODO: Make this independent of the resource used.
31+
if (str == RubberduckUI.ResourceManager.GetString(ResourcePrefix + enumValue.ToString(), culture))
32+
{
33+
return enumValue;
34+
}
35+
}
36+
37+
throw new ArgumentException("There is no enumeration member corresponding to the specified name.", "value");
38+
}
39+
}
40+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Windows;
4+
using System.Windows.Data;
5+
using Rubberduck.CodeAnalysis.Inspections;
6+
using Rubberduck.Resources.Inspections;
7+
8+
namespace Rubberduck.UI.Converters
9+
{
10+
public class InspectionToLocalizedNameConverter : IValueConverter
11+
{
12+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
13+
{
14+
var inspectionName = value is IInspection inspection
15+
? inspection.Name
16+
: value as string;
17+
18+
if (inspectionName == null)
19+
{
20+
21+
throw new ArgumentException("The value must be an instance of IInspection or a string containing the programmatic name of an inspection.", "value");
22+
}
23+
24+
return InspectionNames.ResourceManager.GetString(inspectionName, culture);
25+
}
26+
27+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
28+
{
29+
return DependencyProperty.UnsetValue;
30+
}
31+
}
32+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Rubberduck.Refactorings.AnnotateDeclaration;
2+
using Rubberduck.Resources;
3+
4+
namespace Rubberduck.UI.Refactorings.AnnotateDeclaration
5+
{
6+
internal class AnnotateDeclarationPresenter : RefactoringPresenterBase<AnnotateDeclarationModel>, IAnnotateDeclarationPresenter
7+
{
8+
private static readonly DialogData DialogData = DialogData.Create(RubberduckUI.AnnotateDeclarationDialog_Caption, 164, 684);
9+
10+
public AnnotateDeclarationPresenter(AnnotateDeclarationModel model, IRefactoringDialogFactory dialogFactory) :
11+
base(DialogData, model, dialogFactory)
12+
{}
13+
}
14+
}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
<UserControl x:Class="Rubberduck.UI.Refactorings.AnnotateDeclaration.AnnotateDeclarationView"
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+
xmlns:local="clr-namespace:Rubberduck.UI.Refactorings.AnnotateDeclaration"
8+
xmlns:annotations="clr-namespace:Rubberduck.Parsing.Annotations;assembly=Rubberduck.Parsing"
9+
mc:Ignorable="d"
10+
d:DesignHeight="300" d:DesignWidth="300">
11+
<UserControl.Resources>
12+
<ResourceDictionary>
13+
<ResourceDictionary.MergedDictionaries>
14+
<ResourceDictionary Source="../../Controls/ToolBar.xaml"/>
15+
</ResourceDictionary.MergedDictionaries>
16+
17+
<converters:EnumToLocalizedStringConverter ResourcePrefix="AnnotationArgumentType_" x:Key="AnnotationArgumentTypeToStringConverter"/>
18+
<converters:InspectionToLocalizedNameConverter x:Key="InspectionToLocalizedNameConverter"/>
19+
<converters:DeclarationToQualifiedNameConverter x:Key="DeclarationToQualifiedNameConverter"/>
20+
21+
<BitmapImage x:Key="InvalidTextImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/cross-circle.png" />
22+
<Style x:Key="TextBoxErrorStyle" TargetType="{x:Type TextBox}">
23+
<Setter Property="Validation.ErrorTemplate">
24+
<Setter.Value>
25+
<ControlTemplate x:Name="TextBoxErrorTemplate">
26+
<DockPanel LastChildFill="True">
27+
<AdornedElementPlaceholder/>
28+
<Image Source="{StaticResource InvalidTextImage}"
29+
Height="16"
30+
Margin="0,-8,-8,0"
31+
HorizontalAlignment="Right"
32+
VerticalAlignment="Top"/>
33+
</DockPanel>
34+
</ControlTemplate>
35+
</Setter.Value>
36+
</Setter>
37+
<Style.Triggers>
38+
<Trigger Property="Validation.HasError"
39+
Value="True">
40+
<Setter Property="ToolTip"
41+
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
42+
Path=(Validation.Errors)[0].ErrorContent}">
43+
</Setter>
44+
</Trigger>
45+
</Style.Triggers>
46+
</Style>
47+
</ResourceDictionary>
48+
</UserControl.Resources>
49+
50+
<Grid>
51+
<Grid.RowDefinitions>
52+
<RowDefinition Height="auto" />
53+
<RowDefinition Height="auto" />
54+
<RowDefinition Height="*" />
55+
<RowDefinition Height="40" />
56+
</Grid.RowDefinitions>
57+
<StackPanel Background="{StaticResource BackgroundLightBrush}">
58+
<Label Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=AnnotateDeclarationDialog_TitleText}" FontWeight="Bold" />
59+
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=AnnotateDeclarationDialog_Instructions}" Margin="5,0" TextWrapping="Wrap" />
60+
</StackPanel>
61+
<StackPanel Grid.Row="1">
62+
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=AnnotateDeclarationDialog_DeclarationLabel}" Margin="5,0" />
63+
<TextBlock Text="{Binding Model.Target, Converter={StaticResource DeclarationToQualifiedNameConverter}}" Margin="10,0" />
64+
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=AnnotateDeclarationDialog_AnnotationLabel}" Margin="5,5,0,0" />
65+
<ComboBox
66+
ItemsSource="{Binding ApplicableAnnotations}"
67+
SelectedItem="{Binding Annotation}"
68+
IsSynchronizedWithCurrentItem="True"
69+
Margin="5,0">
70+
<ComboBox.ItemTemplate>
71+
<DataTemplate DataType="{x:Type annotations:IAnnotation}">
72+
<TextBlock Text="{Binding Name, StringFormat=@{}{0}}"/>
73+
</DataTemplate>
74+
</ComboBox.ItemTemplate>
75+
</ComboBox>
76+
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=AnnotateDeclarationDialog_ArgumentsLabel}" Margin="5,5,0,0" />
77+
</StackPanel>
78+
<Grid Grid.Row="2">
79+
<Grid.ColumnDefinitions>
80+
<ColumnDefinition Width="*" />
81+
<ColumnDefinition Width="auto" />
82+
</Grid.ColumnDefinitions>
83+
<Grid.Resources>
84+
<DataTemplate DataType="{x:Type local:IAnnotationArgumentViewModel}" x:Key="ArgumentSingleTypeTemplate">
85+
<TextBlock Text="{Binding ArgumentType, Converter={StaticResource AnnotationArgumentTypeToStringConverter}}"/>
86+
</DataTemplate>
87+
<DataTemplate DataType="{x:Type local:IAnnotationArgumentViewModel}" x:Key="ArgumentMultiTypeTemplate">
88+
<ComboBox
89+
ItemsSource="{Binding Path=ApplicableArgumentTypes, Converter={StaticResource AnnotationArgumentTypeToStringConverter}}"
90+
SelectedItem="{Binding Path=ArgumentType, Converter={StaticResource AnnotationArgumentTypeToStringConverter}}"
91+
IsSynchronizedWithCurrentItem="True"/>
92+
</DataTemplate>
93+
<DataTemplate DataType="{x:Type local:IAnnotationArgumentViewModel}" x:Key="ArgumentValueTemplate">
94+
<TextBox
95+
Text="{Binding Path=ArgumentValue, ValidatesOnNotifyDataErrors=True}"
96+
Style="{StaticResource TextBoxErrorStyle}"/>
97+
</DataTemplate>
98+
<DataTemplate DataType="{x:Type local:IAnnotationArgumentViewModel}" x:Key="ArgumentValueBooleanTemplate">
99+
<ComboBox
100+
SelectedItem="{Binding Path=ArgumentValue}"
101+
IsSynchronizedWithCurrentItem="True">
102+
<TextBlock Text="True"/>
103+
<TextBlock Text="False"/>
104+
</ComboBox>
105+
</DataTemplate>
106+
<DataTemplate DataType="{x:Type local:IAnnotationArgumentViewModel}" x:Key="ArgumentValueInspectionTemplate">
107+
<ComboBox
108+
SelectedItem="{Binding Path=ArgumentValue}"
109+
IsSynchronizedWithCurrentItem="True">
110+
<ComboBox.ItemTemplate>
111+
<DataTemplate>
112+
<TextBlock Text="{Binding Path=., Converter={StaticResource InspectionToLocalizedNameConverter}}"/>
113+
</DataTemplate>
114+
</ComboBox.ItemTemplate>
115+
</ComboBox>
116+
</DataTemplate>
117+
<local:AnnotationArgumentTypeCellDataTemplateSelector x:Key="AnnotationArgumentTypeCellDataTemplateSelector"/>
118+
<local:AnnotationArgumentValueCellDataTemplateSelector x:Key="AnnotationArgumentValueCellDataTemplateSelector"/>
119+
</Grid.Resources>
120+
<DataGrid
121+
Grid.Column="0"
122+
VerticalAlignment="Stretch"
123+
ItemsSource="{Binding Path=AnnotationArguments}"
124+
AutoGenerateColumns="False"
125+
VerticalScrollBarVisibility="Auto"
126+
Margin="5,0,0,5">
127+
<DataGrid.Columns>
128+
<DataGridTemplateColumn
129+
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=AnnotateDeclarationDialog_ArgumentTypeHeader}"
130+
CellTemplateSelector="{StaticResource AnnotationArgumentTypeCellDataTemplateSelector}"
131+
CellEditingTemplateSelector="{StaticResource AnnotationArgumentTypeCellDataTemplateSelector}">
132+
</DataGridTemplateColumn>
133+
<DataGridTemplateColumn
134+
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=AnnotateDeclarationDialog_ArgumentValueHeader}"
135+
CellTemplateSelector="{StaticResource AnnotationArgumentValueCellDataTemplateSelector}"
136+
CellEditingTemplateSelector="{StaticResource AnnotationArgumentValueCellDataTemplateSelector}">
137+
</DataGridTemplateColumn>
138+
</DataGrid.Columns>
139+
</DataGrid>
140+
<StackPanel
141+
Grid.Column="1"
142+
VerticalAlignment="Center">
143+
<Button Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=AnnotateDeclarationDialog_AddArgumentButtonLabel}"
144+
Height="20"
145+
Margin="5,2.5"
146+
Padding="10,0"
147+
Command="{Binding AddAnnotationArgument}"/>
148+
<Button Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=AnnotateDeclarationDialog_RemoveArgumentButtonLabel}"
149+
Height="20"
150+
Margin="5,2.5"
151+
Padding="10,0"
152+
Command="{Binding RemoveAnnotationArgument}"/>
153+
</StackPanel>
154+
</Grid>
155+
<Grid Grid.Row="3" Background="{x:Static SystemColors.ControlDarkBrush}" Grid.IsSharedSizeScope="True">
156+
<Grid HorizontalAlignment="Right"
157+
Margin="5,0">
158+
<Grid.ColumnDefinitions>
159+
<ColumnDefinition SharedSizeGroup="SettingsButtons" />
160+
<ColumnDefinition SharedSizeGroup="SettingsButtons" />
161+
</Grid.ColumnDefinitions>
162+
<Button Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=OK}"
163+
Grid.Column="0"
164+
Height="20"
165+
Margin="5,0"
166+
Padding="10,0"
167+
IsEnabled="{Binding IsValidAnnotation}"
168+
IsDefault="True"
169+
Command="{Binding OkButtonCommand}" />
170+
<Button Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=CancelButtonText}"
171+
Grid.Column="1"
172+
Height="20"
173+
Margin="5,0"
174+
Padding="10,0"
175+
IsCancel="True"
176+
Command="{Binding CancelButtonCommand}">
177+
</Button>
178+
</Grid>
179+
</Grid>
180+
</Grid>
181+
</UserControl>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Rubberduck.Refactorings;
2+
using Rubberduck.Refactorings.AnnotateDeclaration;
3+
4+
namespace Rubberduck.UI.Refactorings.AnnotateDeclaration
5+
{
6+
public partial class AnnotateDeclarationView : IRefactoringView<AnnotateDeclarationModel>
7+
{
8+
public AnnotateDeclarationView()
9+
{
10+
InitializeComponent();
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)