diff --git a/Source/LibationWinForms/AvaloniaUI/App.axaml b/Source/LibationWinForms/AvaloniaUI/App.axaml index 3526c826..f8ef3650 100644 --- a/Source/LibationWinForms/AvaloniaUI/App.axaml +++ b/Source/LibationWinForms/AvaloniaUI/App.axaml @@ -12,5 +12,6 @@ + \ No newline at end of file diff --git a/Source/LibationWinForms/AvaloniaUI/App.axaml.cs b/Source/LibationWinForms/AvaloniaUI/App.axaml.cs index 2351216d..c38a0ef0 100644 --- a/Source/LibationWinForms/AvaloniaUI/App.axaml.cs +++ b/Source/LibationWinForms/AvaloniaUI/App.axaml.cs @@ -1,12 +1,20 @@ using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; +using Avalonia.Media; using LibationWinForms.AvaloniaUI.Views; namespace LibationWinForms.AvaloniaUI { public class App : Application { + public static IBrush ProcessQueueBookFailedBrush { get; private set; } + public static IBrush ProcessQueueBookCompletedBrush { get; private set; } + public static IBrush ProcessQueueBookCancelledBrush { get; private set; } + public static IBrush ProcessQueueBookDefaultBrush { get; private set; } + public static IBrush SeriesEntryGridBackgroundBrush { get; private set; } + + public override void Initialize() { AvaloniaXamlLoader.Load(this); @@ -14,6 +22,8 @@ namespace LibationWinForms.AvaloniaUI public override void OnFrameworkInitializationCompleted() { + LoadStyles(); + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { var mainWindow = new MainWindow(); @@ -23,5 +33,14 @@ namespace LibationWinForms.AvaloniaUI base.OnFrameworkInitializationCompleted(); } + + private void LoadStyles() + { + ProcessQueueBookFailedBrush = AvaloniaUtils.GetBrushFromResources("ProcessQueueBookFailedBrush"); + ProcessQueueBookCompletedBrush = AvaloniaUtils.GetBrushFromResources("ProcessQueueBookCompletedBrush"); + ProcessQueueBookCancelledBrush = AvaloniaUtils.GetBrushFromResources("ProcessQueueBookCancelledBrush"); + ProcessQueueBookDefaultBrush = AvaloniaUtils.GetBrushFromResources("ProcessQueueBookDefaultBrush"); + SeriesEntryGridBackgroundBrush = AvaloniaUtils.GetBrushFromResources("SeriesEntryGridBackgroundBrush"); + } } } \ No newline at end of file diff --git a/Source/LibationWinForms/AvaloniaUI/Assets/LibationStyles.xaml b/Source/LibationWinForms/AvaloniaUI/Assets/LibationStyles.xaml new file mode 100644 index 00000000..e1e3f5ce --- /dev/null +++ b/Source/LibationWinForms/AvaloniaUI/Assets/LibationStyles.xaml @@ -0,0 +1,12 @@ + + + #FFE6FFE6 + + + + + + + + + \ No newline at end of file diff --git a/Source/LibationWinForms/AvaloniaUI/AvaloniaUtils.cs b/Source/LibationWinForms/AvaloniaUI/AvaloniaUtils.cs new file mode 100644 index 00000000..18e28559 --- /dev/null +++ b/Source/LibationWinForms/AvaloniaUI/AvaloniaUtils.cs @@ -0,0 +1,22 @@ +using Avalonia.Media; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LibationWinForms.AvaloniaUI +{ + internal static class AvaloniaUtils + { + + public static IBrush GetBrushFromResources(string name) + => GetBrushFromResources(name, Brushes.Transparent); + public static IBrush GetBrushFromResources(string name, IBrush defaultBrush) + { + if (App.Current.Styles.TryGetResource(name, out var value) && value is IBrush brush) + return brush; + return defaultBrush; + } + } +} diff --git a/Source/LibationWinForms/AvaloniaUI/ViewModels/ProcessBook2.cs b/Source/LibationWinForms/AvaloniaUI/ViewModels/ProcessBook2.cs index be11604d..9fdf74c2 100644 --- a/Source/LibationWinForms/AvaloniaUI/ViewModels/ProcessBook2.cs +++ b/Source/LibationWinForms/AvaloniaUI/ViewModels/ProcessBook2.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using ApplicationServices; +using Avalonia.Media; using Avalonia.Media.Imaging; using DataLayer; using Dinah.Core; @@ -63,12 +64,12 @@ namespace LibationWinForms.AvaloniaUI.ViewModels public bool IsDownloading => Status is ProcessBookStatus.Working; public bool Queued => Status is ProcessBookStatus.Queued; - public string BackgroundColor => Status switch + public IBrush BackgroundColor => Status switch { - ProcessBookStatus.Cancelled => "Khaki", - ProcessBookStatus.Completed => "PaleGreen", - ProcessBookStatus.Failed => "LightCoral", - _ => "White", + ProcessBookStatus.Cancelled => App.ProcessQueueBookCancelledBrush, + ProcessBookStatus.Completed => App.ProcessQueueBookCompletedBrush, + ProcessBookStatus.Failed => App.ProcessQueueBookFailedBrush, + _ => App.ProcessQueueBookDefaultBrush, }; public string StatusText => Result switch { @@ -83,6 +84,7 @@ namespace LibationWinForms.AvaloniaUI.ViewModels #endregion + private TimeSpan TimeRemaining { set { ETA = $"ETA: {value:mm\\:ss}"; } } private Processable CurrentProcessable => _currentProcessable ??= Processes.Dequeue().Invoke(); private Processable NextProcessable() => _currentProcessable = null; @@ -107,6 +109,7 @@ namespace LibationWinForms.AvaloniaUI.ViewModels // Mutable property. Set the field so PropertyChanged isn't fired. using var ms = new System.IO.MemoryStream(picture); _cover = new Bitmap(ms); + } private void PictureStorage_PictureCached(object sender, PictureCachedEventArgs e) diff --git a/Source/LibationWinForms/AvaloniaUI/Views/MainWindow/MainWindow.axaml b/Source/LibationWinForms/AvaloniaUI/Views/MainWindow/MainWindow.axaml index 633f312b..47c66173 100644 --- a/Source/LibationWinForms/AvaloniaUI/Views/MainWindow/MainWindow.axaml +++ b/Source/LibationWinForms/AvaloniaUI/Views/MainWindow/MainWindow.axaml @@ -9,13 +9,25 @@ mc:Ignorable="d" d:DesignWidth="2000" d:DesignHeight="700" x:Class="LibationWinForms.AvaloniaUI.Views.MainWindow" Title="MainWindow"> - - - + + + - - + + + + + + + + + + Toggle _Me0 @@ -30,16 +42,34 @@ - + + + + + - + - + + + + + + + + + Toggle _Me0 @@ -49,16 +79,28 @@ + + + + - + - - - + + + + + + + - + @@ -68,41 +110,56 @@ - - @@ -47,9 +48,10 @@ - - + + + diff --git a/Source/LibationWinForms/AvaloniaUI/Views/ProcessQueueControl2.axaml b/Source/LibationWinForms/AvaloniaUI/Views/ProcessQueueControl2.axaml index 8bb8c708..c5d0be64 100644 --- a/Source/LibationWinForms/AvaloniaUI/Views/ProcessQueueControl2.axaml +++ b/Source/LibationWinForms/AvaloniaUI/Views/ProcessQueueControl2.axaml @@ -10,31 +10,30 @@ - + - + - - - - - + + + + Process Queue - + + Queue Log - + @@ -84,11 +84,11 @@ - + diff --git a/Source/LibationWinForms/AvaloniaUI/Views/ProductsDisplay2.axaml b/Source/LibationWinForms/AvaloniaUI/Views/ProductsDisplay2.axaml index 55a4323f..50361033 100644 --- a/Source/LibationWinForms/AvaloniaUI/Views/ProductsDisplay2.axaml +++ b/Source/LibationWinForms/AvaloniaUI/Views/ProductsDisplay2.axaml @@ -11,7 +11,7 @@ - + diff --git a/Source/LibationWinForms/AvaloniaUI/Views/ProductsDisplay2.axaml.cs b/Source/LibationWinForms/AvaloniaUI/Views/ProductsDisplay2.axaml.cs index a4c123eb..5c40f5b1 100644 --- a/Source/LibationWinForms/AvaloniaUI/Views/ProductsDisplay2.axaml.cs +++ b/Source/LibationWinForms/AvaloniaUI/Views/ProductsDisplay2.axaml.cs @@ -38,6 +38,7 @@ namespace LibationWinForms.AvaloniaUI.Views .Select(lbe => lbe.LibraryBook) .ToList(); + DataGridColumn removeGVColumn; DataGridColumn liberateGVColumn; DataGridColumn coverGVColumn; @@ -53,12 +54,28 @@ namespace LibationWinForms.AvaloniaUI.Views DataGridColumn myRatingGVColumn; DataGridColumn miscGVColumn; DataGridColumn tagAndDetailsGVColumn; + + #region Init + public ProductsDisplay2() { InitializeComponent(); + + + if (Design.IsDesignMode) + { + using var context = DbContexts.GetContext(); + var book = context.GetLibraryBook_Flat_NoTracking("B017V4IM1G"); + productsGrid.DataContext = _viewModel = new ProductsDisplayViewModel(new List { book }); + return; + } + } + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); productsGrid = this.FindControl(nameof(productsGrid)); - productsGrid.Sorting += Dg1_Sorting; + productsGrid.Sorting += ProductsGrid_Sorting; productsGrid.CanUserSortColumns = true; productsGrid.LoadingRow += ProductsGrid_LoadingRow; @@ -78,6 +95,42 @@ namespace LibationWinForms.AvaloniaUI.Views miscGVColumn = productsGrid.Columns[13]; tagAndDetailsGVColumn = productsGrid.Columns[14]; + RegisterCustomColumnComparers(); + } + + #endregion + + #region Apply Background Brush Style to Series Books Rows + + private static object tagObj = new(); + private void ProductsGrid_LoadingRow(object sender, DataGridRowEventArgs e) + { + if (e.Row.Tag == tagObj) + return; + e.Row.Tag = tagObj; + + static IBrush GetRowColor(DataGridRow row) + => row.DataContext is GridEntry2 gEntry + && gEntry is LibraryBookEntry2 lbEntry + && lbEntry.Parent is not null + ? App.SeriesEntryGridBackgroundBrush + : null; + + e.Row.Background = GetRowColor(e.Row); + e.Row.DataContextChanged += (sender, e) => + { + var row = sender as DataGridRow; + row.Background = GetRowColor(row); + }; + } + + #endregion + + #region Sorting + + private void RegisterCustomColumnComparers() + { + removeGVColumn.CustomSortComparer = new RowComparer(removeGVColumn); liberateGVColumn.CustomSortComparer = new RowComparer(liberateGVColumn); titleGVColumn.CustomSortComparer = new RowComparer(titleGVColumn); @@ -92,50 +145,27 @@ namespace LibationWinForms.AvaloniaUI.Views myRatingGVColumn.CustomSortComparer = new RowComparer(myRatingGVColumn); miscGVColumn.CustomSortComparer = new RowComparer(miscGVColumn); tagAndDetailsGVColumn.CustomSortComparer = new RowComparer(tagAndDetailsGVColumn); - - removeGVColumn.PropertyChanged += RemoveGVColumn_PropertyChanged; - - if (Design.IsDesignMode) - { - using var context = DbContexts.GetContext(); - var book = context.GetLibraryBook_Flat_NoTracking("B017V4IM1G"); - productsGrid.DataContext = _viewModel = new ProductsDisplayViewModel(new List { book }); - return; - } } - private void RemoveGVColumn_PropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e) + private void ReSort() { - + if (CurrentSortColumn is null) + bindingList.InternalList.Sort((i1, i2) => i2.DateAdded.CompareTo(i1.DateAdded)); + else + CurrentSortColumn.Sort(((RowComparer)CurrentSortColumn.CustomSortComparer).SortDirection ?? ListSortDirection.Ascending); } - private static object tagObj = new(); - private static readonly IBrush SeriesBgColor = Brush.Parse("#ffe6ffe6"); - private void ProductsGrid_LoadingRow(object sender, DataGridRowEventArgs e) + private DataGridColumn CurrentSortColumn; + + private void ProductsGrid_Sorting(object sender, DataGridColumnEventArgs e) { - if (e.Row.Tag == tagObj) - return; - e.Row.Tag = tagObj; - - static IBrush GetRowColor(DataGridRow row) - => row.DataContext is GridEntry2 gEntry - && gEntry is LibraryBookEntry2 lbEntry - && lbEntry.Parent is not null - ? SeriesBgColor - : null; - - e.Row.Background = GetRowColor(e.Row); - e.Row.DataContextChanged += (sender, e) => - { - var row = sender as DataGridRow; - row.Background = GetRowColor(row); - }; - } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); + var comparer = e.Column.CustomSortComparer as RowComparer; + //Force the comparer to get the current sort order. We can't + //retrieve it from inside this event handler because Avalonia + //doesn't set the property until after this event. + comparer.SortDirection = null; + CurrentSortColumn = e.Column; } private class RowComparer : IComparer @@ -167,7 +197,7 @@ namespace LibationWinForms.AvaloniaUI.Views var geA = (GridEntry2)x; var geB = (GridEntry2)y; - SortDirection ??= GetSortOrder(Column); + SortDirection ??= GetSortOrder(); SeriesEntrys2 parentA = null; SeriesEntrys2 parentB = null; @@ -209,8 +239,8 @@ namespace LibationWinForms.AvaloniaUI.Views return Compare(parentA, parentB); } - private static ListSortDirection? GetSortOrder(DataGridColumn column) - => CurrentSortingStatePi.GetValue(HeaderCellPi.GetValue(column)) as ListSortDirection?; + private ListSortDirection? GetSortOrder() + => CurrentSortingStatePi.GetValue(HeaderCellPi.GetValue(Column)) as ListSortDirection?; private int Compare(GridEntry2 x, GridEntry2 y) { @@ -221,17 +251,7 @@ namespace LibationWinForms.AvaloniaUI.Views } } - DataGridColumn CurrentSortColumn; - - private void Dg1_Sorting(object sender, DataGridColumnEventArgs e) - { - var comparer = e.Column.CustomSortComparer as RowComparer; - //Force the comparer to get the current sort order. We can't - //retrieve it from inside this event handler because Avalonia - //doesn't set the property until after this event. - comparer.SortDirection = null; - CurrentSortColumn = e.Column; - } + #endregion #region Button controls @@ -244,7 +264,10 @@ namespace LibationWinForms.AvaloniaUI.Views if (sEntry.Liberate.Expanded) bindingList.CollapseItem(sEntry); else + { bindingList.ExpandItem(sEntry); + ReSort(); + } VisibleCountChanged?.Invoke(this, bindingList.BookEntries().Count()); } @@ -565,14 +588,9 @@ namespace LibationWinForms.AvaloniaUI.Views VisibleCountChanged?.Invoke(this, bindingList.BookEntries().Count()); //Re-sort after filtering - if (CurrentSortColumn is null) - bindingList.InternalList.Sort((i1, i2) => i2.DateAdded.CompareTo(i1.DateAdded)); - else - { - CurrentSortColumn.Sort(((RowComparer)CurrentSortColumn.CustomSortComparer).SortDirection ?? ListSortDirection.Ascending); - } - + bindingList.ResetCollection(); + ReSort(); } #endregion diff --git a/Source/LibationWinForms/LibationWinForms.csproj b/Source/LibationWinForms/LibationWinForms.csproj index a2854712..d08592d7 100644 --- a/Source/LibationWinForms/LibationWinForms.csproj +++ b/Source/LibationWinForms/LibationWinForms.csproj @@ -48,6 +48,7 @@ + @@ -79,6 +80,12 @@ SettingsDialog.cs + + + + + MSBuild:Compile +