Skip to content

Commit db8405e

Browse files
committed
Feature: Profile filter
1 parent 4e14f47 commit db8405e

File tree

3 files changed

+225
-5
lines changed

3 files changed

+225
-5
lines changed

Source/NETworkManager/ProfileDialogManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ public static Task ShowDeleteProfileDialog(Window parentWindow, IProfileManagerM
581581
Strings.Delete
582582
);
583583

584-
childWindow.Title = Strings.DeleteProfile;
584+
childWindow.Title = profiles.Count == 1 ? Strings.DeleteProfile : Strings.DeleteProfiles;
585585

586586
childWindow.DataContext = childWindowViewModel;
587587

Source/NETworkManager/ViewModels/ProfilesViewModel.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Collections;
77
using System.Collections.Generic;
8+
using System.Collections.ObjectModel;
89
using System.ComponentModel;
910
using System.Linq;
1011
using System.Windows;
@@ -158,6 +159,69 @@ public bool IsSearching
158159
}
159160
}
160161

162+
private bool _profileFilterIsOpen;
163+
164+
public bool ProfileFilterIsOpen
165+
{
166+
get => _profileFilterIsOpen;
167+
set
168+
{
169+
if (value == _profileFilterIsOpen)
170+
return;
171+
172+
_profileFilterIsOpen = value;
173+
OnPropertyChanged();
174+
}
175+
}
176+
177+
public ICollectionView ProfileFilterTagsView { get; set; }
178+
179+
public ObservableCollection<ProfileFilterTagsInfo> ProfileFilterTags { get; set; } = [];
180+
181+
private bool _profileFilterTagsMatchAny = GlobalStaticConfiguration.Profile_TagsMatchAny;
182+
183+
public bool ProfileFilterTagsMatchAny
184+
{
185+
get => _profileFilterTagsMatchAny;
186+
set
187+
{
188+
if (value == _profileFilterTagsMatchAny)
189+
return;
190+
191+
_profileFilterTagsMatchAny = value;
192+
OnPropertyChanged();
193+
}
194+
}
195+
196+
private bool _profileFilterTagsMatchAll;
197+
198+
public bool ProfileFilterTagsMatchAll
199+
{
200+
get => _profileFilterTagsMatchAll;
201+
set
202+
{
203+
if (value == _profileFilterTagsMatchAll)
204+
return;
205+
206+
_profileFilterTagsMatchAll = value;
207+
OnPropertyChanged();
208+
}
209+
}
210+
211+
private bool _isProfileFilterSet;
212+
213+
public bool IsProfileFilterSet
214+
{
215+
get => _isProfileFilterSet;
216+
set
217+
{
218+
if (value == _isProfileFilterSet)
219+
return;
220+
221+
_isProfileFilterSet = value;
222+
OnPropertyChanged();
223+
}
224+
}
161225
#endregion
162226

163227
#region Commands & Actions
@@ -224,6 +288,36 @@ private void DeleteGroupAction()
224288
ProfileDialogManager.ShowDeleteGroupDialog(Application.Current.MainWindow, this, SelectedGroup).ConfigureAwait(false);
225289
}
226290

291+
public ICommand OpenProfileFilterCommand => new RelayCommand(_ => OpenProfileFilterAction());
292+
293+
private void OpenProfileFilterAction()
294+
{
295+
ProfileFilterIsOpen = true;
296+
}
297+
298+
public ICommand ApplyProfileFilterCommand => new RelayCommand(_ => ApplyProfileFilterAction());
299+
300+
private void ApplyProfileFilterAction()
301+
{
302+
RefreshProfiles();
303+
304+
IsProfileFilterSet = true;
305+
ProfileFilterIsOpen = false;
306+
}
307+
308+
public ICommand ClearProfileFilterCommand => new RelayCommand(_ => ClearProfileFilterAction());
309+
310+
private void ClearProfileFilterAction()
311+
{
312+
foreach (var tag in ProfileFilterTags)
313+
tag.IsSelected = false;
314+
315+
RefreshProfiles();
316+
317+
IsProfileFilterSet = false;
318+
ProfileFilterIsOpen = false;
319+
}
320+
227321
#endregion
228322

229323
#region Methods

Source/NETworkManager/Views/ProfilesView.xaml

Lines changed: 130 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
<UserControl.Resources>
1818
<converters:BooleanReverseToVisibilityCollapsedConverter x:Key="BooleanReverseToVisibilityCollapsedConverter" />
1919
<converters:BooleanToVisibilityCollapsedConverter x:Key="BooleanToVisibilityCollapsedConverter" />
20+
<converters:IntNotZeroToVisibilityCollapsedConverter x:Key="IntNotZeroToVisibilityCollapsedConverter" />
21+
<converters:IntZeroToVisibilityCollapsedConverter x:Key="IntZeroToVisibilityCollapsedConverter" />
2022
</UserControl.Resources>
2123
<Grid>
2224
<Grid Grid.Column="0" Grid.Row="0"
@@ -118,10 +120,134 @@
118120
</Grid.RowDefinitions>
119121
<TextBlock Grid.Column="0" Grid.Row="0" Style="{StaticResource HeaderTextBlock}"
120122
Text="{x:Static localization:Strings.Profiles}" />
121-
<TextBox x:Name="TextBoxSearch" Grid.Column="0" Grid.Row="0" VerticalAlignment="Center"
122-
HorizontalAlignment="Right" Width="250"
123-
Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}"
124-
Style="{StaticResource SearchTextBox}" />
123+
124+
<Grid Grid.Column="0" Grid.Row="0" VerticalAlignment="Center"
125+
HorizontalAlignment="Right">
126+
<Grid.ColumnDefinitions>
127+
<ColumnDefinition Width="250" />
128+
<ColumnDefinition Width="10" />
129+
<ColumnDefinition Width="Auto" />
130+
</Grid.ColumnDefinitions>
131+
<TextBox x:Name="TextBoxSearch"
132+
Grid.Row="0" Grid.Column="0"
133+
Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}"
134+
Style="{StaticResource SearchTextBox}" />
135+
<Button Grid.Column="2" Grid.Row="0"
136+
x:Name="ButtonProfileFilter"
137+
Focusable="False"
138+
Style="{StaticResource ResourceKey=CleanButton}"
139+
Command="{Binding Path=OpenProfileFilterCommand}"
140+
ToolTip="{x:Static Member=localization:Strings.FilterProfilesDots}">
141+
<Rectangle Width="16" Height="16">
142+
<Rectangle.Resources>
143+
<VisualBrush x:Key="VisualFilter" Stretch="Uniform"
144+
Visual="{iconPacks:Material Kind=FilterOutline}" />
145+
<VisualBrush x:Key="VisualFilterRemove" Stretch="Uniform"
146+
Visual="{iconPacks:Material Kind=FilterMultipleOutline}" />
147+
</Rectangle.Resources>
148+
<Rectangle.Style>
149+
<Style TargetType="{x:Type TypeName=Rectangle}">
150+
<Setter Property="OpacityMask"
151+
Value="{StaticResource ResourceKey=VisualFilter}" />
152+
<Setter Property="Fill"
153+
Value="{DynamicResource ResourceKey=MahApps.Brushes.Gray3}" />
154+
<Style.Triggers>
155+
<DataTrigger Binding="{Binding Path=IsProfileFilterSet}" Value="True">
156+
<Setter Property="OpacityMask"
157+
Value="{StaticResource ResourceKey=VisualFilterRemove}" />
158+
</DataTrigger>
159+
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TypeName=Button}}, Path=IsMouseOver}"
160+
Value="True">
161+
<Setter Property="Fill"
162+
Value="{DynamicResource ResourceKey=MahApps.Brushes.Gray5}" />
163+
</DataTrigger>
164+
</Style.Triggers>
165+
</Style>
166+
</Rectangle.Style>
167+
</Rectangle>
168+
</Button>
169+
<Popup PlacementTarget="{Binding ElementName=ButtonProfileFilter}"
170+
Placement="Bottom" StaysOpen="False"
171+
IsOpen="{Binding ProfileFilterIsOpen}"
172+
Width="220">
173+
<Border Background="{DynamicResource MahApps.Brushes.Window.Background}"
174+
BorderBrush="{DynamicResource MahApps.Brushes.Gray8}"
175+
BorderThickness="1">
176+
<Grid Margin="10">
177+
<Grid.RowDefinitions>
178+
<RowDefinition Height="Auto" />
179+
<RowDefinition Height="10" />
180+
<RowDefinition MaxHeight="150" />
181+
<RowDefinition Height="10" />
182+
<RowDefinition Height="Auto" />
183+
<RowDefinition Height="10" />
184+
<RowDefinition Height="Auto" />
185+
<RowDefinition Height="10" />
186+
<RowDefinition Height="Auto" />
187+
</Grid.RowDefinitions>
188+
<TextBlock Grid.Column="0" Grid.Row="0"
189+
Text="{x:Static Member=localization:Strings.FilterByTags}"
190+
Style="{StaticResource InfoTextBlock}"/>
191+
<ScrollViewer Grid.Column="0" Grid.Row="2"
192+
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden"
193+
Visibility="{Binding Path=ProfileFilterTagsView.Count, Converter={StaticResource IntNotZeroToVisibilityCollapsedConverter}}">
194+
<ItemsControl ItemsSource="{Binding ProfileFilterTagsView}"
195+
Width="200">
196+
<ItemsControl.ItemsPanel>
197+
<ItemsPanelTemplate>
198+
<WrapPanel />
199+
</ItemsPanelTemplate>
200+
</ItemsControl.ItemsPanel>
201+
<ItemsControl.ItemTemplate>
202+
<DataTemplate DataType="{x:Type profiles:ProfileFilterTagsInfo}">
203+
<CheckBox Margin="0,5,10,5" Content="{Binding Name}"
204+
IsChecked="{Binding IsSelected}"
205+
Style="{StaticResource DefaultCheckBox}" />
206+
</DataTemplate>
207+
</ItemsControl.ItemTemplate>
208+
</ItemsControl>
209+
</ScrollViewer>
210+
<TextBlock Grid.Column="0" Grid.Row="2"
211+
Text="{x:Static localization:Strings.NoTagsFound}"
212+
Visibility="{Binding Path=ProfileFilterTagsView.Count, Converter={StaticResource IntZeroToVisibilityCollapsedConverter}}"
213+
Style="{StaticResource MessageTextBlock}" />
214+
<TextBlock Grid.Column="0" Grid.Row="4"
215+
Text="{x:Static localization:Strings.Match}"
216+
Style="{StaticResource InfoTextBlock}"/>
217+
<StackPanel Grid.Column="0" Grid.Row="6"
218+
Orientation="Horizontal">
219+
<RadioButton Content="{x:Static localization:Strings.Any}"
220+
IsChecked="{Binding Path=ProfileFilterTagsMatchAny}" />
221+
<RadioButton Content="{x:Static localization:Strings.All}"
222+
IsChecked="{Binding Path=ProfileFilterTagsMatchAll}"
223+
Margin="10,0,0,0"/>
224+
</StackPanel>
225+
<StackPanel Grid.Column="0" Grid.Row="8"
226+
Orientation="Horizontal" HorizontalAlignment="Right">
227+
<Button Command="{Binding ApplyProfileFilterCommand}"
228+
Style="{StaticResource ImageButton}"
229+
ToolTip="{x:Static localization:Strings.ApplyFilter}">
230+
<Rectangle Width="16" Height="16" Fill="{DynamicResource MahApps.Brushes.Gray3}">
231+
<Rectangle.OpacityMask>
232+
<VisualBrush Stretch="Uniform" Visual="{iconPacks:Material Kind=ContentSaveOutline}" />
233+
</Rectangle.OpacityMask>
234+
</Rectangle>
235+
</Button>
236+
<Button Command="{Binding ClearProfileFilterCommand}"
237+
Style="{StaticResource ImageButton}"
238+
ToolTip="{x:Static localization:Strings.ClearFilter}"
239+
Margin="10,0,0,0">
240+
<Rectangle Width="20" Height="20" Fill="{DynamicResource MahApps.Brushes.Gray3}">
241+
<Rectangle.OpacityMask>
242+
<VisualBrush Stretch="Uniform" Visual="{iconPacks:Material Kind=FilterRemoveOutline}" />
243+
</Rectangle.OpacityMask>
244+
</Rectangle>
245+
</Button>
246+
</StackPanel>
247+
</Grid>
248+
</Border>
249+
</Popup>
250+
</Grid>
125251
<controls:MultiSelectDataGrid x:Name="DataGridProfiles" Grid.Column="0" Grid.Row="1"
126252
Visibility="{Binding IsSearching, Converter={StaticResource BooleanReverseToVisibilityCollapsedConverter}}"
127253
ItemsSource="{Binding Profiles}" SelectedItem="{Binding SelectedProfile}"

0 commit comments

Comments
 (0)