Skip to content

Commit a7a3977

Browse files
Fix settings headers (#4935)
Fix settings headers Co-authored-by: SonGokussj4 <SonGokussj4@users.noreply.github.com>
2 parents 1655c1c + aa0f199 commit a7a3977

File tree

9 files changed

+173
-30
lines changed

9 files changed

+173
-30
lines changed

Rubberduck.Core/UI/Settings/AutoCompleteSettings.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
<StackPanel Margin="5,5,5,0" ScrollViewer.VerticalScrollBarVisibility="Auto">
5959
<Label Background="DarkGray"
6060
HorizontalContentAlignment="Stretch"
61-
Margin="0,5,0,5">
61+
Margin="0,0,0,3">
6262
<Label.Style>
6363
<Style>
6464
<Style.Resources>

Rubberduck.Core/UI/Settings/GeneralSettings.xaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,14 @@
192192
Width="*"
193193
IsReadOnly="True" />
194194
<DataGridTemplateColumn
195-
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GeneralSettings_ModifierWarning}"
196-
Width="Auto">
195+
Width="Auto">
197196
<DataGridTemplateColumn.CellTemplate>
198197
<DataTemplate>
199-
<Label Content="{Resx ResxName=Rubberduck.Resources.Resources, Key=exclamation}"
200-
Visibility="{Binding IsValid, Converter={StaticResource BoolToHiddenVisibility}}"
201-
HorizontalContentAlignment="Center"
202-
ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GeneralSettings_HotkeyRestrictionToolTip}"/>
198+
<Label Visibility="{Binding IsValid, Converter={StaticResource BoolToHiddenVisibility}}"
199+
HorizontalContentAlignment="Center">
200+
<Image Source="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=exclamation}"
201+
ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GeneralSettings_HotkeyRestrictionToolTip}"/>
202+
</Label>
203203
</DataTemplate>
204204
</DataGridTemplateColumn.CellTemplate>
205205
</DataGridTemplateColumn>

Rubberduck.Core/UI/Settings/GeneralSettingsViewModel.cs

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
using Rubberduck.Resources;
1313
using Rubberduck.Resources.Settings;
1414
using Rubberduck.Parsing.Common;
15+
using System.Collections.Specialized;
16+
using Rubberduck.UI.WPF;
1517

1618
namespace Rubberduck.UI.Settings
1719
{
@@ -79,19 +81,32 @@ public DisplayLanguageSetting SelectedLanguage
7981
}
8082
}
8183

82-
private ObservableCollection<HotkeySetting> _hotkeys;
83-
public ObservableCollection<HotkeySetting> Hotkeys
84+
private ObservableViewModelCollection<HotkeySettingViewModel> _hotkeys;
85+
public ObservableViewModelCollection<HotkeySettingViewModel> Hotkeys
8486
{
8587
get => _hotkeys;
8688
set
8789
{
8890
if (_hotkeys != value)
8991
{
92+
if (_hotkeys != null)
93+
{
94+
_hotkeys.ElementPropertyChanged -= InvalidateShouldDisplayWarning;
95+
}
96+
if (value != null)
97+
{
98+
value.ElementPropertyChanged += InvalidateShouldDisplayWarning;
99+
}
90100
_hotkeys = value;
91101
OnPropertyChanged();
102+
OnPropertyChanged(nameof(ShouldDisplayHotkeyModificationLabel));
92103
}
93104
}
94105
}
106+
private void InvalidateShouldDisplayWarning(object sender, ElementPropertyChangedEventArgs<HotkeySettingViewModel> e)
107+
{
108+
OnPropertyChanged(nameof(ShouldDisplayHotkeyModificationLabel));
109+
}
95110

96111
public bool ShouldDisplayHotkeyModificationLabel
97112
{
@@ -259,7 +274,7 @@ private void ShowLogFolder()
259274
public void UpdateConfig(Configuration config)
260275
{
261276
config.UserSettings.GeneralSettings = GetCurrentGeneralSettings();
262-
config.UserSettings.HotkeySettings.Settings = Hotkeys.ToArray();
277+
config.UserSettings.HotkeySettings.Settings = Hotkeys.Select(vm => vm.Unwrap()).ToArray();
263278
}
264279

265280
public void SetToDefaults(Configuration config)
@@ -290,13 +305,13 @@ protected override void TransferSettingsToView(Rubberduck.Settings.GeneralSettin
290305
TransferSettingsToView(toLoad, null);
291306
}
292307

293-
private void TransferSettingsToView(IGeneralSettings general, IHotkeySettings hottkey)
308+
private void TransferSettingsToView(IGeneralSettings general, IHotkeySettings hotkey)
294309
{
295310
SelectedLanguage = Languages.FirstOrDefault(culture => culture.Code == general.Language.Code);
296311

297-
Hotkeys = hottkey == null
298-
? new ObservableCollection<HotkeySetting>()
299-
: new ObservableCollection<HotkeySetting>(hottkey.Settings);
312+
Hotkeys = hotkey == null
313+
? new ObservableViewModelCollection<HotkeySettingViewModel>()
314+
: new ObservableViewModelCollection<HotkeySettingViewModel>(hotkey.Settings.Select(data => new HotkeySettingViewModel(data)));
300315
ShowSplashAtStartup = general.CanShowSplash;
301316
CheckVersionAtStartup = general.CanCheckVersion;
302317
CompileBeforeParse = general.CompileBeforeParse;
@@ -352,8 +367,60 @@ protected override void ExportSettings(Rubberduck.Settings.GeneralSettings setti
352367
dialog.ShowDialog();
353368
if (string.IsNullOrEmpty(dialog.FileName)) return;
354369
Service.Save(settings, dialog.FileName);
355-
_hotkeyService.Save(new HotkeySettings { Settings = Hotkeys.ToArray() }, dialog.FileName);
370+
_hotkeyService.Save(new HotkeySettings { Settings = Hotkeys.Select(vm => vm.Unwrap()).ToArray() }, dialog.FileName);
356371
}
357372
}
358373
}
374+
375+
public class HotkeySettingViewModel : ViewModelBase
376+
{
377+
private readonly HotkeySetting wrapped;
378+
379+
public HotkeySettingViewModel(HotkeySetting wrapped)
380+
{
381+
this.wrapped = wrapped;
382+
}
383+
384+
public HotkeySetting Unwrap() { return wrapped; }
385+
386+
public string Key1
387+
{
388+
get { return wrapped.Key1; }
389+
set { wrapped.Key1 = value; OnPropertyChanged(); }
390+
}
391+
392+
public bool IsEnabled
393+
{
394+
get { return wrapped.IsEnabled; }
395+
set { wrapped.IsEnabled = value; OnPropertyChanged(); }
396+
}
397+
398+
public bool HasShiftModifier
399+
{
400+
get { return wrapped.HasShiftModifier; }
401+
set { wrapped.HasShiftModifier = value; OnPropertyChanged(); OnPropertyChanged(nameof(IsValid)); }
402+
}
403+
404+
public bool HasAltModifier
405+
{
406+
get { return wrapped.HasAltModifier; }
407+
set { wrapped.HasAltModifier = value; OnPropertyChanged(); OnPropertyChanged(nameof(IsValid)); }
408+
}
409+
410+
public bool HasCtrlModifier
411+
{
412+
get { return wrapped.HasCtrlModifier; }
413+
set { wrapped.HasCtrlModifier = value; OnPropertyChanged(); OnPropertyChanged(nameof(IsValid)); }
414+
}
415+
416+
public string CommandTypeName
417+
{
418+
get { return wrapped.CommandTypeName; }
419+
set { wrapped.CommandTypeName = value; OnPropertyChanged(); }
420+
}
421+
422+
public bool IsValid { get { return wrapped.IsValid; } }
423+
// FIXME If this is the only use, the property should be inlined to here
424+
public string Prompt { get { return wrapped.Prompt; } }
425+
}
359426
}

Rubberduck.Core/UI/Settings/InspectionSettings.xaml

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<BitmapImage x:Key="AddImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/plus-circle.png" />
2121
<BitmapImage x:Key="DeleteImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/cross-script.png" />
2222
<BitmapImage x:Key="FilterImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/Funnel.png" />
23-
23+
2424
<LinearGradientBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" EndPoint="0,1" StartPoint="0,0">
2525
<GradientStop Color="#FFD9F4FF" Offset="0"/>
2626
<GradientStop Color="#FF9BDDFB" Offset="1"/>
@@ -31,7 +31,7 @@
3131
</LinearGradientBrush>
3232
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
3333
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
34-
34+
3535
<ObjectDataProvider x:Key="Severities"
3636
MethodName="GetValues"
3737
ObjectType="{x:Type core:Enum}">
@@ -268,7 +268,7 @@
268268
<Setter Property="Background" Value="DarkGray"/>
269269
<Setter Property="CornerRadius" Value="5"/>
270270
</Style>
271-
271+
272272
<Style TargetType="ScrollViewer">
273273
<Style.Setters>
274274
<Setter Property="settings:ScrollViewerCorrector.FixScrolling" Value="True" />
@@ -279,25 +279,24 @@
279279
<ScrollViewer x:Name="ScrollViewer">
280280
<StackPanel Margin="5,5,5,0" ScrollViewer.VerticalScrollBarVisibility="Auto">
281281
<Border Style="{StaticResource BorderHeader}"
282-
Margin="0,5,0,5">
282+
Margin="0,0,0,3" Height="36">
283283
<DockPanel FlowDirection="LeftToRight">
284284
<StackPanel Orientation="Horizontal" DockPanel.Dock="Left">
285285
<Label Style="{StaticResource HeaderText}"
286-
Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=CodeInspectionSettings_InspectionSeveritySettingsLabel}" />
286+
Content="{Resx Key=CodeInspectionSettings_InspectionSeveritySettingsLabel, ResxName=Rubberduck.Resources.RubberduckUI}" Margin="5,5,0,5" Width="123" />
287287
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
288-
<Label Content="-"/>
289-
<Image Source="{StaticResource FilterImage}" />
288+
<Label Content="-" Margin="0,5"/>
289+
<Image Source="{StaticResource FilterImage}" Margin="0,5" Width="19" RenderTransformOrigin="0.564,1.859" />
290290
<Label Style="{StaticResource HeaderText}"
291-
Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=InspectionSettings_FilterByDescription}" />
291+
Content="{Resx Key=InspectionSettings_FilterByDescription, ResxName=Rubberduck.Resources.RubberduckUI}" Margin="0,5" />
292292
<TextBox MinWidth="125"
293-
Text="{Binding InspectionSettingsDescriptionFilter, UpdateSourceTrigger=PropertyChanged}"
294-
HorizontalAlignment="Stretch" />
293+
Text="{Binding InspectionSettingsDescriptionFilter, UpdateSourceTrigger=PropertyChanged}" Margin="0,5" Height="26" />
295294
<Border Width="10" />
296295
<Label Style="{StaticResource HeaderText}"
297-
Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=InspectionSettings_FilterBySeverity}" />
296+
Content="{Resx Key=InspectionSettings_FilterBySeverity, ResxName=Rubberduck.Resources.RubberduckUI}" Margin="0,5" />
298297
<ComboBox Width="100"
299298
ItemsSource="{Binding SeverityFilters, UpdateSourceTrigger=PropertyChanged}"
300-
SelectedItem="{Binding SelectedSeverityFilter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
299+
SelectedItem="{Binding SelectedSeverityFilter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="0,5" />
301300
</StackPanel>
302301
</StackPanel>
303302
<StackPanel Orientation="Horizontal" DockPanel.Dock="Right" HorizontalAlignment="Left"
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
4+
using System.Collections.Specialized;
5+
using System.ComponentModel;
6+
7+
namespace Rubberduck.UI.WPF
8+
{
9+
// Taken and adjusted from https://stackoverflow.com/a/5256827/1803692
10+
/// <summary>
11+
/// This class extends the capabilities of ObservableCollection.
12+
/// It adds an additional event, which is raised when the properties of an item stored in the collection change.
13+
/// </summary>
14+
public class ObservableViewModelCollection<T> : ObservableCollection<T>
15+
where T : INotifyPropertyChanged
16+
{
17+
public event EventHandler<ElementPropertyChangedEventArgs<T>> ElementPropertyChanged;
18+
19+
public ObservableViewModelCollection()
20+
{
21+
CollectionChanged += UpdateContributorEventHandlers;
22+
}
23+
24+
public ObservableViewModelCollection(IEnumerable<T> items) : this()
25+
{
26+
foreach (var item in items)
27+
{
28+
this.Add(item);
29+
}
30+
}
31+
32+
private void UpdateContributorEventHandlers(object sender, NotifyCollectionChangedEventArgs e)
33+
{
34+
foreach (INotifyPropertyChanged added in e.NewItems ?? new List<INotifyPropertyChanged>())
35+
{
36+
added.PropertyChanged += OnItemPropertyChanged;
37+
}
38+
foreach (INotifyPropertyChanged removed in e.OldItems ?? new List<INotifyPropertyChanged>())
39+
{
40+
removed.PropertyChanged -= OnItemPropertyChanged;
41+
}
42+
}
43+
44+
private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
45+
{
46+
var specializedArgs = new ElementPropertyChangedEventArgs<T>((T)sender, e.PropertyName);
47+
ElementPropertyChanged?.Invoke(this, specializedArgs);
48+
}
49+
}
50+
51+
public class ElementPropertyChangedEventArgs<T>
52+
{
53+
public T Element { get; private set; }
54+
public string PropertyName { get; private set; }
55+
56+
public ElementPropertyChangedEventArgs(T element, string propertyName)
57+
{
58+
Element = element;
59+
PropertyName = propertyName;
60+
}
61+
}
62+
}

Rubberduck.Resources/Settings/SettingsUI.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rubberduck.Resources/Settings/SettingsUI.cs.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,7 @@
228228
<data name="PageInstructions_ReferenceSettings" xml:space="preserve">
229229
<value>Nakonfigurovat nastavení pro přidávání a odstraňování referencí.</value>
230230
</data>
231+
<data name="HotKeys_Exclamation" xml:space="preserve">
232+
<value>Pozor! Chybí modifikátor!</value>
233+
</data>
231234
</root>

Rubberduck.Resources/Settings/SettingsUI.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,7 @@
228228
<data name="Settings_Caption" xml:space="preserve">
229229
<value>Rubberduck Settings</value>
230230
</data>
231+
<data name="HotKeys_Exclamation" xml:space="preserve">
232+
<value>Warning! No Modifier!</value>
233+
</data>
231234
</root>

RubberduckTests/Settings/GeneralSettingsTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public void SaveConfigWorks()
9999
Assert.Multiple(() =>
100100
{
101101
Assert.AreEqual(config.UserSettings.GeneralSettings.Language, viewModel.SelectedLanguage);
102-
Assert.IsTrue(config.UserSettings.HotkeySettings.Settings.SequenceEqual(viewModel.Hotkeys));
102+
Assert.IsTrue(config.UserSettings.HotkeySettings.Settings.SequenceEqual(viewModel.Hotkeys.Select(vm => vm.Unwrap())));
103103
Assert.AreEqual(config.UserSettings.GeneralSettings.IsAutoSaveEnabled, viewModel.AutoSaveEnabled);
104104
Assert.AreEqual(config.UserSettings.GeneralSettings.AutoSavePeriod, viewModel.AutoSavePeriod);
105105
});
@@ -117,7 +117,7 @@ public void SetDefaultsWorks()
117117
Assert.Multiple(() =>
118118
{
119119
Assert.AreEqual(defaultConfig.UserSettings.GeneralSettings.Language, viewModel.SelectedLanguage);
120-
Assert.IsTrue(defaultConfig.UserSettings.HotkeySettings.Settings.SequenceEqual(viewModel.Hotkeys));
120+
Assert.IsTrue(defaultConfig.UserSettings.HotkeySettings.Settings.SequenceEqual(viewModel.Hotkeys.Select(vm => vm.Unwrap())));
121121
Assert.AreEqual(defaultConfig.UserSettings.GeneralSettings.IsAutoSaveEnabled, viewModel.AutoSaveEnabled);
122122
Assert.AreEqual(defaultConfig.UserSettings.GeneralSettings.AutoSavePeriod, viewModel.AutoSavePeriod);
123123
});
@@ -140,7 +140,7 @@ public void HotkeysAreSetInCtor()
140140
var defaultConfig = GetDefaultConfig();
141141
var viewModel = new GeneralSettingsViewModel(defaultConfig, GetOperatingSystemMock().Object, GetMessageBoxMock().Object, GetVbeSettingsMock().Object, GetExperimentalTypesProviderMock().Object, null, null);
142142

143-
Assert.IsTrue(defaultConfig.UserSettings.HotkeySettings.Settings.SequenceEqual(viewModel.Hotkeys));
143+
Assert.IsTrue(defaultConfig.UserSettings.HotkeySettings.Settings.SequenceEqual(viewModel.Hotkeys.Select(vm => vm.Unwrap())));
144144
}
145145

146146
[Category("Settings")]

0 commit comments

Comments
 (0)