diff --git a/LibationLauncher/LibationLauncher.csproj b/LibationLauncher/LibationLauncher.csproj
index c0d121d3..5af2cd25 100644
--- a/LibationLauncher/LibationLauncher.csproj
+++ b/LibationLauncher/LibationLauncher.csproj
@@ -13,7 +13,7 @@
win-x64
- 5.4.9.0
+ 5.4.9.79
diff --git a/LibationWinForms/DataGridViewImageButtonColumn.cs b/LibationWinForms/DataGridViewImageButtonColumn.cs
new file mode 100644
index 00000000..31d41780
--- /dev/null
+++ b/LibationWinForms/DataGridViewImageButtonColumn.cs
@@ -0,0 +1,50 @@
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace LibationWinForms
+{
+ public abstract class DataGridViewImageButtonColumn : DataGridViewButtonColumn
+ {
+ private DataGridViewImageButtonCell _cellTemplate;
+ public override DataGridViewCell CellTemplate
+ {
+ get => GetCellTemplate();
+ set
+ {
+ if (value is DataGridViewImageButtonCell cellTemplate)
+ _cellTemplate = cellTemplate;
+ }
+ }
+
+ protected abstract DataGridViewImageButtonCell NewCell();
+
+ private DataGridViewImageButtonCell GetCellTemplate()
+ {
+ if (_cellTemplate is null)
+ return NewCell();
+ else
+ return _cellTemplate;
+ }
+
+ public override object Clone()
+ {
+ var clone = (DataGridViewImageButtonColumn)base.Clone();
+ clone._cellTemplate = _cellTemplate;
+
+ return clone;
+ }
+ }
+
+ public class DataGridViewImageButtonCell : DataGridViewButtonCell
+ {
+ protected void DrawImage(Graphics graphics, Bitmap image, Rectangle cellBounds)
+ {
+ var w = image.Width;
+ var h = image.Height;
+ var x = cellBounds.Left + (cellBounds.Width - w) / 2;
+ var y = cellBounds.Top + (cellBounds.Height - h) / 2;
+
+ graphics.DrawImage(image, new Rectangle(x, y, w, h));
+ }
+ }
+}
diff --git a/LibationWinForms/Dialogs/RemoveBooksDialog.cs b/LibationWinForms/Dialogs/RemoveBooksDialog.cs
index 273176cb..7bfafb8c 100644
--- a/LibationWinForms/Dialogs/RemoveBooksDialog.cs
+++ b/LibationWinForms/Dialogs/RemoveBooksDialog.cs
@@ -40,7 +40,7 @@ namespace LibationWinForms.Dialogs
var orderedGridEntries = _libraryBooks
.Select(lb => new RemovableGridEntry(new GridEntry(lb)))
- .OrderByDescending(ge => ge.GridEntry.Purchase_Date)
+ .OrderByDescending(ge => ge.GridEntry.PurchaseDate)
.ToList();
_removableGridEntries = orderedGridEntries.ToSortableBindingList();
@@ -173,10 +173,10 @@ namespace LibationWinForms.Dialogs
NotifyPropertyChanged();
}
}
- public string Title => GetDisplayValue(nameof(GridEntry.Title), GridEntry.Title);
- public string Authors => GetDisplayValue(nameof(GridEntry.Authors), GridEntry.Authors);
- public string Misc => GetDisplayValue(nameof(GridEntry.Misc), GridEntry.Misc);
- public string DatePurchased => GetDisplayValue(nameof(GridEntry.Purchase_Date), GridEntry.Purchase_Date);
+ public string Title => GridEntry.Title;
+ public string Authors => GridEntry.Authors;
+ public string Misc => GridEntry.Misc;
+ public string DatePurchased => GridEntry.PurchaseDate;
private bool _remove = false;
private Image _cover;
@@ -185,7 +185,7 @@ namespace LibationWinForms.Dialogs
{
GridEntry = gridEntry;
- var picDef = new FileManager.PictureDefinition(GridEntry.GetBook().PictureId, FileManager.PictureSize._80x80);
+ var picDef = new FileManager.PictureDefinition(GridEntry.LibraryBook.Book.PictureId, FileManager.PictureSize._80x80);
(bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(picDef);
if (isDefault)
@@ -196,19 +196,12 @@ namespace LibationWinForms.Dialogs
private void PictureStorage_PictureCached(object sender, string pictureId)
{
- if (pictureId == GridEntry.GetBook().PictureId)
+ if (pictureId == GridEntry.LibraryBook.Book.PictureId)
{
Cover = WindowsDesktopUtilities.WinAudibleImageServer.GetImage(pictureId, FileManager.PictureSize._80x80);
FileManager.PictureStorage.PictureCached -= PictureStorage_PictureCached;
}
}
-
- private string GetDisplayValue(string propertyName, string defaultValue)
- {
- if (GridEntry.TryDisplayValue(propertyName, out string value))
- return value;
- return defaultValue;
- }
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
diff --git a/LibationWinForms/EditTagsDataGridViewImageButtonColumn.cs b/LibationWinForms/EditTagsDataGridViewImageButtonColumn.cs
new file mode 100644
index 00000000..fdee638f
--- /dev/null
+++ b/LibationWinForms/EditTagsDataGridViewImageButtonColumn.cs
@@ -0,0 +1,26 @@
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace LibationWinForms
+{
+ public class EditTagsDataGridViewImageButtonColumn : DataGridViewImageButtonColumn
+ {
+ protected override DataGridViewImageButtonCell NewCell()
+ => new EditTagsDataGridViewImageButtonCell();
+ }
+
+ internal class EditTagsDataGridViewImageButtonCell : DataGridViewImageButtonCell
+ {
+ private static readonly Bitmap ButtonImage = Properties.Resources.edit_tags_25x25;
+ 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)
+ {
+ if (((string)value).Length == 0)
+ {
+ base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts);
+ DrawImage(graphics, ButtonImage, cellBounds);
+ }
+ else
+ base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
+ }
+ }
+}
diff --git a/LibationWinForms/GridEntry.cs b/LibationWinForms/GridEntry.cs
index 5f24c447..d20c6553 100644
--- a/LibationWinForms/GridEntry.cs
+++ b/LibationWinForms/GridEntry.cs
@@ -1,86 +1,159 @@
using System;
+using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
+using System.Runtime.CompilerServices;
using ApplicationServices;
using DataLayer;
+using Dinah.Core.Drawing;
namespace LibationWinForms
{
- internal class GridEntry
+ internal class GridEntry : INotifyPropertyChanged, IObjectMemberComparable
{
- private LibraryBook libraryBook { get; }
- private Book book => libraryBook.Book;
+ public const string LIBERATE_COLUMN_NAME = "Liberate";
+ public const string EDIT_TAGS_COLUMN_NAME = "DisplayTags";
- public Book GetBook() => book;
- public LibraryBook GetLibraryBook() => libraryBook;
-
- public GridEntry(LibraryBook libraryBook) => this.libraryBook = libraryBook;
-
- // hide from public fields from Data Source GUI with [Browsable(false)]
+ #region implementation properties
+ // hide from public fields from Data Source GUI with [Browsable(false)]
+ [Browsable(false)]
+ public string AudibleProductId => Book.AudibleProductId;
[Browsable(false)]
- public string AudibleProductId => book.AudibleProductId;
+ public string Tags => Book.UserDefinedItem.Tags;
[Browsable(false)]
- public string Tags => book.UserDefinedItem.Tags;
+ public IEnumerable TagsEnumerated => Book.UserDefinedItem.TagsEnumerated;
[Browsable(false)]
- public IEnumerable TagsEnumerated => book.UserDefinedItem.TagsEnumerated;
- [Browsable(false)]
- public string PictureId => book.PictureId;
- [Browsable(false)]
- public LiberatedState Liberated_Status => LibraryCommands.Liberated_Status(book);
- [Browsable(false)]
- public PdfState Pdf_Status => LibraryCommands.Pdf_Status(book);
+ public LibraryBook LibraryBook { get; }
- // displayValues is what gets displayed
- // the value that gets returned from the property is the cell's value
- // this allows for the value to be sorted one way and displayed another
- // eg:
- // orig title: The Computer
- // formatReplacement: The Computer
- // value for sorting: Computer
- private Dictionary displayValues { get; } = new Dictionary();
- public bool TryDisplayValue(string key, out string value) => displayValues.TryGetValue(key, out value);
+ #endregion
- public Image Cover =>
- WindowsDesktopUtilities.WinAudibleImageServer.GetImage(book.PictureId, FileManager.PictureSize._80x80);
+ public event PropertyChangedEventHandler PropertyChanged;
+ private Book Book => LibraryBook.Book;
+ private Image _cover;
- public string Title
+ public GridEntry(LibraryBook libraryBook)
{
- get
+ LibraryBook = libraryBook;
+
+ _compareValues = CreatePropertyValueDictionary();
+
+ //Get cover art. If it's default, subscribe to PictureCached
+ var picDef = new FileManager.PictureDefinition(Book.PictureId, FileManager.PictureSize._80x80);
+ (bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(picDef);
+
+ if (isDefault)
+ FileManager.PictureStorage.PictureCached += PictureStorage_PictureCached;
+
+ //Mutable property. Set the field so PropertyChanged doesn't fire.
+ _cover = ImageReader.ToImage(picture);
+
+ //Immutable properties
{
- displayValues[nameof(Title)] = book.Title;
- return getSortName(book.Title);
+ Title = Book.Title;
+ Series = Book.SeriesNames;
+ Length = Book.LengthInMinutes == 0 ? "" : $"{Book.LengthInMinutes / 60} hr {Book.LengthInMinutes % 60} min";
+ MyRating = GetStarString(Book.UserDefinedItem.Rating);
+ PurchaseDate = libraryBook.DateAdded.ToString("d");
+ ProductRating = GetStarString(Book.Rating);
+ Authors = Book.AuthorNames;
+ Narrators = Book.NarratorNames;
+ Category = string.Join(" > ", Book.CategoriesNames);
+ Misc = GetMiscDisplay(libraryBook);
+ Description = GetDescriptionDisplay(Book);
+ }
+
+ //DisplayTags and Liberate are live.
+ }
+
+ private void PictureStorage_PictureCached(object sender, string pictureId)
+ {
+ if (pictureId == Book.PictureId)
+ {
+ Cover = WindowsDesktopUtilities.WinAudibleImageServer.GetImage(pictureId, FileManager.PictureSize._80x80);
+ FileManager.PictureStorage.PictureCached -= PictureStorage_PictureCached;
}
}
- public string Authors => book.AuthorNames;
- public string Narrators => book.NarratorNames;
+ private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- public int Length
+ #region Data Source properties
+ public Image Cover
{
get
{
- displayValues[nameof(Length)]
- = book.LengthInMinutes == 0
- ? ""
- : $"{book.LengthInMinutes / 60} hr {book.LengthInMinutes % 60} min";
-
- return book.LengthInMinutes;
+ return _cover;
}
- }
-
- public string Series
- {
- get
+ private set
{
- displayValues[nameof(Series)] = book.SeriesNames;
- return getSortName(book.SeriesNames);
+ _cover = value;
+ NotifyPropertyChanged();
}
}
- private static string[] sortPrefixIgnores { get; } = new[] { "the", "a", "an" };
+ public string ProductRating { get; }
+ public string PurchaseDate { get; }
+ public string MyRating { get; }
+ public string Series { get; }
+ public string Title { get; }
+ public string Length { get; }
+ public string Authors { get; }
+ public string Narrators { get; }
+ public string Category { get; }
+ public string Misc { get; }
+ public string Description { get; }
+
+ public string DisplayTags => string.Join("\r\n", TagsEnumerated);
+ public (LiberatedState, PdfState) Liberate => (LibraryCommands.Liberated_Status(Book), LibraryCommands.Pdf_Status(Book));
+
+ #endregion
+
+ #region Data Sorting
+
+ private Dictionary> _compareValues { get; }
+ private static Dictionary _objectComparers;
+
+ public object GetMemberValue(string propertyName) => _compareValues[propertyName]();
+ public IComparer GetComparer(Type propertyType) => _objectComparers[propertyType];
+
+ ///
+ /// Instantiate comparers for every type needed to sort columns.
+ ///
+ static GridEntry()
+ {
+ _objectComparers = new Dictionary()
+ {
+ { typeof(string), new ObjectComparer() },
+ { typeof(int), new ObjectComparer() },
+ { typeof(float), new ObjectComparer() },
+ { typeof(DateTime), new ObjectComparer() },
+ { typeof(LiberatedState), new ObjectComparer() },
+ };
+ }
+ ///
+ /// Create getters for all member values by name
+ ///
+ Dictionary> CreatePropertyValueDictionary() => new()
+ {
+ { nameof(Title), () => getSortName(Book.Title)},
+ { nameof(Series),() => getSortName(Book.SeriesNames)},
+ { nameof(Length), () => Book.LengthInMinutes},
+ { nameof(MyRating), () => Book.UserDefinedItem.Rating.FirstScore},
+ { nameof(PurchaseDate), () => LibraryBook.DateAdded},
+ { nameof(ProductRating), () => Book.Rating.FirstScore},
+ { nameof(Authors), () => Authors},
+ { nameof(Narrators), () => Narrators},
+ { nameof(Description), () => Description},
+ { nameof(Category), () => Category},
+ { nameof(Misc), () => Misc},
+ { nameof(DisplayTags), () => DisplayTags},
+ { nameof(Liberate), () => Liberate.Item1}
+ };
+
+ private static readonly string[] sortPrefixIgnores = { "the", "a", "an" };
private static string getSortName(string unformattedName)
{
var sortName = unformattedName
@@ -95,104 +168,115 @@ namespace LibationWinForms
return sortName;
}
- private string descriptionCache = null;
- public string Description
+ #endregion
+
+ #region Static library display functions
+
+ public static (string mouseoverText, Bitmap buttonImage) GetLiberateDisplay(LiberatedState liberatedStatus, PdfState pdfStatus)
{
- get
+ string text;
+ Bitmap image;
+
+ // get mouseover text
{
- // HtmlAgilityPack is expensive. cache results
- if (descriptionCache is null)
+ var libState = liberatedStatus switch
{
- if (book.Description is null)
- descriptionCache = "";
- else
- {
- var doc = new HtmlAgilityPack.HtmlDocument();
- doc.LoadHtml(book.Description);
- var noHtml = doc.DocumentNode.InnerText;
- descriptionCache
- = noHtml.Length < 63
- ? noHtml
- : noHtml.Substring(0, 60) + "...";
- }
- }
+ LiberatedState.Liberated => "Liberated",
+ LiberatedState.PartialDownload => "File has been at least\r\npartially downloaded",
+ LiberatedState.NotDownloaded => "Book NOT downloaded",
+ _ => throw new Exception("Unexpected liberation state")
+ };
+
+ var pdfState = pdfStatus switch
+ {
+ PdfState.Downloaded => "\r\nPDF downloaded",
+ PdfState.NotDownloaded => "\r\nPDF NOT downloaded",
+ PdfState.NoPdf => "",
+ _ => throw new Exception("Unexpected PDF state")
+ };
+
+ text = libState + pdfState;
+
+ if (liberatedStatus == LiberatedState.NotDownloaded ||
+ liberatedStatus == LiberatedState.PartialDownload ||
+ pdfStatus == PdfState.NotDownloaded)
+ text += "\r\nClick to complete";
- return descriptionCache;
}
- }
- public string Category => string.Join(" > ", book.CategoriesNames);
-
- // star ratings retain numeric value but display star text. this is needed because just using star text doesn't sort correctly:
- // - star
- // - star star
- // - star 1/2
-
- public string Product_Rating
- {
- get
+ // get image
{
- displayValues[nameof(Product_Rating)] = starString(book.Rating);
- return firstScore(book.Rating);
+ var image_lib
+ = liberatedStatus == LiberatedState.NotDownloaded ? "red"
+ : liberatedStatus == LiberatedState.PartialDownload ? "yellow"
+ : liberatedStatus == LiberatedState.Liberated ? "green"
+ : throw new Exception("Unexpected liberation state");
+ var image_pdf
+ = pdfStatus == PdfState.NoPdf ? ""
+ : pdfStatus == PdfState.NotDownloaded ? "_pdf_no"
+ : pdfStatus == PdfState.Downloaded ? "_pdf_yes"
+ : throw new Exception("Unexpected PDF state");
+
+ image = (Bitmap)Properties.Resources.ResourceManager.GetObject($"liberate_{image_lib}{image_pdf}");
}
+
+ return (text, image);
}
- public string Purchase_Date
+ ///
+ /// This information should not change during lifetime, so call only once.
+ ///
+ private static string GetDescriptionDisplay(Book book)
+ {
+ var doc = new HtmlAgilityPack.HtmlDocument();
+ doc.LoadHtml(book.Description);
+ var noHtml = doc.DocumentNode.InnerText;
+ return
+ noHtml.Length < 63?
+ noHtml :
+ noHtml.Substring(0, 60) + "...";
+ }
+
+ ///
+ /// This information should not change during lifetime, so call only once.
+ ///
+ private static string GetMiscDisplay(LibraryBook libraryBook)
{
- get
- {
- displayValues[nameof(Purchase_Date)] = libraryBook.DateAdded.ToString("d");
- return libraryBook.DateAdded.ToString("yyyy-MM-dd HH:mm:ss");
- }
+ // max 5 text rows
+
+ var details = new List();
+
+ var locale
+ = string.IsNullOrWhiteSpace(libraryBook.Book.Locale)
+ ? "[unknown]"
+ : libraryBook.Book.Locale;
+ var acct
+ = string.IsNullOrWhiteSpace(libraryBook.Account)
+ ? "[unknown]"
+ : libraryBook.Account;
+ details.Add($"Account: {locale} - {acct}");
+
+ if (libraryBook.Book.HasPdf)
+ details.Add("Has PDF");
+ if (libraryBook.Book.IsAbridged)
+ details.Add("Abridged");
+ if (libraryBook.Book.DatePublished.HasValue)
+ details.Add($"Date pub'd: {libraryBook.Book.DatePublished.Value:MM/dd/yyyy}");
+ // this goes last since it's most likely to have a line-break
+ if (!string.IsNullOrWhiteSpace(libraryBook.Book.Publisher))
+ details.Add($"Pub: {libraryBook.Book.Publisher.Trim()}");
+
+ if (!details.Any())
+ return "[details not imported]";
+
+ return string.Join("\r\n", details);
}
- public string My_Rating
- {
- get
- {
- displayValues[nameof(My_Rating)] = starString(book.UserDefinedItem.Rating);
- return firstScore(book.UserDefinedItem.Rating);
- }
- }
+ private static string GetStarString(Rating rating)
+ => (rating?.FirstScore != null && rating?.FirstScore > 0f)
+ ? rating?.ToStarString()
+ : "";
- private string starString(Rating rating)
- => (rating?.FirstScore != null && rating?.FirstScore > 0f)
- ? rating?.ToStarString()
- : "";
- private string firstScore(Rating rating) => rating?.FirstScore.ToString("0.0");
-
- // max 5 text rows
- public string Misc
- {
- get
- {
- var details = new List();
-
- var locale
- = string.IsNullOrWhiteSpace(book.Locale)
- ? "[unknown]"
- : book.Locale;
- var acct
- = string.IsNullOrWhiteSpace(libraryBook.Account)
- ? "[unknown]"
- : libraryBook.Account;
- details.Add($"Account: {locale} - {acct}");
-
- if (book.HasPdf)
- details.Add("Has PDF");
- if (book.IsAbridged)
- details.Add("Abridged");
- if (book.DatePublished.HasValue)
- details.Add($"Date pub'd: {book.DatePublished.Value:MM/dd/yyyy}");
- // this goes last since it's most likely to have a line-break
- if (!string.IsNullOrWhiteSpace(book.Publisher))
- details.Add($"Pub: {book.Publisher.Trim()}");
-
- if (!details.Any())
- return "[details not imported]";
-
- return string.Join("\r\n", details);
- }
- }
- }
+ #endregion
+ }
}
diff --git a/LibationWinForms/IObjectMemberComparable.cs b/LibationWinForms/IObjectMemberComparable.cs
new file mode 100644
index 00000000..8bc5b762
--- /dev/null
+++ b/LibationWinForms/IObjectMemberComparable.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections;
+
+namespace LibationWinForms
+{
+ interface IObjectMemberComparable
+ {
+ IComparer GetComparer(Type propertyType);
+ object GetMemberValue(string valueName);
+ }
+}
diff --git a/LibationWinForms/LiberateDataGridViewImageButtonColumn.cs b/LibationWinForms/LiberateDataGridViewImageButtonColumn.cs
new file mode 100644
index 00000000..63d64257
--- /dev/null
+++ b/LibationWinForms/LiberateDataGridViewImageButtonColumn.cs
@@ -0,0 +1,30 @@
+using ApplicationServices;
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace LibationWinForms
+{
+ public class LiberateDataGridViewImageButtonColumn : DataGridViewImageButtonColumn
+ {
+ protected override DataGridViewImageButtonCell NewCell()
+ => new LiberateDataGridViewImageButtonCell();
+ }
+
+ internal class LiberateDataGridViewImageButtonCell : DataGridViewImageButtonCell
+ {
+ 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 (LiberatedState liberatedState, PdfState pdfState))
+ {
+ (string mouseoverText, Bitmap buttonImage) = GridEntry.GetLiberateDisplay(liberatedState, pdfState);
+
+ DrawImage(graphics, buttonImage, cellBounds);
+
+ ToolTipText = mouseoverText;
+ }
+ }
+ }
+}
diff --git a/LibationWinForms/ObjectComparer[T].cs b/LibationWinForms/ObjectComparer[T].cs
new file mode 100644
index 00000000..2bc69d8d
--- /dev/null
+++ b/LibationWinForms/ObjectComparer[T].cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections;
+
+namespace LibationWinForms
+{
+ class ObjectComparer : IComparer where T : IComparable
+ {
+ public int Compare(object x, object y) => ((T)x).CompareTo((T)y);
+ }
+}
diff --git a/LibationWinForms/ObjectMemberComparer[T].cs b/LibationWinForms/ObjectMemberComparer[T].cs
new file mode 100644
index 00000000..00f29510
--- /dev/null
+++ b/LibationWinForms/ObjectMemberComparer[T].cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+
+namespace LibationWinForms
+{
+ class ObjectMemberComparer : IComparer where T : IObjectMemberComparable
+ {
+ public ListSortDirection Direction { get; set; } = ListSortDirection.Ascending;
+ public string PropertyName { get; set; }
+
+ public int Compare(T x, T y)
+ {
+ var val1 = x.GetMemberValue(PropertyName);
+ var val2 = y.GetMemberValue(PropertyName);
+
+ return DirMult * x.GetComparer(val1.GetType()).Compare(val1, val2);
+ }
+
+ private int DirMult => Direction == ListSortDirection.Descending ? -1 : 1;
+ }
+}
diff --git a/LibationWinForms/ProductsGrid.Designer.cs b/LibationWinForms/ProductsGrid.Designer.cs
index a81c8abf..0a74a123 100644
--- a/LibationWinForms/ProductsGrid.Designer.cs
+++ b/LibationWinForms/ProductsGrid.Designer.cs
@@ -28,146 +28,198 @@
///
private void InitializeComponent()
{
- this.components = new System.ComponentModel.Container();
- this.gridEntryBindingSource = new System.Windows.Forms.BindingSource(this.components);
- this.gridEntryDataGridView = new System.Windows.Forms.DataGridView();
- this.dataGridViewImageColumn1 = new System.Windows.Forms.DataGridViewImageColumn();
- this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dataGridViewTextBoxColumn4 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dataGridViewTextBoxColumn6 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dataGridViewTextBoxColumn7 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dataGridViewTextBoxColumn8 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dataGridViewTextBoxColumn9 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dataGridViewTextBoxColumn10 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dataGridViewTextBoxColumn11 = new System.Windows.Forms.DataGridViewTextBoxColumn();
- ((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).BeginInit();
- this.SuspendLayout();
- //
- // gridEntryBindingSource
- //
- this.gridEntryBindingSource.DataSource = typeof(LibationWinForms.GridEntry);
- //
- // gridEntryDataGridView
- //
- this.gridEntryDataGridView.AutoGenerateColumns = false;
- this.gridEntryDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
- this.gridEntryDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
- this.dataGridViewImageColumn1,
- this.dataGridViewTextBoxColumn1,
- this.dataGridViewTextBoxColumn2,
- this.dataGridViewTextBoxColumn3,
- this.dataGridViewTextBoxColumn4,
- this.dataGridViewTextBoxColumn5,
- this.dataGridViewTextBoxColumn6,
- this.dataGridViewTextBoxColumn7,
- this.dataGridViewTextBoxColumn8,
- this.dataGridViewTextBoxColumn9,
- this.dataGridViewTextBoxColumn10,
- this.dataGridViewTextBoxColumn11});
- this.gridEntryDataGridView.DataSource = this.gridEntryBindingSource;
- this.gridEntryDataGridView.Location = new System.Drawing.Point(54, 58);
- this.gridEntryDataGridView.Name = "gridEntryDataGridView";
- this.gridEntryDataGridView.Size = new System.Drawing.Size(300, 220);
- this.gridEntryDataGridView.TabIndex = 0;
- //
- // dataGridViewImageColumn1
- //
- this.dataGridViewImageColumn1.DataPropertyName = "Cover";
- this.dataGridViewImageColumn1.HeaderText = "Cover";
- this.dataGridViewImageColumn1.Name = "dataGridViewImageColumn1";
- this.dataGridViewImageColumn1.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn1
- //
- this.dataGridViewTextBoxColumn1.DataPropertyName = "Title";
- this.dataGridViewTextBoxColumn1.HeaderText = "Title";
- this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
- this.dataGridViewTextBoxColumn1.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn2
- //
- this.dataGridViewTextBoxColumn2.DataPropertyName = "Authors";
- this.dataGridViewTextBoxColumn2.HeaderText = "Authors";
- this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
- this.dataGridViewTextBoxColumn2.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn3
- //
- this.dataGridViewTextBoxColumn3.DataPropertyName = "Narrators";
- this.dataGridViewTextBoxColumn3.HeaderText = "Narrators";
- this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
- this.dataGridViewTextBoxColumn3.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn4
- //
- this.dataGridViewTextBoxColumn4.DataPropertyName = "Length";
- this.dataGridViewTextBoxColumn4.HeaderText = "Length";
- this.dataGridViewTextBoxColumn4.Name = "dataGridViewTextBoxColumn4";
- this.dataGridViewTextBoxColumn4.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn5
- //
- this.dataGridViewTextBoxColumn5.DataPropertyName = "Series";
- this.dataGridViewTextBoxColumn5.HeaderText = "Series";
- this.dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5";
- this.dataGridViewTextBoxColumn5.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn6
- //
- this.dataGridViewTextBoxColumn6.DataPropertyName = "Description";
- this.dataGridViewTextBoxColumn6.HeaderText = "Description";
- this.dataGridViewTextBoxColumn6.Name = "dataGridViewTextBoxColumn6";
- this.dataGridViewTextBoxColumn6.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn7
- //
- this.dataGridViewTextBoxColumn7.DataPropertyName = "Category";
- this.dataGridViewTextBoxColumn7.HeaderText = "Category";
- this.dataGridViewTextBoxColumn7.Name = "dataGridViewTextBoxColumn7";
- this.dataGridViewTextBoxColumn7.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn8
- //
- this.dataGridViewTextBoxColumn8.DataPropertyName = "Product_Rating";
- this.dataGridViewTextBoxColumn8.HeaderText = "Product_Rating";
- this.dataGridViewTextBoxColumn8.Name = "dataGridViewTextBoxColumn8";
- this.dataGridViewTextBoxColumn8.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn9
- //
- this.dataGridViewTextBoxColumn9.DataPropertyName = "Purchase_Date";
- this.dataGridViewTextBoxColumn9.HeaderText = "Purchase_Date";
- this.dataGridViewTextBoxColumn9.Name = "dataGridViewTextBoxColumn9";
- this.dataGridViewTextBoxColumn9.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn10
- //
- this.dataGridViewTextBoxColumn10.DataPropertyName = "My_Rating";
- this.dataGridViewTextBoxColumn10.HeaderText = "My_Rating";
- this.dataGridViewTextBoxColumn10.Name = "dataGridViewTextBoxColumn10";
- this.dataGridViewTextBoxColumn10.ReadOnly = true;
- //
- // dataGridViewTextBoxColumn11
- //
- this.dataGridViewTextBoxColumn11.DataPropertyName = "Misc";
- this.dataGridViewTextBoxColumn11.HeaderText = "Misc";
- this.dataGridViewTextBoxColumn11.Name = "dataGridViewTextBoxColumn11";
- this.dataGridViewTextBoxColumn11.ReadOnly = true;
- //
- // ProductsGrid
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.Controls.Add(this.gridEntryDataGridView);
- this.Name = "ProductsGrid";
- this.Size = new System.Drawing.Size(434, 329);
- ((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).EndInit();
- this.ResumeLayout(false);
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
+ this.gridEntryBindingSource = new System.Windows.Forms.BindingSource(this.components);
+ this.gridEntryDataGridView = new System.Windows.Forms.DataGridView();
+ this.dataGridViewImageButtonBoxColumn1 = new LibationWinForms.LiberateDataGridViewImageButtonColumn();
+ this.dataGridViewImageColumn1 = new System.Windows.Forms.DataGridViewImageColumn();
+ this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dataGridViewTextBoxColumn4 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dataGridViewTextBoxColumn6 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dataGridViewTextBoxColumn7 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.ProductRating = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.PurchaseDate = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.MyRating = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dataGridViewTextBoxColumn11 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dataGridViewImageButtonBoxColumn2 = new LibationWinForms.EditTagsDataGridViewImageButtonColumn();
+ ((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).BeginInit();
+ this.SuspendLayout();
+ //
+ // gridEntryBindingSource
+ //
+ this.gridEntryBindingSource.DataSource = typeof(LibationWinForms.GridEntry);
+ //
+ // gridEntryDataGridView
+ //
+ this.gridEntryDataGridView.AllowUserToAddRows = false;
+ this.gridEntryDataGridView.AllowUserToDeleteRows = false;
+ this.gridEntryDataGridView.AutoGenerateColumns = false;
+ this.gridEntryDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ this.gridEntryDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+ this.dataGridViewImageButtonBoxColumn1,
+ this.dataGridViewImageColumn1,
+ this.dataGridViewTextBoxColumn1,
+ this.dataGridViewTextBoxColumn2,
+ this.dataGridViewTextBoxColumn3,
+ this.dataGridViewTextBoxColumn4,
+ this.dataGridViewTextBoxColumn5,
+ this.dataGridViewTextBoxColumn6,
+ this.dataGridViewTextBoxColumn7,
+ this.ProductRating,
+ this.PurchaseDate,
+ this.MyRating,
+ this.dataGridViewTextBoxColumn11,
+ this.dataGridViewImageButtonBoxColumn2});
+ this.gridEntryDataGridView.DataSource = this.gridEntryBindingSource;
+ dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
+ dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Window;
+ dataGridViewCellStyle1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
+ dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.ControlText;
+ dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
+ dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
+ dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
+ this.gridEntryDataGridView.DefaultCellStyle = dataGridViewCellStyle1;
+ this.gridEntryDataGridView.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.gridEntryDataGridView.Location = new System.Drawing.Point(0, 0);
+ this.gridEntryDataGridView.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.gridEntryDataGridView.Name = "gridEntryDataGridView";
+ this.gridEntryDataGridView.ReadOnly = true;
+ this.gridEntryDataGridView.RowHeadersVisible = false;
+ this.gridEntryDataGridView.RowTemplate.Height = 82;
+ this.gridEntryDataGridView.Size = new System.Drawing.Size(1503, 380);
+ this.gridEntryDataGridView.TabIndex = 0;
+ //
+ // dataGridViewImageButtonBoxColumn1
+ //
+ this.dataGridViewImageButtonBoxColumn1.DataPropertyName = "Liberate";
+ this.dataGridViewImageButtonBoxColumn1.HeaderText = "Liberate";
+ this.dataGridViewImageButtonBoxColumn1.Name = "dataGridViewImageButtonBoxColumn1";
+ this.dataGridViewImageButtonBoxColumn1.ReadOnly = true;
+ this.dataGridViewImageButtonBoxColumn1.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+ this.dataGridViewImageButtonBoxColumn1.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
+ this.dataGridViewImageButtonBoxColumn1.Width = 70;
+ //
+ // dataGridViewImageColumn1
+ //
+ this.dataGridViewImageColumn1.DataPropertyName = "Cover";
+ this.dataGridViewImageColumn1.HeaderText = "Cover";
+ this.dataGridViewImageColumn1.Name = "dataGridViewImageColumn1";
+ this.dataGridViewImageColumn1.ReadOnly = true;
+ this.dataGridViewImageColumn1.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+ this.dataGridViewImageColumn1.ToolTipText = "Cover Art";
+ this.dataGridViewImageColumn1.Width = 80;
+ //
+ // dataGridViewTextBoxColumn1
+ //
+ this.dataGridViewTextBoxColumn1.DataPropertyName = "Title";
+ this.dataGridViewTextBoxColumn1.HeaderText = "Title";
+ this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
+ this.dataGridViewTextBoxColumn1.ReadOnly = true;
+ this.dataGridViewTextBoxColumn1.ToolTipText = "Book Title";
+ this.dataGridViewTextBoxColumn1.Width = 200;
+ //
+ // dataGridViewTextBoxColumn2
+ //
+ this.dataGridViewTextBoxColumn2.DataPropertyName = "Authors";
+ this.dataGridViewTextBoxColumn2.HeaderText = "Authors";
+ this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
+ this.dataGridViewTextBoxColumn2.ReadOnly = true;
+ this.dataGridViewTextBoxColumn2.ToolTipText = "Book Author(s)";
+ //
+ // dataGridViewTextBoxColumn3
+ //
+ this.dataGridViewTextBoxColumn3.DataPropertyName = "Narrators";
+ this.dataGridViewTextBoxColumn3.HeaderText = "Narrators";
+ this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
+ this.dataGridViewTextBoxColumn3.ReadOnly = true;
+ this.dataGridViewTextBoxColumn3.ToolTipText = "Audiobook Narrator(s)";
+ //
+ // dataGridViewTextBoxColumn4
+ //
+ this.dataGridViewTextBoxColumn4.DataPropertyName = "Length";
+ this.dataGridViewTextBoxColumn4.HeaderText = "Length";
+ this.dataGridViewTextBoxColumn4.Name = "dataGridViewTextBoxColumn4";
+ this.dataGridViewTextBoxColumn4.ReadOnly = true;
+ this.dataGridViewTextBoxColumn4.ToolTipText = "Recording Length";
+ //
+ // dataGridViewTextBoxColumn5
+ //
+ this.dataGridViewTextBoxColumn5.DataPropertyName = "Series";
+ this.dataGridViewTextBoxColumn5.HeaderText = "Series";
+ this.dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5";
+ this.dataGridViewTextBoxColumn5.ReadOnly = true;
+ this.dataGridViewTextBoxColumn5.ToolTipText = "Book Series";
+ //
+ // dataGridViewTextBoxColumn6
+ //
+ this.dataGridViewTextBoxColumn6.DataPropertyName = "Description";
+ this.dataGridViewTextBoxColumn6.HeaderText = "Description";
+ this.dataGridViewTextBoxColumn6.Name = "dataGridViewTextBoxColumn6";
+ this.dataGridViewTextBoxColumn6.ReadOnly = true;
+ //
+ // dataGridViewTextBoxColumn7
+ //
+ this.dataGridViewTextBoxColumn7.DataPropertyName = "Category";
+ this.dataGridViewTextBoxColumn7.HeaderText = "Category";
+ this.dataGridViewTextBoxColumn7.Name = "dataGridViewTextBoxColumn7";
+ this.dataGridViewTextBoxColumn7.ReadOnly = true;
+ //
+ // ProductRating
+ //
+ this.ProductRating.DataPropertyName = "ProductRating";
+ this.ProductRating.HeaderText = "Product Rating";
+ this.ProductRating.Name = "ProductRating";
+ this.ProductRating.ReadOnly = true;
+ this.ProductRating.Width = 108;
+ //
+ // PurchaseDate
+ //
+ this.PurchaseDate.DataPropertyName = "PurchaseDate";
+ this.PurchaseDate.HeaderText = "Purchase Date";
+ this.PurchaseDate.Name = "PurchaseDate";
+ this.PurchaseDate.ReadOnly = true;
+ //
+ // MyRating
+ //
+ this.MyRating.DataPropertyName = "MyRating";
+ this.MyRating.HeaderText = "My Rating";
+ this.MyRating.Name = "MyRating";
+ this.MyRating.ReadOnly = true;
+ this.MyRating.Width = 108;
+ //
+ // dataGridViewTextBoxColumn11
+ //
+ this.dataGridViewTextBoxColumn11.DataPropertyName = "Misc";
+ this.dataGridViewTextBoxColumn11.HeaderText = "Misc";
+ this.dataGridViewTextBoxColumn11.Name = "dataGridViewTextBoxColumn11";
+ this.dataGridViewTextBoxColumn11.ReadOnly = true;
+ this.dataGridViewTextBoxColumn11.Width = 135;
+ //
+ // dataGridViewImageButtonBoxColumn2
+ //
+ this.dataGridViewImageButtonBoxColumn2.DataPropertyName = "DisplayTags";
+ this.dataGridViewImageButtonBoxColumn2.HeaderText = "Edit Tags";
+ this.dataGridViewImageButtonBoxColumn2.Name = "dataGridViewImageButtonBoxColumn2";
+ this.dataGridViewImageButtonBoxColumn2.ReadOnly = true;
+ this.dataGridViewImageButtonBoxColumn2.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+ this.dataGridViewImageButtonBoxColumn2.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
+ //
+ // ProductsGrid
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.gridEntryDataGridView);
+ this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.Name = "ProductsGrid";
+ this.Size = new System.Drawing.Size(1503, 380);
+ ((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).EndInit();
+ this.ResumeLayout(false);
}
@@ -175,17 +227,22 @@
private System.Windows.Forms.BindingSource gridEntryBindingSource;
private System.Windows.Forms.DataGridView gridEntryDataGridView;
- private System.Windows.Forms.DataGridViewImageColumn dataGridViewImageColumn1;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn3;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn4;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn5;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn6;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn7;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn8;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn9;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn10;
- private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn11;
- }
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn8;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn9;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn10;
+ private LiberateDataGridViewImageButtonColumn dataGridViewImageButtonBoxColumn1;
+ private System.Windows.Forms.DataGridViewImageColumn dataGridViewImageColumn1;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn3;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn4;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn5;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn6;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn7;
+ private System.Windows.Forms.DataGridViewTextBoxColumn ProductRating;
+ private System.Windows.Forms.DataGridViewTextBoxColumn PurchaseDate;
+ private System.Windows.Forms.DataGridViewTextBoxColumn MyRating;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn11;
+ private EditTagsDataGridViewImageButtonColumn dataGridViewImageButtonBoxColumn2;
+ }
}
diff --git a/LibationWinForms/ProductsGrid.cs b/LibationWinForms/ProductsGrid.cs
index 5f811bd1..6cea7acc 100644
--- a/LibationWinForms/ProductsGrid.cs
+++ b/LibationWinForms/ProductsGrid.cs
@@ -1,12 +1,11 @@
using System;
using System.Drawing;
using System.Linq;
+using System.Threading.Tasks;
using System.Windows.Forms;
using ApplicationServices;
using DataLayer;
using Dinah.Core;
-using Dinah.Core.Collections.Generic;
-using Dinah.Core.DataBinding;
using Dinah.Core.Windows.Forms;
using LibationWinForms.Dialogs;
@@ -30,158 +29,54 @@ namespace LibationWinForms
public event EventHandler VisibleCountChanged;
public event EventHandler BackupCountsChanged;
- private const string EDIT_TAGS = "Edit Tags";
- private const string LIBERATE = "Liberate";
-
// alias
- private DataGridView dataGridView => gridEntryDataGridView;
+ private DataGridView _dataGridView => gridEntryDataGridView;
public ProductsGrid()
{
InitializeComponent();
- formatDataGridView();
- addLiberateButtons();
- addEditTagsButtons();
- formatColumns();
-
- manageLiveImageUpdateSubscriptions();
-
- enableDoubleBuffering();
- }
-
- private void enableDoubleBuffering()
- {
- var propertyInfo = dataGridView.GetType().GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
-
- //var before = (bool)propertyInfo.GetValue(dataGridView);
- propertyInfo.SetValue(dataGridView, true, null);
- //var after = (bool)propertyInfo.GetValue(dataGridView);
- }
-
- private void formatDataGridView()
- {
- dataGridView.Dock = DockStyle.Fill;
- dataGridView.AllowUserToAddRows = false;
- dataGridView.AllowUserToDeleteRows = false;
- dataGridView.AutoGenerateColumns = false;
- dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
- dataGridView.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
- dataGridView.ReadOnly = true;
- dataGridView.RowHeadersVisible = false;
-
- // adjust height for 80x80 pictures.
- // this must be done before databinding. or can alter later by iterating through rows
- dataGridView.RowTemplate.Height = 82;
- dataGridView.CellFormatting += replaceFormatted;
- dataGridView.CellFormatting += hiddenFormatting;
// sorting breaks filters. must reapply filters after sorting
- dataGridView.Sorted += (_, __) => filter();
- }
+ _dataGridView.Sorted += (_, __) => Filter();
+ _dataGridView.CellFormatting += HiddenFormatting;
+ _dataGridView.CellContentClick += DataGridView_CellContentClick;
- #region format text cells. ie: not buttons
- private void replaceFormatted(object sender, DataGridViewCellFormattingEventArgs e)
+ EnableDoubleBuffering();
+ }
+
+ private void EnableDoubleBuffering()
+ {
+ var propertyInfo = _dataGridView.GetType().GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
+
+ //var before = (bool)propertyInfo.GetValue(dataGridView);
+ propertyInfo.SetValue(_dataGridView, true, null);
+ //var after = (bool)propertyInfo.GetValue(dataGridView);
+ }
+
+ #region Button controls
+
+ private async void DataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
- var col = ((DataGridView)sender).Columns[e.ColumnIndex];
- if (col is DataGridViewTextBoxColumn textCol && getGridEntry(e.RowIndex).TryDisplayValue(textCol.Name, out string value))
+ // handle grid button click: https://stackoverflow.com/a/13687844
+ if (e.RowIndex < 0 || _dataGridView.Columns[e.ColumnIndex] is not DataGridViewButtonColumn)
+ return;
+
+ var liveGridEntry = getGridEntry(e.RowIndex);
+
+ switch (_dataGridView.Columns[e.ColumnIndex].DataPropertyName)
{
- // DO NOT DO THIS: getCell(e).Value = value;
- // it's the wrong way and will infinitely call CellFormatting on each assign
-
- // this is the correct way. will actually set FormattedValue (and EditedFormattedValue) while leaving Value as-is for sorting
- e.Value = value;
-
- getCell(e).ToolTipText = value;
+ case GridEntry.LIBERATE_COLUMN_NAME:
+ await Liberate_Click(liveGridEntry);
+ break;
+ case GridEntry.EDIT_TAGS_COLUMN_NAME:
+ EditTags_Click(liveGridEntry);
+ break;
}
}
- private void hiddenFormatting(object sender, DataGridViewCellFormattingEventArgs e)
+ private async Task Liberate_Click(GridEntry liveGridEntry)
{
- var dgv = (DataGridView)sender;
- // no action needed for buttons
- if (e.RowIndex < 0 || dgv.Columns[e.ColumnIndex] is DataGridViewButtonColumn)
- return;
-
- var isHidden = getGridEntry(e.RowIndex).TagsEnumerated.Contains("hidden");
-
- getCell(e).Style
- = isHidden
- ? new DataGridViewCellStyle { ForeColor = Color.LightGray }
- : dgv.DefaultCellStyle;
- }
- #endregion
-
- #region liberation buttons
- private void addLiberateButtons()
- {
- dataGridView.Columns.Insert(0, new DataGridViewButtonColumn { HeaderText = LIBERATE });
-
- dataGridView.CellPainting += liberate_Paint;
- dataGridView.CellContentClick += liberate_Click;
- }
-
- private void liberate_Paint(object sender, DataGridViewCellPaintingEventArgs e)
- {
- if (!isColumnValid(e, LIBERATE))
- return;
-
- var cell = getCell(e);
- var gridEntry = getGridEntry(e.RowIndex);
- var liberatedStatus = gridEntry.Liberated_Status;
- var pdfStatus = gridEntry.Pdf_Status;
-
- // mouseover text
- {
- var libState = liberatedStatus switch
- {
- LiberatedState.Liberated => "Liberated",
- LiberatedState.PartialDownload => "File has been at least\r\npartially downloaded",
- LiberatedState.NotDownloaded => "Book NOT downloaded",
- _ => throw new Exception("Unexpected liberation state")
- };
-
- var pdfState = pdfStatus switch
- {
- PdfState.Downloaded => "\r\nPDF downloaded",
- PdfState.NotDownloaded => "\r\nPDF NOT downloaded",
- PdfState.NoPdf => "",
- _ => throw new Exception("Unexpected PDF state")
- };
-
- var text = libState + pdfState;
-
- if (liberatedStatus == LiberatedState.NotDownloaded ||
- liberatedStatus == LiberatedState.PartialDownload ||
- pdfStatus == PdfState.NotDownloaded)
- text += "\r\nClick to complete";
-
- //DEBUG//cell.Value = text;
- cell.ToolTipText = text;
- }
-
- // draw img
- {
- var image_lib
- = liberatedStatus == LiberatedState.NotDownloaded ? "red"
- : liberatedStatus == LiberatedState.PartialDownload ? "yellow"
- : liberatedStatus == LiberatedState.Liberated ? "green"
- : throw new Exception("Unexpected liberation state");
- var image_pdf
- = pdfStatus == PdfState.NoPdf ? ""
- : pdfStatus == PdfState.NotDownloaded ? "_pdf_no"
- : pdfStatus == PdfState.Downloaded ? "_pdf_yes"
- : throw new Exception("Unexpected PDF state");
- var image = (Bitmap)Properties.Resources.ResourceManager.GetObject($"liberate_{image_lib}{image_pdf}");
- drawImage(e, image);
- }
- }
-
- private async void liberate_Click(object sender, DataGridViewCellEventArgs e)
- {
- if (!isColumnValid(e, LIBERATE))
- return;
-
- var libraryBook = getGridEntry(e.RowIndex).GetLibraryBook();
+ var libraryBook = liveGridEntry.LibraryBook;
// liberated: open explorer to file
if (TransitionalFileLocator.Audio_Exists(libraryBook.Book))
@@ -195,146 +90,24 @@ namespace LibationWinForms
// else: liberate
await BookLiberation.ProcessorAutomationController.BackupSingleBookAsync(libraryBook, (_, __) => RefreshRow(libraryBook.Book.AudibleProductId));
}
- #endregion
- public void RefreshRow(string productId)
+ private void EditTags_Click(GridEntry liveGridEntry)
{
- var rowId = getRowId((ge) => ge.AudibleProductId == productId);
-
- // update cells incl Liberate button text
- dataGridView.InvalidateRow(rowId);
-
- // needed in case filtering by -IsLiberated and it gets changed to Liberated. want to immediately show the change
- filter();
-
- BackupCountsChanged?.Invoke(this, EventArgs.Empty);
- }
-
- #region tag buttons
- private void addEditTagsButtons()
- {
- dataGridView.Columns.Add(new DataGridViewButtonColumn { HeaderText = EDIT_TAGS });
-
- dataGridView.CellPainting += editTags_Paint;
- dataGridView.CellContentClick += editTags_Click;
- }
-
- private void editTags_Paint(object sender, DataGridViewCellPaintingEventArgs e)
- {
- // DataGridView Image for Button Column: https://stackoverflow.com/a/36253883
-
- if (!isColumnValid(e, EDIT_TAGS))
- return;
-
- var cell = getCell(e);
- var gridEntry = getGridEntry(e.RowIndex);
-
- var displayTags = gridEntry.TagsEnumerated.ToList();
-
- if (displayTags.Any())
- cell.Value = string.Join("\r\n", displayTags);
- else
- {
- // if removing all tags: clear previous tag text
- cell.Value = "";
- drawImage(e, Properties.Resources.edit_tags_25x25);
- }
- }
-
- private void editTags_Click(object sender, DataGridViewCellEventArgs e)
- {
- // handle grid button click: https://stackoverflow.com/a/13687844
-
- var dgv = (DataGridView)sender;
-
- if (!isColumnValid(e, EDIT_TAGS))
- return;
-
- var liveGridEntry = getGridEntry(e.RowIndex);
-
- // EditTagsDialog should display better-formatted title
- liveGridEntry.TryDisplayValue(nameof(liveGridEntry.Title), out string value);
-
- var bookDetailsForm = new BookDetailsDialog(value, liveGridEntry.Tags);
+ var bookDetailsForm = new BookDetailsDialog(liveGridEntry.Title, liveGridEntry.Tags);
if (bookDetailsForm.ShowDialog() != DialogResult.OK)
return;
- var qtyChanges = LibraryCommands.UpdateTags(liveGridEntry.GetBook(), bookDetailsForm.NewTags);
- if (qtyChanges == 0)
+ var qtyChanges = LibraryCommands.UpdateTags(liveGridEntry.LibraryBook.Book, bookDetailsForm.NewTags);
+ if (qtyChanges == 0)
return;
- // force a re-draw, and re-apply filters
-
- // needed to update text colors
- dgv.InvalidateRow(e.RowIndex);
-
- filter();
+ //Re-apply filters
+ Filter();
}
+
#endregion
- private static void drawImage(DataGridViewCellPaintingEventArgs e, Bitmap image)
- {
- e.Paint(e.CellBounds, DataGridViewPaintParts.All);
-
- var w = image.Width;
- var h = image.Height;
- var x = e.CellBounds.Left + (e.CellBounds.Width - w) / 2;
- var y = e.CellBounds.Top + (e.CellBounds.Height - h) / 2;
-
- e.Graphics.DrawImage(image, new Rectangle(x, y, w, h));
- e.Handled = true;
- }
-
- private bool isColumnValid(DataGridViewCellEventArgs e, string colName) => isColumnValid(e.RowIndex, e.ColumnIndex, colName);
- private bool isColumnValid(DataGridViewCellPaintingEventArgs e, string colName) => isColumnValid(e.RowIndex, e.ColumnIndex, colName);
- private bool isColumnValid(int rowIndex, int colIndex, string colName)
- {
- var col = dataGridView.Columns[colIndex];
- return rowIndex >= 0 && col.Name == colName && col is DataGridViewButtonColumn;
- }
-
- private void formatColumns()
- {
- for (var i = dataGridView.ColumnCount - 1; i >= 0; i--)
- {
- var col = dataGridView.Columns[i];
-
- // initial HeaderText is the lookup name from GridEntry class. any formatting below won't change this
- col.Name = col.HeaderText;
-
- if (!(col is DataGridViewImageColumn || col is DataGridViewButtonColumn))
- col.SortMode = DataGridViewColumnSortMode.Automatic;
-
- col.HeaderText = col.HeaderText.Replace("_", " ");
-
- col.Width = col.Name switch
- {
- LIBERATE => 70,
- nameof(GridEntry.Cover) => 80,
- nameof(GridEntry.Title) => col.Width * 2,
- nameof(GridEntry.Misc) => (int)(col.Width * 1.35),
- var n when n.In(nameof(GridEntry.My_Rating), nameof(GridEntry.Product_Rating)) => col.Width + 8,
- _ => col.Width
- };
- }
- }
-
- #region live update newly downloaded and cached images
- private void manageLiveImageUpdateSubscriptions()
- {
- FileManager.PictureStorage.PictureCached += crossThreadImageUpdate;
- Disposed += (_, __) => FileManager.PictureStorage.PictureCached -= crossThreadImageUpdate;
- }
-
- private void crossThreadImageUpdate(object _, string pictureId)
- => dataGridView.UIThread(() => updateRowImage(pictureId));
- private void updateRowImage(string pictureId)
- {
- var rowId = getRowId((ge) => ge.PictureId == pictureId);
- if (rowId > -1)
- dataGridView.InvalidateRow(rowId);
- }
- #endregion
+ #region UI display functions
private bool hasBeenDisplayed = false;
public void Display()
@@ -352,15 +125,15 @@ namespace LibationWinForms
// if no data. hide all columns. return
if (!lib.Any())
{
- for (var i = dataGridView.ColumnCount - 1; i >= 0; i--)
- dataGridView.Columns.RemoveAt(i);
+ for (var i = _dataGridView.ColumnCount - 1; i >= 0; i--)
+ _dataGridView.Columns.RemoveAt(i);
return;
}
var orderedGridEntries = lib
.Select(lb => new GridEntry(lb)).ToList()
// default load order
- .OrderByDescending(ge => ge.Purchase_Date)
+ .OrderByDescending(ge => ge.PurchaseDate)
//// more advanced example: sort by author, then series, then title
//.OrderBy(ge => ge.Authors)
// .ThenBy(ge => ge.Series)
@@ -370,49 +143,83 @@ namespace LibationWinForms
//
// BIND
//
- gridEntryBindingSource.DataSource = orderedGridEntries.ToSortableBindingList();
+ gridEntryBindingSource.DataSource = new SortableBindingList2(orderedGridEntries);
//
// FILTER
//
- filter();
+ Filter();
BackupCountsChanged?.Invoke(this, EventArgs.Empty);
}
+ public void RefreshRow(string productId)
+ {
+ var rowId = getRowIndex((ge) => ge.AudibleProductId == productId);
+
+ // update cells incl Liberate button text
+ _dataGridView.InvalidateRow(rowId);
+
+ // needed in case filtering by -IsLiberated and it gets changed to Liberated. want to immediately show the change
+ Filter();
+
+ BackupCountsChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ #region format text cells. ie: not buttons
+
+ private void HiddenFormatting(object sender, DataGridViewCellFormattingEventArgs e)
+ {
+ var dgv = (DataGridView)sender;
+ // no action needed for buttons
+ if (e.RowIndex < 0 || dgv.Columns[e.ColumnIndex] is DataGridViewButtonColumn)
+ return;
+
+ var isHidden = getGridEntry(e.RowIndex).TagsEnumerated.Contains("hidden");
+
+ getCell(e).Style
+ = isHidden
+ ? new DataGridViewCellStyle { ForeColor = Color.LightGray }
+ : dgv.DefaultCellStyle;
+ }
+
+ #endregion
+
+ #endregion
+
#region filter
+
string _filterSearchString;
- private void filter() => Filter(_filterSearchString);
+ private void Filter() => Filter(_filterSearchString);
public void Filter(string searchString)
{
_filterSearchString = searchString;
- if (dataGridView.Rows.Count == 0)
+ if (_dataGridView.Rows.Count == 0)
return;
var searchResults = SearchEngineCommands.Search(searchString);
var productIds = searchResults.Docs.Select(d => d.ProductId).ToList();
// https://stackoverflow.com/a/18942430
- var currencyManager = (CurrencyManager)BindingContext[dataGridView.DataSource];
+ var currencyManager = (CurrencyManager)BindingContext[_dataGridView.DataSource];
currencyManager.SuspendBinding();
{
- for (var r = dataGridView.RowCount - 1; r >= 0; r--)
- dataGridView.Rows[r].Visible = productIds.Contains(getGridEntry(r).AudibleProductId);
+ for (var r = _dataGridView.RowCount - 1; r >= 0; r--)
+ _dataGridView.Rows[r].Visible = productIds.Contains(getGridEntry(r).AudibleProductId);
}
currencyManager.ResumeBinding();
- VisibleCountChanged?.Invoke(this, dataGridView.AsEnumerable().Count(r => r.Visible));
+ VisibleCountChanged?.Invoke(this, _dataGridView.AsEnumerable().Count(r => r.Visible));
}
+
#endregion
- private int getRowId(Func func) => dataGridView.GetRowIdOfBoundItem(func);
+ #region DataGridView Macros
- private GridEntry getGridEntry(int rowIndex) => dataGridView.GetBoundItem(rowIndex);
+ private int getRowIndex(Func func) => _dataGridView.GetRowIdOfBoundItem(func);
+ private GridEntry getGridEntry(int rowIndex) => _dataGridView.GetBoundItem(rowIndex);
+ private DataGridViewCell getCell(DataGridViewCellFormattingEventArgs e) => _dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex];
- private DataGridViewCell getCell(DataGridViewCellFormattingEventArgs e) => getCell(e.RowIndex, e.ColumnIndex);
-
- private DataGridViewCell getCell(DataGridViewCellPaintingEventArgs e) => getCell(e.RowIndex, e.ColumnIndex);
-
- private DataGridViewCell getCell(int rowIndex, int columnIndex) => dataGridView.Rows[rowIndex].Cells[columnIndex];
+ #endregion
}
}
diff --git a/LibationWinForms/ProductsGrid.resx b/LibationWinForms/ProductsGrid.resx
index d1166daf..688d741a 100644
--- a/LibationWinForms/ProductsGrid.resx
+++ b/LibationWinForms/ProductsGrid.resx
@@ -1,64 +1,4 @@
-
-
-
+
@@ -120,4 +60,19 @@
17, 17
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
\ No newline at end of file
diff --git a/LibationWinForms/SortableBindingList2[T].cs b/LibationWinForms/SortableBindingList2[T].cs
new file mode 100644
index 00000000..1a0e1d97
--- /dev/null
+++ b/LibationWinForms/SortableBindingList2[T].cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LibationWinForms
+{
+ class SortableBindingList2 : BindingList where T : IObjectMemberComparable
+ {
+ private ObjectMemberComparer Comparer = new();
+
+ private bool isSorted;
+ private ListSortDirection listSortDirection;
+ private PropertyDescriptor propertyDescriptor;
+
+ public SortableBindingList2() : base(new List()) { }
+
+ public SortableBindingList2(IEnumerable enumeration) : base(new List(enumeration)) { }
+
+ protected override bool SupportsSortingCore => true;
+
+ protected override bool IsSortedCore => isSorted;
+
+ protected override PropertyDescriptor SortPropertyCore => propertyDescriptor;
+
+ protected override ListSortDirection SortDirectionCore => listSortDirection;
+
+ protected override bool SupportsSearchingCore => true;
+
+ protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
+ {
+ List itemsList = (List)Items;
+
+ Comparer.PropertyName = property.Name;
+ Comparer.Direction = direction;
+
+ itemsList.Sort(Comparer);
+
+ propertyDescriptor = property;
+ listSortDirection = direction;
+ isSorted = true;
+
+ OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
+ }
+
+ protected override void RemoveSortCore()
+ {
+ isSorted = false;
+ propertyDescriptor = base.SortPropertyCore;
+ listSortDirection = base.SortDirectionCore;
+
+ OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
+ }
+
+ protected override int FindCore(PropertyDescriptor property, object key)
+ {
+ int count = Count;
+ for (int i = 0; i < count; ++i)
+ {
+ T element = this[i];
+ if (property.GetValue(element).Equals(key))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+ }
+}