Improve EditQuickFilters dialog reordering behavior

This commit is contained in:
MBucari 2025-07-25 14:23:14 -06:00
parent c98c7c095a
commit accedeb1b1
2 changed files with 73 additions and 41 deletions

View File

@ -24,9 +24,8 @@
CanUserSortColumns="False" CanUserSortColumns="False"
AutoGenerateColumns="False" AutoGenerateColumns="False"
IsReadOnly="False" IsReadOnly="False"
ItemsSource="{Binding Filters}" ItemsSource="{CompiledBinding Filters}"
GridLinesVisibility="All"> GridLinesVisibility="All">
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTemplateColumn Header="Delete"> <DataGridTemplateColumn Header="Delete">
@ -38,7 +37,7 @@
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center" HorizontalContentAlignment="Center"
IsEnabled="{Binding !IsDefault}" IsEnabled="{CompiledBinding !IsDefault}"
Click="DeleteButton_Clicked" /> Click="DeleteButton_Clicked" />
</DataTemplate> </DataTemplate>
@ -48,14 +47,13 @@
<DataGridTextColumn <DataGridTextColumn
Width="*" Width="*"
IsReadOnly="False" IsReadOnly="False"
Binding="{Binding Name, Mode=TwoWay}" Binding="{CompiledBinding Name, Mode=TwoWay}"
Header="Name"/> Header="Name"/>
<DataGridTextColumn <DataGridTextColumn
Width="*" Width="*"
IsReadOnly="False" IsReadOnly="False"
Binding="{Binding FilterString, Mode=TwoWay}" Binding="{CompiledBinding FilterString, Mode=TwoWay}"
Header="Filter"/> Header="Filter"/>
<DataGridTemplateColumn Header="Move&#xa;Up"> <DataGridTemplateColumn Header="Move&#xa;Up">
@ -67,16 +65,19 @@
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center" HorizontalContentAlignment="Center"
IsEnabled="{Binding !IsDefault}" Click="MoveUpButton_Clicked">
ToolTip.Tip="Export account authorization to audible-cli" <Button.IsEnabled>
Click="MoveUpButton_Clicked" /> <MultiBinding Converter="{x:Static BoolConverters.And}">
<CompiledBinding Path="!IsTop" />
<CompiledBinding Path="!IsDefault" />
</MultiBinding>
</Button.IsEnabled>
</Button>
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Header="Move&#xa;Down"> <DataGridTemplateColumn Header="Move&#xa;Down">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
@ -86,15 +87,18 @@
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center" HorizontalContentAlignment="Center"
IsEnabled="{Binding !IsDefault}" Click="MoveDownButton_Clicked">
ToolTip.Tip="Export account authorization to audible-cli" <Button.IsEnabled>
Click="MoveDownButton_Clicked" /> <MultiBinding Converter="{x:Static BoolConverters.And}">
<CompiledBinding Path="!IsBottom" />
<CompiledBinding Path="!IsDefault" />
</MultiBinding>
</Button.IsEnabled>
</Button>
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
<Grid <Grid

View File

@ -1,15 +1,15 @@
using AudibleUtilities; using AudibleUtilities;
using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using LibationFileManager; using LibationFileManager;
using ReactiveUI; using ReactiveUI;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
namespace LibationAvalonia.Dialogs namespace LibationAvalonia.Dialogs
{ {
public partial class EditQuickFilters : DialogWindow public partial class EditQuickFilters : DialogWindow
{ {
public ObservableCollection<Filter> Filters { get; } = new(); public AvaloniaList<Filter> Filters { get; } = new();
public class Filter : ViewModels.ViewModelBase public class Filter : ViewModels.ViewModelBase
{ {
@ -17,10 +17,7 @@ namespace LibationAvalonia.Dialogs
public string Name public string Name
{ {
get => _name; get => _name;
set set => this.RaiseAndSetIfChanged(ref _name, value);
{
this.RaiseAndSetIfChanged(ref _name, value);
}
} }
private string _filterString; private string _filterString;
@ -35,6 +32,10 @@ namespace LibationAvalonia.Dialogs
} }
} }
public bool IsDefault { get; private set; } = true; public bool IsDefault { get; private set; } = true;
private bool _isTop;
private bool _isBottom;
public bool IsTop { get => _isTop; set => this.RaiseAndSetIfChanged(ref _isTop, value); }
public bool IsBottom { get => _isBottom; set => this.RaiseAndSetIfChanged(ref _isBottom, value); }
public QuickFilters.NamedFilter AsNamedFilter() => new(FilterString, Name); public QuickFilters.NamedFilter AsNamedFilter() => new(FilterString, Name);
@ -44,12 +45,12 @@ namespace LibationAvalonia.Dialogs
InitializeComponent(); InitializeComponent();
if (Design.IsDesignMode) if (Design.IsDesignMode)
{ {
Filters = new ObservableCollection<Filter>([ Filters = [
new Filter { Name = "Filter 1", FilterString = "[filter1 string]" }, new Filter { Name = "Filter 1", FilterString = "[filter1 string]", IsTop = true },
new Filter { Name = "Filter 2", FilterString = "[filter2 string]" }, new Filter { Name = "Filter 2", FilterString = "[filter2 string]" },
new Filter { Name = "Filter 3", FilterString = "[filter3 string]" }, new Filter { Name = "Filter 3", FilterString = "[filter3 string]" },
new Filter { Name = "Filter 4", FilterString = "[filter4 string]" } new Filter { Name = "Filter 4", FilterString = "[filter4 string]", IsBottom = true },
]); new Filter()];
DataContext = this; DataContext = this;
return; return;
} }
@ -65,6 +66,8 @@ namespace LibationAvalonia.Dialogs
ControlToFocusOnShow = this.FindControl<Button>(nameof(saveBtn)); ControlToFocusOnShow = this.FindControl<Button>(nameof(saveBtn));
var allFilters = QuickFilters.Filters.Select(f => new Filter { FilterString = f.Filter, Name = f.Name }).ToList(); var allFilters = QuickFilters.Filters.Select(f => new Filter { FilterString = f.Filter, Name = f.Name }).ToList();
allFilters[0].IsTop = true;
allFilters[^1].IsBottom = true;
allFilters.Add(new Filter()); allFilters.Add(new Filter());
foreach (var f in allFilters) foreach (var f in allFilters)
@ -81,6 +84,7 @@ namespace LibationAvalonia.Dialogs
var newBlank = new Filter(); var newBlank = new Filter();
newBlank.PropertyChanged += Filter_PropertyChanged; newBlank.PropertyChanged += Filter_PropertyChanged;
Filters.Insert(Filters.Count, newBlank); Filters.Insert(Filters.Count, newBlank);
ReIndexFilters();
} }
protected override void SaveAndClose() protected override void SaveAndClose()
@ -98,30 +102,54 @@ namespace LibationAvalonia.Dialogs
filter.PropertyChanged -= Filter_PropertyChanged; filter.PropertyChanged -= Filter_PropertyChanged;
Filters.Remove(filter); Filters.Remove(filter);
ReIndexFilters();
} }
} }
public void MoveUpButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e) public void MoveUpButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{ {
if (e.Source is Button btn && btn.DataContext is Filter filter) if (e.Source is not Button btn || btn.DataContext is not Filter filter || filter.IsDefault)
{ return;
var index = Filters.IndexOf(filter);
if (index < 1) return;
Filters.Remove(filter); var oldIndex = Filters.IndexOf(filter);
Filters.Insert(index - 1, filter); if (oldIndex < 1) return;
}
var filterCount = Filters.Count(f => !f.IsDefault);
MoveFilter(oldIndex, oldIndex - 1, filterCount);
} }
public void MoveDownButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e) public void MoveDownButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{ {
if (e.Source is Button btn && btn.DataContext is Filter filter) if (e.Source is not Button btn || btn.DataContext is not Filter filter || filter.IsDefault)
{ return;
var index = Filters.IndexOf(filter);
if (index >= Filters.Count - 2) return;
Filters.Remove(filter); var filterCount = Filters.Count(f => !f.IsDefault);
Filters.Insert(index + 1, filter); var oldIndex = Filters.IndexOf(filter);
if (oldIndex >= filterCount - 1) return;
MoveFilter(oldIndex, oldIndex + 1, filterCount);
}
private void MoveFilter(int oldIndex, int newIndex, int filterCount)
{
var filter = Filters[oldIndex];
Filters.RemoveAt(oldIndex);
Filters.Insert(newIndex, filter);
Filters[oldIndex].IsTop = oldIndex == 0;
Filters[newIndex].IsTop = newIndex == 0;
Filters[newIndex].IsBottom = newIndex == filterCount - 1;
Filters[oldIndex].IsBottom = oldIndex == filterCount - 1;
}
private void ReIndexFilters()
{
var filterCount = Filters.Count(f => !f.IsDefault);
for (int i = filterCount - 1; i >= 0; i--)
{
Filters[i].IsTop = i == 0;
Filters[i].IsBottom = i == filterCount - 1;
} }
} }
} }