Address comments

This commit is contained in:
Michael Bucari-Tovo 2022-05-24 11:15:41 -06:00
parent 43d6ea82cd
commit e26deb9092
6 changed files with 77 additions and 54 deletions

View File

@ -27,6 +27,7 @@ namespace LibationWinForms.GridView
}
public new bool InvokeRequired => base.InvokeRequired;
public abstract DateTime DateAdded { get; }
public abstract float SeriesIndex { get; }
public abstract string ProductRating { get; protected set; }
public abstract string PurchaseDate { get; protected set; }
public abstract string MyRating { get; protected set; }
@ -40,10 +41,21 @@ namespace LibationWinForms.GridView
public abstract string Description { get; protected set; }
public abstract string DisplayTags { get; }
public abstract LiberateButtonStatus Liberate { get; }
public abstract object GetMemberValue(string memberName);
#endregion
#region Sorting
public GridEntry() => _memberValues = CreateMemberValueDictionary();
private Dictionary<string, Func<object>> _memberValues { get; set; }
protected abstract Dictionary<string, Func<object>> CreateMemberValueDictionary();
// These methods are implementation of Dinah.Core.DataBinding.IMemberComparable
// Used by GridEntryBindingList for all sorting
public virtual object GetMemberValue(string memberName) => _memberValues[memberName]();
public IComparer GetMemberComparer(Type memberType) => _memberTypeComparers[memberType];
#endregion
protected void LoadCover()
{
// Get cover art. If it's default, subscribe to PictureCached

View File

@ -1,5 +1,6 @@
using ApplicationServices;
using Dinah.Core.DataBinding;
using LibationSearchEngine;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -21,15 +22,13 @@ namespace LibationWinForms.GridView
*/
internal class GridEntryBindingList : BindingList<GridEntry>, IBindingListView
{
private bool isSorted;
private ListSortDirection listSortDirection;
private PropertyDescriptor propertyDescriptor;
public GridEntryBindingList() : base(new List<GridEntry>()) { }
public GridEntryBindingList(IEnumerable<GridEntry> enumeration) : base(new List<GridEntry>(enumeration)) { }
/// <returns>All items in the list, including those filtered out.</returns>
public List<GridEntry> AllItems() => Items.Concat(FilterRemoved).ToList();
public bool SupportsFiltering => true;
public string Filter { get => FilterString; set => ApplyFilter(value); }
protected MemberComparer<GridEntry> Comparer { get; } = new();
protected override bool SupportsSortingCore => true;
@ -37,15 +36,14 @@ namespace LibationWinForms.GridView
protected override bool IsSortedCore => isSorted;
protected override PropertyDescriptor SortPropertyCore => propertyDescriptor;
protected override ListSortDirection SortDirectionCore => listSortDirection;
public bool SupportsFiltering => true;
public string Filter { get => FilterString; set => ApplyFilter(value); }
/// <summary>
/// Items that were removed from the base list due to filtering
/// </summary>
/// <summary> Items that were removed from the base list due to filtering </summary>
private readonly List<GridEntry> FilterRemoved = new();
private string FilterString;
private LibationSearchEngine.SearchResultSet SearchResults;
private SearchResultSet SearchResults;
private bool isSorted;
private ListSortDirection listSortDirection;
private PropertyDescriptor propertyDescriptor;
#region Unused - Advanced Filtering
@ -118,11 +116,9 @@ namespace LibationWinForms.GridView
if (SearchResults is null || SearchResults.Docs.Any(d => d.ProductId == episode.AudibleProductId))
{
FilterRemoved.Remove(episode);
Items.Insert(++sindex, episode);
InsertItem(++sindex, episode);
}
}
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
sEntry.Liberate.Expanded = true;
}
@ -137,7 +133,7 @@ namespace LibationWinForms.GridView
if (item is SeriesEntry || (item is LibraryBookEntry lbe && (lbe.Parent is null || lbe.Parent.Liberate.Expanded)))
{
FilterRemoved.Remove(item);
base.InsertItem(visibleCount++, item);
InsertItem(visibleCount++, item);
}
}
@ -175,35 +171,51 @@ namespace LibationWinForms.GridView
{
var itemsList = (List<GridEntry>)Items;
var sortedItems = Items.OrderBy(ge => ge, Comparer).ToList();
var children = itemsList.LibraryBooks().Where(i => i.Parent is not null).ToList();
var children = sortedItems.LibraryBooks().Where(i => i.Parent is not null).ToList();
var sortedItems = itemsList.Except(children).OrderBy(ge => ge, Comparer).ToList();
itemsList.Clear();
//Only add parentless items at this stage. After these items are added in the
//correct sorting order, go back and add the children beneath their parents.
itemsList.AddRange(sortedItems.Except(children));
itemsList.AddRange(sortedItems);
foreach (var parent in children.Select(c => c.Parent).Distinct())
{
var pIndex = itemsList.IndexOf(parent);
foreach (var c in children.Where(c => c.Parent == parent))
//children should always be sorted by series index.
foreach (var c in children.Where(c => c.Parent == parent).OrderBy(c => c.SeriesIndex))
itemsList.Insert(++pIndex, c);
}
}
protected override void OnListChanged(ListChangedEventArgs e)
{
if (isSorted && e.ListChangedType == ListChangedType.ItemChanged && e.PropertyDescriptor == SortPropertyCore)
if (e.ListChangedType == ListChangedType.ItemChanged)
{
if (Items[e.NewIndex] is LibraryBookEntry lbItem)
{
SearchResults = SearchEngineCommands.Search(FilterString);
if (!SearchResults.Docs.Any(d => d.ProductId == lbItem.AudibleProductId))
{
FilterRemoved.Add(lbItem);
base.Remove(lbItem);
return;
}
}
if (isSorted && e.PropertyDescriptor == SortPropertyCore)
{
var item = Items[e.NewIndex];
Sort();
var newIndex = Items.IndexOf(item);
base.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, newIndex, e.NewIndex));
return;
}
}
else
base.OnListChanged(e);
}

View File

@ -7,8 +7,8 @@ namespace LibationWinForms.GridView
{
public LiberatedStatus BookStatus { get; set; }
public LiberatedStatus? PdfStatus { get; set; }
public bool IsSeries { get; init; }
public bool Expanded { get; set; }
public bool IsSeries { get; init; }
/// <summary>
/// Defines the Liberate column's sorting behavior

View File

@ -1,4 +1,5 @@
using DataLayer;
using Dinah.Core.Windows.Forms;
using System;
using System.Drawing;
using System.Windows.Forms;
@ -15,12 +16,18 @@ namespace LibationWinForms.GridView
internal class LiberateDataGridViewImageButtonCell : DataGridViewImageButtonCell
{
private static readonly Color SERIES_BG_COLOR = Color.LightSkyBlue;
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts);
if (value is LiberateButtonStatus status)
{
if (rowIndex >= 0 && DataGridView.GetBoundItem<GridEntry>(rowIndex) is LibraryBookEntry lbEntry && lbEntry.Parent is not null)
{
DataGridView.Rows[rowIndex].DefaultCellStyle.BackColor = SERIES_BG_COLOR;
}
if (status.IsSeries)
{
var imageName = status.Expanded ? "minus" : "plus";

View File

@ -32,6 +32,7 @@ namespace LibationWinForms.GridView
private LiberatedStatus? _pdfStatus;
public override DateTime DateAdded => LibraryBook.DateAdded;
public override float SeriesIndex => Book.SeriesLink.FirstOrDefault()?.Index ?? 0;
public override string ProductRating { get; protected set; }
public override string PurchaseDate { get; protected set; }
public override string MyRating { get; protected set; }
@ -78,7 +79,6 @@ namespace LibationWinForms.GridView
private void setLibraryBook(LibraryBook libraryBook)
{
LibraryBook = libraryBook;
_memberValues = CreateMemberValueDictionary();
LoadCover();
@ -119,16 +119,19 @@ namespace LibationWinForms.GridView
{
case nameof(udi.Tags):
Book.UserDefinedItem.Tags = udi.Tags;
SearchEngineCommands.UpdateBookTags(Book);
NotifyPropertyChanged(nameof(DisplayTags));
break;
case nameof(udi.BookStatus):
Book.UserDefinedItem.BookStatus = udi.BookStatus;
_bookStatus = udi.BookStatus;
SearchEngineCommands.UpdateLiberatedStatus(Book);
NotifyPropertyChanged(nameof(Liberate));
break;
case nameof(udi.PdfStatus):
Book.UserDefinedItem.PdfStatus = udi.PdfStatus;
_pdfStatus = udi.PdfStatus;
SearchEngineCommands.UpdateLiberatedStatus(Book);
NotifyPropertyChanged(nameof(Liberate));
break;
}
@ -157,16 +160,9 @@ namespace LibationWinForms.GridView
#endregion
#region Data Sorting
// These methods are implementation of Dinah.Core.DataBinding.IMemberComparable
// Used by Dinah.Core.DataBinding.SortableBindingList<T> for all sorting
public override object GetMemberValue(string memberName) => _memberValues[memberName]();
private Dictionary<string, Func<object>> _memberValues { get; set; }
/// <summary>
/// Create getters for all member object values by name
/// </summary>
private Dictionary<string, Func<object>> CreateMemberValueDictionary() => new()
/// <summary>Create getters for all member object values by name </summary>
protected override Dictionary<string, Func<object>> CreateMemberValueDictionary() => new()
{
{ nameof(Title), () => Book.TitleSortable() },
{ nameof(Series), () => Book.SeriesSortable() },

View File

@ -10,6 +10,7 @@ namespace LibationWinForms.GridView
{
public List<LibraryBookEntry> Children { get; init; }
public override DateTime DateAdded => Children.Max(c => c.DateAdded);
public override float SeriesIndex { get; }
public override string ProductRating
{
get
@ -47,20 +48,23 @@ namespace LibationWinForms.GridView
public override string Description { get; protected set; } = string.Empty;
public override string DisplayTags { get; } = string.Empty;
public override LiberateButtonStatus Liberate => _liberate;
public override LiberateButtonStatus Liberate { get; }
protected override Book Book => SeriesBook.Book;
private SeriesBook SeriesBook { get; set; }
private LiberateButtonStatus _liberate = new LiberateButtonStatus { IsSeries = true };
public SeriesEntry(SeriesBook seriesBook, IEnumerable<LibraryBook> children)
private SeriesEntry(SeriesBook seriesBook)
{
Children = children.Select(c => new LibraryBookEntry(c) { Parent = this }).ToList();
Liberate = new LiberateButtonStatus { IsSeries = true };
SeriesIndex = seriesBook.Index;
}
public SeriesEntry(SeriesBook seriesBook, IEnumerable<LibraryBook> children) : this(seriesBook)
{
Children = children.Select(c => new LibraryBookEntry(c) { Parent = this }).OrderBy(c => c.SeriesIndex).ToList();
SetSeriesBook(seriesBook);
}
public SeriesEntry(SeriesBook seriesBook, LibraryBook child)
public SeriesEntry(SeriesBook seriesBook, LibraryBook child) : this(seriesBook)
{
Children = new() { new LibraryBookEntry(child) { Parent = this } };
SetSeriesBook(seriesBook);
@ -69,7 +73,6 @@ namespace LibationWinForms.GridView
private void SetSeriesBook(SeriesBook seriesBook)
{
SeriesBook = seriesBook;
_memberValues = CreateMemberValueDictionary();
LoadCover();
// Immutable properties
@ -83,16 +86,9 @@ namespace LibationWinForms.GridView
}
}
// These methods are implementation of Dinah.Core.DataBinding.IMemberComparable
// Used by Dinah.Core.DataBinding.SortableBindingList<T> for all sorting
public override object GetMemberValue(string memberName) => _memberValues[memberName]();
private Dictionary<string, Func<object>> _memberValues { get; set; }
/// <summary>
/// Create getters for all member object values by name
/// </summary>
private Dictionary<string, Func<object>> CreateMemberValueDictionary() => new()
/// <summary>Create getters for all member object values by name</summary>
protected override Dictionary<string, Func<object>> CreateMemberValueDictionary() => new()
{
{ nameof(Title), () => Book.SeriesSortable() },
{ nameof(Series), () => Book.SeriesSortable() },