Address comments
This commit is contained in:
parent
43d6ea82cd
commit
e26deb9092
@ -27,6 +27,7 @@ namespace LibationWinForms.GridView
|
|||||||
}
|
}
|
||||||
public new bool InvokeRequired => base.InvokeRequired;
|
public new bool InvokeRequired => base.InvokeRequired;
|
||||||
public abstract DateTime DateAdded { get; }
|
public abstract DateTime DateAdded { get; }
|
||||||
|
public abstract float SeriesIndex { get; }
|
||||||
public abstract string ProductRating { get; protected set; }
|
public abstract string ProductRating { get; protected set; }
|
||||||
public abstract string PurchaseDate { get; protected set; }
|
public abstract string PurchaseDate { get; protected set; }
|
||||||
public abstract string MyRating { 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 Description { get; protected set; }
|
||||||
public abstract string DisplayTags { get; }
|
public abstract string DisplayTags { get; }
|
||||||
public abstract LiberateButtonStatus Liberate { get; }
|
public abstract LiberateButtonStatus Liberate { get; }
|
||||||
public abstract object GetMemberValue(string memberName);
|
|
||||||
#endregion
|
#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];
|
public IComparer GetMemberComparer(Type memberType) => _memberTypeComparers[memberType];
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
protected void LoadCover()
|
protected void LoadCover()
|
||||||
{
|
{
|
||||||
// Get cover art. If it's default, subscribe to PictureCached
|
// Get cover art. If it's default, subscribe to PictureCached
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using ApplicationServices;
|
using ApplicationServices;
|
||||||
using Dinah.Core.DataBinding;
|
using Dinah.Core.DataBinding;
|
||||||
|
using LibationSearchEngine;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
@ -21,15 +22,13 @@ namespace LibationWinForms.GridView
|
|||||||
*/
|
*/
|
||||||
internal class GridEntryBindingList : BindingList<GridEntry>, IBindingListView
|
internal class GridEntryBindingList : BindingList<GridEntry>, IBindingListView
|
||||||
{
|
{
|
||||||
private bool isSorted;
|
|
||||||
private ListSortDirection listSortDirection;
|
|
||||||
private PropertyDescriptor propertyDescriptor;
|
|
||||||
|
|
||||||
public GridEntryBindingList() : base(new List<GridEntry>()) { }
|
public GridEntryBindingList() : base(new List<GridEntry>()) { }
|
||||||
public GridEntryBindingList(IEnumerable<GridEntry> enumeration) : base(new List<GridEntry>(enumeration)) { }
|
public GridEntryBindingList(IEnumerable<GridEntry> enumeration) : base(new List<GridEntry>(enumeration)) { }
|
||||||
|
|
||||||
/// <returns>All items in the list, including those filtered out.</returns>
|
/// <returns>All items in the list, including those filtered out.</returns>
|
||||||
public List<GridEntry> AllItems() => Items.Concat(FilterRemoved).ToList();
|
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 MemberComparer<GridEntry> Comparer { get; } = new();
|
||||||
protected override bool SupportsSortingCore => true;
|
protected override bool SupportsSortingCore => true;
|
||||||
@ -37,15 +36,14 @@ namespace LibationWinForms.GridView
|
|||||||
protected override bool IsSortedCore => isSorted;
|
protected override bool IsSortedCore => isSorted;
|
||||||
protected override PropertyDescriptor SortPropertyCore => propertyDescriptor;
|
protected override PropertyDescriptor SortPropertyCore => propertyDescriptor;
|
||||||
protected override ListSortDirection SortDirectionCore => listSortDirection;
|
protected override ListSortDirection SortDirectionCore => listSortDirection;
|
||||||
public bool SupportsFiltering => true;
|
|
||||||
public string Filter { get => FilterString; set => ApplyFilter(value); }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Items that were removed from the base list due to filtering </summary>
|
||||||
/// Items that were removed from the base list due to filtering
|
|
||||||
/// </summary>
|
|
||||||
private readonly List<GridEntry> FilterRemoved = new();
|
private readonly List<GridEntry> FilterRemoved = new();
|
||||||
private string FilterString;
|
private string FilterString;
|
||||||
private LibationSearchEngine.SearchResultSet SearchResults;
|
private SearchResultSet SearchResults;
|
||||||
|
private bool isSorted;
|
||||||
|
private ListSortDirection listSortDirection;
|
||||||
|
private PropertyDescriptor propertyDescriptor;
|
||||||
|
|
||||||
|
|
||||||
#region Unused - Advanced Filtering
|
#region Unused - Advanced Filtering
|
||||||
@ -118,11 +116,9 @@ namespace LibationWinForms.GridView
|
|||||||
if (SearchResults is null || SearchResults.Docs.Any(d => d.ProductId == episode.AudibleProductId))
|
if (SearchResults is null || SearchResults.Docs.Any(d => d.ProductId == episode.AudibleProductId))
|
||||||
{
|
{
|
||||||
FilterRemoved.Remove(episode);
|
FilterRemoved.Remove(episode);
|
||||||
Items.Insert(++sindex, episode);
|
InsertItem(++sindex, episode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
|
|
||||||
sEntry.Liberate.Expanded = true;
|
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)))
|
if (item is SeriesEntry || (item is LibraryBookEntry lbe && (lbe.Parent is null || lbe.Parent.Liberate.Expanded)))
|
||||||
{
|
{
|
||||||
FilterRemoved.Remove(item);
|
FilterRemoved.Remove(item);
|
||||||
base.InsertItem(visibleCount++, item);
|
InsertItem(visibleCount++, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,35 +171,51 @@ namespace LibationWinForms.GridView
|
|||||||
{
|
{
|
||||||
var itemsList = (List<GridEntry>)Items;
|
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();
|
itemsList.Clear();
|
||||||
|
|
||||||
//Only add parentless items at this stage. After these items are added in the
|
//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.
|
//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())
|
foreach (var parent in children.Select(c => c.Parent).Distinct())
|
||||||
{
|
{
|
||||||
var pIndex = itemsList.IndexOf(parent);
|
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);
|
itemsList.Insert(++pIndex, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnListChanged(ListChangedEventArgs e)
|
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];
|
var item = Items[e.NewIndex];
|
||||||
Sort();
|
Sort();
|
||||||
var newIndex = Items.IndexOf(item);
|
var newIndex = Items.IndexOf(item);
|
||||||
|
|
||||||
base.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, newIndex, e.NewIndex));
|
base.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, newIndex, e.NewIndex));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
base.OnListChanged(e);
|
base.OnListChanged(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,8 @@ namespace LibationWinForms.GridView
|
|||||||
{
|
{
|
||||||
public LiberatedStatus BookStatus { get; set; }
|
public LiberatedStatus BookStatus { get; set; }
|
||||||
public LiberatedStatus? PdfStatus { get; set; }
|
public LiberatedStatus? PdfStatus { get; set; }
|
||||||
public bool IsSeries { get; init; }
|
|
||||||
public bool Expanded { get; set; }
|
public bool Expanded { get; set; }
|
||||||
|
public bool IsSeries { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the Liberate column's sorting behavior
|
/// Defines the Liberate column's sorting behavior
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using DataLayer;
|
using DataLayer;
|
||||||
|
using Dinah.Core.Windows.Forms;
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
@ -15,12 +16,18 @@ namespace LibationWinForms.GridView
|
|||||||
|
|
||||||
internal class LiberateDataGridViewImageButtonCell : DataGridViewImageButtonCell
|
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)
|
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);
|
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts);
|
||||||
|
|
||||||
if (value is LiberateButtonStatus status)
|
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)
|
if (status.IsSeries)
|
||||||
{
|
{
|
||||||
var imageName = status.Expanded ? "minus" : "plus";
|
var imageName = status.Expanded ? "minus" : "plus";
|
||||||
|
|||||||
@ -32,6 +32,7 @@ namespace LibationWinForms.GridView
|
|||||||
private LiberatedStatus? _pdfStatus;
|
private LiberatedStatus? _pdfStatus;
|
||||||
|
|
||||||
public override DateTime DateAdded => LibraryBook.DateAdded;
|
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 ProductRating { get; protected set; }
|
||||||
public override string PurchaseDate { get; protected set; }
|
public override string PurchaseDate { get; protected set; }
|
||||||
public override string MyRating { get; protected set; }
|
public override string MyRating { get; protected set; }
|
||||||
@ -78,7 +79,6 @@ namespace LibationWinForms.GridView
|
|||||||
private void setLibraryBook(LibraryBook libraryBook)
|
private void setLibraryBook(LibraryBook libraryBook)
|
||||||
{
|
{
|
||||||
LibraryBook = libraryBook;
|
LibraryBook = libraryBook;
|
||||||
_memberValues = CreateMemberValueDictionary();
|
|
||||||
|
|
||||||
LoadCover();
|
LoadCover();
|
||||||
|
|
||||||
@ -119,16 +119,19 @@ namespace LibationWinForms.GridView
|
|||||||
{
|
{
|
||||||
case nameof(udi.Tags):
|
case nameof(udi.Tags):
|
||||||
Book.UserDefinedItem.Tags = udi.Tags;
|
Book.UserDefinedItem.Tags = udi.Tags;
|
||||||
|
SearchEngineCommands.UpdateBookTags(Book);
|
||||||
NotifyPropertyChanged(nameof(DisplayTags));
|
NotifyPropertyChanged(nameof(DisplayTags));
|
||||||
break;
|
break;
|
||||||
case nameof(udi.BookStatus):
|
case nameof(udi.BookStatus):
|
||||||
Book.UserDefinedItem.BookStatus = udi.BookStatus;
|
Book.UserDefinedItem.BookStatus = udi.BookStatus;
|
||||||
_bookStatus = udi.BookStatus;
|
_bookStatus = udi.BookStatus;
|
||||||
|
SearchEngineCommands.UpdateLiberatedStatus(Book);
|
||||||
NotifyPropertyChanged(nameof(Liberate));
|
NotifyPropertyChanged(nameof(Liberate));
|
||||||
break;
|
break;
|
||||||
case nameof(udi.PdfStatus):
|
case nameof(udi.PdfStatus):
|
||||||
Book.UserDefinedItem.PdfStatus = udi.PdfStatus;
|
Book.UserDefinedItem.PdfStatus = udi.PdfStatus;
|
||||||
_pdfStatus = udi.PdfStatus;
|
_pdfStatus = udi.PdfStatus;
|
||||||
|
SearchEngineCommands.UpdateLiberatedStatus(Book);
|
||||||
NotifyPropertyChanged(nameof(Liberate));
|
NotifyPropertyChanged(nameof(Liberate));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -157,16 +160,9 @@ namespace LibationWinForms.GridView
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Data Sorting
|
#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>
|
||||||
|
protected override Dictionary<string, Func<object>> CreateMemberValueDictionary() => new()
|
||||||
/// <summary>
|
|
||||||
/// Create getters for all member object values by name
|
|
||||||
/// </summary>
|
|
||||||
private Dictionary<string, Func<object>> CreateMemberValueDictionary() => new()
|
|
||||||
{
|
{
|
||||||
{ nameof(Title), () => Book.TitleSortable() },
|
{ nameof(Title), () => Book.TitleSortable() },
|
||||||
{ nameof(Series), () => Book.SeriesSortable() },
|
{ nameof(Series), () => Book.SeriesSortable() },
|
||||||
|
|||||||
@ -10,6 +10,7 @@ namespace LibationWinForms.GridView
|
|||||||
{
|
{
|
||||||
public List<LibraryBookEntry> Children { get; init; }
|
public List<LibraryBookEntry> Children { get; init; }
|
||||||
public override DateTime DateAdded => Children.Max(c => c.DateAdded);
|
public override DateTime DateAdded => Children.Max(c => c.DateAdded);
|
||||||
|
public override float SeriesIndex { get; }
|
||||||
public override string ProductRating
|
public override string ProductRating
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -47,20 +48,23 @@ namespace LibationWinForms.GridView
|
|||||||
public override string Description { get; protected set; } = string.Empty;
|
public override string Description { get; protected set; } = string.Empty;
|
||||||
public override string DisplayTags { get; } = 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;
|
protected override Book Book => SeriesBook.Book;
|
||||||
|
|
||||||
private SeriesBook SeriesBook { get; set; }
|
private SeriesBook SeriesBook { get; set; }
|
||||||
|
|
||||||
private LiberateButtonStatus _liberate = new LiberateButtonStatus { IsSeries = true };
|
private SeriesEntry(SeriesBook seriesBook)
|
||||||
|
|
||||||
public SeriesEntry(SeriesBook seriesBook, IEnumerable<LibraryBook> children)
|
|
||||||
{
|
{
|
||||||
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);
|
SetSeriesBook(seriesBook);
|
||||||
}
|
}
|
||||||
public SeriesEntry(SeriesBook seriesBook, LibraryBook child)
|
public SeriesEntry(SeriesBook seriesBook, LibraryBook child) : this(seriesBook)
|
||||||
{
|
{
|
||||||
Children = new() { new LibraryBookEntry(child) { Parent = this } };
|
Children = new() { new LibraryBookEntry(child) { Parent = this } };
|
||||||
SetSeriesBook(seriesBook);
|
SetSeriesBook(seriesBook);
|
||||||
@ -69,7 +73,6 @@ namespace LibationWinForms.GridView
|
|||||||
private void SetSeriesBook(SeriesBook seriesBook)
|
private void SetSeriesBook(SeriesBook seriesBook)
|
||||||
{
|
{
|
||||||
SeriesBook = seriesBook;
|
SeriesBook = seriesBook;
|
||||||
_memberValues = CreateMemberValueDictionary();
|
|
||||||
LoadCover();
|
LoadCover();
|
||||||
|
|
||||||
// Immutable properties
|
// 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>
|
||||||
|
protected override Dictionary<string, Func<object>> CreateMemberValueDictionary() => new()
|
||||||
/// <summary>
|
|
||||||
/// Create getters for all member object values by name
|
|
||||||
/// </summary>
|
|
||||||
private Dictionary<string, Func<object>> CreateMemberValueDictionary() => new()
|
|
||||||
{
|
{
|
||||||
{ nameof(Title), () => Book.SeriesSortable() },
|
{ nameof(Title), () => Book.SeriesSortable() },
|
||||||
{ nameof(Series), () => Book.SeriesSortable() },
|
{ nameof(Series), () => Book.SeriesSortable() },
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user