diff --git a/Source/AaxDecrypter/AudiobookDownloadBase.cs b/Source/AaxDecrypter/AudiobookDownloadBase.cs index ef16f7d5..04e901ed 100644 --- a/Source/AaxDecrypter/AudiobookDownloadBase.cs +++ b/Source/AaxDecrypter/AudiobookDownloadBase.cs @@ -140,11 +140,6 @@ namespace AaxDecrypter else FileUtility.SaferDelete(TempFilePath); } - else - { - FileUtility.SaferDelete(OutputFileName); - } - return success; } diff --git a/Source/AppScaffolding/LibationScaffolding.cs b/Source/AppScaffolding/LibationScaffolding.cs index d287190f..6bde3030 100644 --- a/Source/AppScaffolding/LibationScaffolding.cs +++ b/Source/AppScaffolding/LibationScaffolding.cs @@ -125,6 +125,15 @@ namespace AppScaffolding if (!config.Exists(nameof(config.AutoScan))) config.AutoScan = true; + + if (!config.Exists(nameof(config.GridColumnsVisibilities))) + config.GridColumnsVisibilities = new Dictionary(); + + if (!config.Exists(nameof(config.GridColumnsDisplayIndices))) + config.GridColumnsDisplayIndices = new Dictionary(); + + if (!config.Exists(nameof(config.GridColumnsWidths))) + config.GridColumnsWidths = new Dictionary(); } /// Initialize logging. Run after migration diff --git a/Source/AudibleUtilities/AudibleUtilities.csproj b/Source/AudibleUtilities/AudibleUtilities.csproj index e345a1ee..1b933a47 100644 --- a/Source/AudibleUtilities/AudibleUtilities.csproj +++ b/Source/AudibleUtilities/AudibleUtilities.csproj @@ -5,7 +5,7 @@ - + diff --git a/Source/DataLayer/EfClasses/Book.cs b/Source/DataLayer/EfClasses/Book.cs index 2dba71d5..63d3e7c3 100644 --- a/Source/DataLayer/EfClasses/Book.cs +++ b/Source/DataLayer/EfClasses/Book.cs @@ -34,6 +34,7 @@ namespace DataLayer // mutable public string PictureId { get; set; } + public string PictureLarge { get; set; } // book details public bool IsAbridged { get; private set; } diff --git a/Source/DataLayer/LibationContext.db b/Source/DataLayer/LibationContext.db deleted file mode 100644 index 7591b152..00000000 Binary files a/Source/DataLayer/LibationContext.db and /dev/null differ diff --git a/Source/DataLayer/Migrations/20220510175257_AddPictureIDLargeMigration.Designer.cs b/Source/DataLayer/Migrations/20220510175257_AddPictureIDLargeMigration.Designer.cs new file mode 100644 index 00000000..dae19073 --- /dev/null +++ b/Source/DataLayer/Migrations/20220510175257_AddPictureIDLargeMigration.Designer.cs @@ -0,0 +1,394 @@ +// +using System; +using DataLayer; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace DataLayer.Migrations +{ + [DbContext(typeof(LibationContext))] + [Migration("20220510175257_AddPictureIDLargeMigration")] + partial class AddPictureIDLargeMigration + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.4"); + + modelBuilder.Entity("DataLayer.Book", b => + { + b.Property("BookId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AudibleProductId") + .HasColumnType("TEXT"); + + b.Property("CategoryId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("DatePublished") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsAbridged") + .HasColumnType("INTEGER"); + + b.Property("LengthInMinutes") + .HasColumnType("INTEGER"); + + b.Property("Locale") + .HasColumnType("TEXT"); + + b.Property("PictureId") + .HasColumnType("TEXT"); + + b.Property("PictureLarge") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("BookId"); + + b.HasIndex("AudibleProductId"); + + b.HasIndex("CategoryId"); + + b.ToTable("Books"); + }); + + modelBuilder.Entity("DataLayer.BookContributor", b => + { + b.Property("BookId") + .HasColumnType("INTEGER"); + + b.Property("ContributorId") + .HasColumnType("INTEGER"); + + b.Property("Role") + .HasColumnType("INTEGER"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.HasKey("BookId", "ContributorId", "Role"); + + b.HasIndex("BookId"); + + b.HasIndex("ContributorId"); + + b.ToTable("BookContributor"); + }); + + modelBuilder.Entity("DataLayer.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AudibleCategoryId") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("ParentCategoryCategoryId") + .HasColumnType("INTEGER"); + + b.HasKey("CategoryId"); + + b.HasIndex("AudibleCategoryId"); + + b.HasIndex("ParentCategoryCategoryId"); + + b.ToTable("Categories"); + + b.HasData( + new + { + CategoryId = -1, + AudibleCategoryId = "", + Name = "" + }); + }); + + modelBuilder.Entity("DataLayer.Contributor", b => + { + b.Property("ContributorId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AudibleContributorId") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("ContributorId"); + + b.HasIndex("Name"); + + b.ToTable("Contributors"); + + b.HasData( + new + { + ContributorId = -1, + Name = "" + }); + }); + + modelBuilder.Entity("DataLayer.LibraryBook", b => + { + b.Property("BookId") + .HasColumnType("INTEGER"); + + b.Property("Account") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.HasKey("BookId"); + + b.ToTable("LibraryBooks"); + }); + + modelBuilder.Entity("DataLayer.Series", b => + { + b.Property("SeriesId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AudibleSeriesId") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("SeriesId"); + + b.HasIndex("AudibleSeriesId"); + + b.ToTable("Series"); + }); + + modelBuilder.Entity("DataLayer.SeriesBook", b => + { + b.Property("SeriesId") + .HasColumnType("INTEGER"); + + b.Property("BookId") + .HasColumnType("INTEGER"); + + b.Property("Order") + .HasColumnType("TEXT"); + + b.HasKey("SeriesId", "BookId"); + + b.HasIndex("BookId"); + + b.HasIndex("SeriesId"); + + b.ToTable("SeriesBook"); + }); + + modelBuilder.Entity("DataLayer.Book", b => + { + b.HasOne("DataLayer.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("DataLayer.Rating", "Rating", b1 => + { + b1.Property("BookId") + .HasColumnType("INTEGER"); + + b1.Property("OverallRating") + .HasColumnType("REAL"); + + b1.Property("PerformanceRating") + .HasColumnType("REAL"); + + b1.Property("StoryRating") + .HasColumnType("REAL"); + + b1.HasKey("BookId"); + + b1.ToTable("Books"); + + b1.WithOwner() + .HasForeignKey("BookId"); + }); + + b.OwnsMany("DataLayer.Supplement", "Supplements", b1 => + { + b1.Property("SupplementId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b1.Property("BookId") + .HasColumnType("INTEGER"); + + b1.Property("Url") + .HasColumnType("TEXT"); + + b1.HasKey("SupplementId"); + + b1.HasIndex("BookId"); + + b1.ToTable("Supplement"); + + b1.WithOwner("Book") + .HasForeignKey("BookId"); + + b1.Navigation("Book"); + }); + + b.OwnsOne("DataLayer.UserDefinedItem", "UserDefinedItem", b1 => + { + b1.Property("BookId") + .HasColumnType("INTEGER"); + + b1.Property("BookStatus") + .HasColumnType("INTEGER"); + + b1.Property("PdfStatus") + .HasColumnType("INTEGER"); + + b1.Property("Tags") + .HasColumnType("TEXT"); + + b1.HasKey("BookId"); + + b1.ToTable("UserDefinedItem", (string)null); + + b1.WithOwner("Book") + .HasForeignKey("BookId"); + + b1.OwnsOne("DataLayer.Rating", "Rating", b2 => + { + b2.Property("UserDefinedItemBookId") + .HasColumnType("INTEGER"); + + b2.Property("OverallRating") + .HasColumnType("REAL"); + + b2.Property("PerformanceRating") + .HasColumnType("REAL"); + + b2.Property("StoryRating") + .HasColumnType("REAL"); + + b2.HasKey("UserDefinedItemBookId"); + + b2.ToTable("UserDefinedItem"); + + b2.WithOwner() + .HasForeignKey("UserDefinedItemBookId"); + }); + + b1.Navigation("Book"); + + b1.Navigation("Rating"); + }); + + b.Navigation("Category"); + + b.Navigation("Rating"); + + b.Navigation("Supplements"); + + b.Navigation("UserDefinedItem"); + }); + + modelBuilder.Entity("DataLayer.BookContributor", b => + { + b.HasOne("DataLayer.Book", "Book") + .WithMany("ContributorsLink") + .HasForeignKey("BookId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DataLayer.Contributor", "Contributor") + .WithMany("BooksLink") + .HasForeignKey("ContributorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Book"); + + b.Navigation("Contributor"); + }); + + modelBuilder.Entity("DataLayer.Category", b => + { + b.HasOne("DataLayer.Category", "ParentCategory") + .WithMany() + .HasForeignKey("ParentCategoryCategoryId"); + + b.Navigation("ParentCategory"); + }); + + modelBuilder.Entity("DataLayer.LibraryBook", b => + { + b.HasOne("DataLayer.Book", "Book") + .WithOne() + .HasForeignKey("DataLayer.LibraryBook", "BookId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Book"); + }); + + modelBuilder.Entity("DataLayer.SeriesBook", b => + { + b.HasOne("DataLayer.Book", "Book") + .WithMany("SeriesLink") + .HasForeignKey("BookId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DataLayer.Series", "Series") + .WithMany("BooksLink") + .HasForeignKey("SeriesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Book"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("DataLayer.Book", b => + { + b.Navigation("ContributorsLink"); + + b.Navigation("SeriesLink"); + }); + + modelBuilder.Entity("DataLayer.Contributor", b => + { + b.Navigation("BooksLink"); + }); + + modelBuilder.Entity("DataLayer.Series", b => + { + b.Navigation("BooksLink"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Source/DataLayer/Migrations/20220510175257_AddPictureIDLargeMigration.cs b/Source/DataLayer/Migrations/20220510175257_AddPictureIDLargeMigration.cs new file mode 100644 index 00000000..10363132 --- /dev/null +++ b/Source/DataLayer/Migrations/20220510175257_AddPictureIDLargeMigration.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace DataLayer.Migrations +{ + public partial class AddPictureIDLargeMigration : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "PictureLarge", + table: "Books", + type: "TEXT", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "PictureLarge", + table: "Books"); + } + } +} diff --git a/Source/DataLayer/Migrations/LibationContextModelSnapshot.cs b/Source/DataLayer/Migrations/LibationContextModelSnapshot.cs index 5453c4a9..c198e3c0 100644 --- a/Source/DataLayer/Migrations/LibationContextModelSnapshot.cs +++ b/Source/DataLayer/Migrations/LibationContextModelSnapshot.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +#nullable disable + namespace DataLayer.Migrations { [DbContext(typeof(LibationContext))] @@ -13,8 +15,7 @@ namespace DataLayer.Migrations protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "5.0.10"); + modelBuilder.HasAnnotation("ProductVersion", "6.0.4"); modelBuilder.Entity("DataLayer.Book", b => { @@ -49,6 +50,9 @@ namespace DataLayer.Migrations b.Property("PictureId") .HasColumnType("TEXT"); + b.Property("PictureLarge") + .HasColumnType("TEXT"); + b.Property("Title") .HasColumnType("TEXT"); @@ -267,7 +271,7 @@ namespace DataLayer.Migrations b1.HasKey("BookId"); - b1.ToTable("UserDefinedItem"); + b1.ToTable("UserDefinedItem", (string)null); b1.WithOwner("Book") .HasForeignKey("BookId"); diff --git a/Source/DtoImporterService/BookImporter.cs b/Source/DtoImporterService/BookImporter.cs index cbb56d3b..bc69f382 100644 --- a/Source/DtoImporterService/BookImporter.cs +++ b/Source/DtoImporterService/BookImporter.cs @@ -164,6 +164,9 @@ namespace DtoImporterService // set/update book-specific info which may have changed if (item.PictureId is not null) book.PictureId = item.PictureId; + + if (item.PictureLarge is not null) + book.PictureLarge = item.PictureLarge; book.UpdateProductRating(item.Product_OverallStars, item.Product_PerformanceStars, item.Product_StoryStars); diff --git a/Source/FileLiberator/Processable.cs b/Source/FileLiberator/Processable.cs index 0c7743e7..56ca47a5 100644 --- a/Source/FileLiberator/Processable.cs +++ b/Source/FileLiberator/Processable.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using DataLayer; using Dinah.Core; using Dinah.Core.ErrorHandling; +using LibationFileManager; namespace FileLiberator { @@ -47,9 +48,38 @@ namespace FileLiberator = (await ProcessAsync(libraryBook)) ?? new StatusHandler { "Processable should never return a null status" }; + if (status.IsSuccess) + DownloadCoverArt(libraryBook); + return status; } + private void DownloadCoverArt(LibraryBook libraryBook) + { + var destinationDir = AudibleFileStorage.Audio.GetDestinationDirectory(libraryBook); + var coverPath = FileManager.FileUtility.GetValidFilename(System.IO.Path.Combine(destinationDir, "Cover.jpg"), "", true); + + if (System.IO.File.Exists(coverPath)) return; + + try + { + (string picId, PictureSize size) = libraryBook.Book.PictureLarge is null ? + (libraryBook.Book.PictureId, PictureSize.Native) : + (libraryBook.Book.PictureLarge, PictureSize.Native); + + var picBytes = PictureStorage.GetPictureSynchronously(new PictureDefinition(picId, size)); + + if (picBytes.Length > 0) + System.IO.File.WriteAllBytes(coverPath, picBytes); + } + catch (Exception ex) + { + //Failure to download cover art should not be + //considered a failure to download the book + Serilog.Log.Logger.Error(ex.Message); + } + } + public async Task TryProcessAsync(LibraryBook libraryBook) => Validate(libraryBook) ? await ProcessAsync(libraryBook) diff --git a/Source/LibationFileManager/Configuration.cs b/Source/LibationFileManager/Configuration.cs index 89ab5f9f..698a5a05 100644 --- a/Source/LibationFileManager/Configuration.cs +++ b/Source/LibationFileManager/Configuration.cs @@ -179,6 +179,27 @@ namespace LibationFileManager get => persistentDictionary.GetNonString(nameof(LameVBRQuality)); set => persistentDictionary.SetNonString(nameof(LameVBRQuality), value); } + + [Description("A Dictionary of GridView data property names and bool indicating its column's visibility in ProductsGrid")] + public Dictionary GridColumnsVisibilities + { + get => persistentDictionary.GetNonString>(nameof(GridColumnsVisibilities)); + set => persistentDictionary.SetNonString(nameof(GridColumnsVisibilities), value); + } + + [Description("A Dictionary of GridView data property names and int indicating its column's display index in ProductsGrid")] + public Dictionary GridColumnsDisplayIndices + { + get => persistentDictionary.GetNonString>(nameof(GridColumnsDisplayIndices)); + set => persistentDictionary.SetNonString(nameof(GridColumnsDisplayIndices), value); + } + + [Description("A Dictionary of GridView data property names and int indicating its column's width in ProductsGrid")] + public Dictionary GridColumnsWidths + { + get => persistentDictionary.GetNonString>(nameof(GridColumnsWidths)); + set => persistentDictionary.SetNonString(nameof(GridColumnsWidths), value); + } public enum BadBookAction { diff --git a/Source/LibationFileManager/PictureStorage.cs b/Source/LibationFileManager/PictureStorage.cs index 868e4e33..ba5cea1a 100644 --- a/Source/LibationFileManager/PictureStorage.cs +++ b/Source/LibationFileManager/PictureStorage.cs @@ -8,13 +8,13 @@ using System.Threading.Tasks; namespace LibationFileManager { - public enum PictureSize { _80x80 = 80, _300x300 = 300, _500x500 = 500 } + public enum PictureSize { Native, _80x80 = 80, _300x300 = 300, _500x500 = 500 } public class PictureCachedEventArgs : EventArgs { public PictureDefinition Definition { get; internal set; } public byte[] Picture { get; internal set; } } - public struct PictureDefinition + public struct PictureDefinition : IEquatable { public string PictureId { get; } public PictureSize Size { get; } @@ -24,6 +24,11 @@ namespace LibationFileManager PictureId = pictureId; Size = pictureSize; } + + public bool Equals(PictureDefinition other) + { + return PictureId == other.PictureId && Size == other.Size; + } } public static class PictureStorage { @@ -113,8 +118,8 @@ namespace LibationFileManager try { - var sz = (int)def.Size; - var bytes = imageDownloadClient.GetByteArrayAsync("ht" + $"tps://images-na.ssl-images-amazon.com/images/I/{def.PictureId}._SL{sz}_.jpg").Result; + var sizeStr = def.Size == PictureSize.Native ? "" : $"._SL{(int)def.Size}_"; + var bytes = imageDownloadClient.GetByteArrayAsync("ht" + $"tps://images-na.ssl-images-amazon.com/images/I/{def.PictureId}{sizeStr}.jpg").Result; // save image file. make sure to not save default image var path = getPath(def); diff --git a/Source/LibationWinForms/BookLiberation/BaseForms/LiberationBaseForm.cs b/Source/LibationWinForms/BookLiberation/BaseForms/LiberationBaseForm.cs index 691db3c9..03f5ba05 100644 --- a/Source/LibationWinForms/BookLiberation/BaseForms/LiberationBaseForm.cs +++ b/Source/LibationWinForms/BookLiberation/BaseForms/LiberationBaseForm.cs @@ -19,6 +19,7 @@ namespace LibationWinForms.BookLiberation.BaseForms //If this is the first form created, it will not exist until after execution //reaches inside the constructor (after base class has been initialized). Invoker = new SynchronizeInvoker(); + this.SetLibationIcon(); } public void RegisterFileLiberator(Streamable streamable, LogMe logMe = null) diff --git a/Source/LibationWinForms/BookLiberation/ProcessorAutomationController.cs b/Source/LibationWinForms/BookLiberation/ProcessorAutomationController.cs index 064b012e..dca83b84 100644 --- a/Source/LibationWinForms/BookLiberation/ProcessorAutomationController.cs +++ b/Source/LibationWinForms/BookLiberation/ProcessorAutomationController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using System.Windows.Forms; using DataLayer; diff --git a/Source/LibationWinForms/Dialogs/AccountsDialog.cs b/Source/LibationWinForms/Dialogs/AccountsDialog.cs index 3da3cdbd..14c67523 100644 --- a/Source/LibationWinForms/Dialogs/AccountsDialog.cs +++ b/Source/LibationWinForms/Dialogs/AccountsDialog.cs @@ -28,6 +28,7 @@ namespace LibationWinForms.Dialogs populateDropDown(); populateGridValues(); + this.SetLibationIcon(); } private void populateDropDown() diff --git a/Source/LibationWinForms/Dialogs/BookDetailsDialog.Designer.cs b/Source/LibationWinForms/Dialogs/BookDetailsDialog.Designer.cs index 9f57e610..2e51bc1a 100644 --- a/Source/LibationWinForms/Dialogs/BookDetailsDialog.Designer.cs +++ b/Source/LibationWinForms/Dialogs/BookDetailsDialog.Designer.cs @@ -205,7 +205,6 @@ this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "BookDetailsDialog"; - this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Book Details"; diff --git a/Source/LibationWinForms/Dialogs/BookDetailsDialog.cs b/Source/LibationWinForms/Dialogs/BookDetailsDialog.cs index 3e20b74b..89184b00 100644 --- a/Source/LibationWinForms/Dialogs/BookDetailsDialog.cs +++ b/Source/LibationWinForms/Dialogs/BookDetailsDialog.cs @@ -27,6 +27,7 @@ namespace LibationWinForms.Dialogs public BookDetailsDialog() { InitializeComponent(); + this.SetLibationIcon(); } public BookDetailsDialog(LibraryBook libraryBook) : this() { diff --git a/Source/LibationWinForms/Dialogs/EditQuickFilters.cs b/Source/LibationWinForms/Dialogs/EditQuickFilters.cs index 7d8f20ca..3d6eab63 100644 --- a/Source/LibationWinForms/Dialogs/EditQuickFilters.cs +++ b/Source/LibationWinForms/Dialogs/EditQuickFilters.cs @@ -26,6 +26,7 @@ namespace LibationWinForms.Dialogs dataGridView1.Columns[COL_Filter].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; populateGridValues(); + this.SetLibationIcon(); } private void populateGridValues() diff --git a/Source/LibationWinForms/Dialogs/EditTemplateDialog.Designer.cs b/Source/LibationWinForms/Dialogs/EditTemplateDialog.Designer.cs index deea82d3..592c285d 100644 --- a/Source/LibationWinForms/Dialogs/EditTemplateDialog.Designer.cs +++ b/Source/LibationWinForms/Dialogs/EditTemplateDialog.Designer.cs @@ -170,8 +170,10 @@ this.Controls.Add(this.templateTb); this.Controls.Add(this.cancelBtn); this.Controls.Add(this.saveBtn); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.MaximizeBox = false; + this.MinimizeBox = false; this.Name = "EditTemplateDialog"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Edit Template"; diff --git a/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs b/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs index a14066ba..734a49d4 100644 --- a/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs +++ b/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs @@ -28,7 +28,11 @@ namespace LibationWinForms.Dialogs private Templates template { get; } private string inputTemplateText { get; } - public EditTemplateDialog() => InitializeComponent(); + public EditTemplateDialog() + { + InitializeComponent(); + this.SetLibationIcon(); + } public EditTemplateDialog(Templates template, string inputTemplateText) : this() { this.template = ArgumentValidator.EnsureNotNull(template, nameof(template)); diff --git a/Source/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs b/Source/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs index ea2551ce..61974264 100644 --- a/Source/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs +++ b/Source/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs @@ -164,7 +164,7 @@ namespace LibationWinForms.Dialogs this.Controls.Add(this.btnRemoveBooks); this.Controls.Add(this._dataGridView); this.Name = "RemoveBooksDialog"; - this.Text = "RemoveBooksDialog"; + this.Text = "Remove Books from Libation's Database"; this.Shown += new System.EventHandler(this.RemoveBooksDialog_Shown); ((System.ComponentModel.ISupportInitialize)(this._dataGridView)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).EndInit(); diff --git a/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs b/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs index 9680e246..1f7e18d9 100644 --- a/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs +++ b/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs @@ -48,6 +48,7 @@ namespace LibationWinForms.Dialogs gridEntryBindingSource.DataSource = _removableGridEntries; _dataGridView.Enabled = false; + this.SetLibationIcon(); } private void _dataGridView_BindingContextChanged(object sender, EventArgs e) diff --git a/Source/LibationWinForms/Dialogs/ScanAccountsDialog.cs b/Source/LibationWinForms/Dialogs/ScanAccountsDialog.cs index 5ad47361..0ebd283d 100644 --- a/Source/LibationWinForms/Dialogs/ScanAccountsDialog.cs +++ b/Source/LibationWinForms/Dialogs/ScanAccountsDialog.cs @@ -17,6 +17,7 @@ namespace LibationWinForms.Dialogs _parent = parent; InitializeComponent(); + this.SetLibationIcon(); } private class listItem diff --git a/Source/LibationWinForms/Dialogs/SearchSyntaxDialog.Designer.cs b/Source/LibationWinForms/Dialogs/SearchSyntaxDialog.Designer.cs index 7a7f27d9..7600c226 100644 --- a/Source/LibationWinForms/Dialogs/SearchSyntaxDialog.Designer.cs +++ b/Source/LibationWinForms/Dialogs/SearchSyntaxDialog.Designer.cs @@ -113,7 +113,6 @@ this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "SearchSyntaxDialog"; - this.ShowIcon = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Filter options"; this.ResumeLayout(false); diff --git a/Source/LibationWinForms/Dialogs/SearchSyntaxDialog.cs b/Source/LibationWinForms/Dialogs/SearchSyntaxDialog.cs index ed897b11..d809f33f 100644 --- a/Source/LibationWinForms/Dialogs/SearchSyntaxDialog.cs +++ b/Source/LibationWinForms/Dialogs/SearchSyntaxDialog.cs @@ -14,6 +14,7 @@ namespace LibationWinForms.Dialogs label3.Text += "\r\n\r\n" + string.Join("\r\n", LibationSearchEngine.SearchEngine.GetSearchNumberFields()); label4.Text += "\r\n\r\n" + string.Join("\r\n", LibationSearchEngine.SearchEngine.GetSearchBoolFields()); label5.Text += "\r\n\r\n" + string.Join("\r\n", LibationSearchEngine.SearchEngine.GetSearchIdFields()); + this.SetLibationIcon(); } private void CloseBtn_Click(object sender, EventArgs e) => this.Close(); diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs index 6b45db4e..68cf9d6f 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs @@ -17,7 +17,6 @@ namespace LibationWinForms.Dialogs private void LameMatchSourceBRCbox_CheckedChanged(object sender, EventArgs e) { lameBitrateTb.Enabled = !LameMatchSourceBRCbox.Checked; - lameConstantBitrateCbox.Enabled = !LameMatchSourceBRCbox.Checked; } private void convertFormatRb_CheckedChanged(object sender, EventArgs e) diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs index 48cd06d2..2df343c7 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs @@ -944,8 +944,10 @@ this.Controls.Add(this.tabControl); this.Controls.Add(this.cancelBtn); this.Controls.Add(this.saveBtn); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.MaximizeBox = false; + this.MinimizeBox = false; this.Name = "SettingsDialog"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Edit Settings"; diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.cs index a0333608..6d106411 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.cs @@ -13,7 +13,11 @@ namespace LibationWinForms.Dialogs private Configuration config { get; } = Configuration.Instance; private Func desc { get; } = Configuration.GetDescription; - public SettingsDialog() => InitializeComponent(); + public SettingsDialog() + { + InitializeComponent(); + this.SetLibationIcon(); + } private void SettingsDialog_Load(object sender, EventArgs e) { diff --git a/Source/LibationWinForms/Form1.cs b/Source/LibationWinForms/Form1.cs index dac6d01a..b0d26cf1 100644 --- a/Source/LibationWinForms/Form1.cs +++ b/Source/LibationWinForms/Form1.cs @@ -262,8 +262,8 @@ namespace LibationWinForms .Where(a => a.LibraryScan) .ToArray(); - // in autoScan, new books SHALL NOT show dialog - await LibraryCommands.ImportAccountAsync(Login.WinformLoginChoiceEager.ApiExtendedFunc, accounts); + // in autoScan, new books SHALL NOT show dialog + await Invoke(async () => await LibraryCommands.ImportAccountAsync(Login.WinformLoginChoiceEager.ApiExtendedFunc, accounts)); }; // load init state to menu checkbox diff --git a/Source/LibationWinForms/FormSaveExtension.cs b/Source/LibationWinForms/FormSaveExtension.cs index cca421b7..22be5c73 100644 --- a/Source/LibationWinForms/FormSaveExtension.cs +++ b/Source/LibationWinForms/FormSaveExtension.cs @@ -7,6 +7,18 @@ namespace LibationWinForms { public static class FormSaveExtension { + static readonly Icon libationIcon; + static FormSaveExtension() + { + var resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); + libationIcon = (Icon)resources.GetObject("$this.Icon"); + } + + public static void SetLibationIcon(this Form form) + { + form.Icon = libationIcon; + } + public static void RestoreSizeAndLocation(this Form form, Configuration config) { FormSizeAndPosition savedState = config.GetNonString(form.Name); @@ -77,6 +89,7 @@ namespace LibationWinForms config.SetObject(form.Name, saveState); } + } class FormSizeAndPosition { diff --git a/Source/LibationWinForms/grid/DescriptionDisplay.Designer.cs b/Source/LibationWinForms/grid/DescriptionDisplay.Designer.cs new file mode 100644 index 00000000..96012e50 --- /dev/null +++ b/Source/LibationWinForms/grid/DescriptionDisplay.Designer.cs @@ -0,0 +1,69 @@ +namespace LibationWinForms +{ + partial class DescriptionDisplay + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.textBox1 = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox1.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.textBox1.Location = new System.Drawing.Point(5, 5); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + this.textBox1.Size = new System.Drawing.Size(540, 140); + this.textBox1.TabIndex = 0; + // + // DescriptionDisplay + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Highlight; + this.ClientSize = new System.Drawing.Size(550, 150); + this.Controls.Add(this.textBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "DescriptionDisplay"; + this.ShowInTaskbar = false; + this.Text = "DescriptionDisplay"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + } +} \ No newline at end of file diff --git a/Source/LibationWinForms/grid/DescriptionDisplay.cs b/Source/LibationWinForms/grid/DescriptionDisplay.cs new file mode 100644 index 00000000..3f95a92e --- /dev/null +++ b/Source/LibationWinForms/grid/DescriptionDisplay.cs @@ -0,0 +1,51 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Linq; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace LibationWinForms +{ + public partial class DescriptionDisplay : Form + { + private int borderThickness = 5; + + public int BorderThickness + { + get => borderThickness; + set + { + borderThickness = value; + textBox1.Location = new Point(borderThickness, borderThickness); + textBox1.Size = new Size(Width - 2 * borderThickness, Height - 2 * borderThickness); + } + } + public string DescriptionText { get => textBox1.Text; set => textBox1.Text = value; } + public Point SpawnLocation { get; set; } + public DescriptionDisplay() + { + InitializeComponent(); + textBox1.LostFocus += (_, _) => Close(); + Shown += DescriptionDisplay_Shown; + } + + private void DescriptionDisplay_Shown(object sender, EventArgs e) + { + textBox1.DeselectAll(); + HideCaret(textBox1.Handle); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + int lineCount = textBox1.GetLineFromCharIndex(int.MaxValue) + 2; + Height = Height - textBox1.Height + lineCount * TextRenderer.MeasureText("X", textBox1.Font).Height; + + Location = new Point(SpawnLocation.X, Math.Min(SpawnLocation.Y, Screen.PrimaryScreen.WorkingArea.Height - Height)); + } + + [DllImport("user32.dll")] + static extern bool HideCaret(IntPtr hWnd); + } +} diff --git a/Source/LibationWinForms/grid/DescriptionDisplay.resx b/Source/LibationWinForms/grid/DescriptionDisplay.resx new file mode 100644 index 00000000..f298a7be --- /dev/null +++ b/Source/LibationWinForms/grid/DescriptionDisplay.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/LibationWinForms/grid/GridEntry.cs b/Source/LibationWinForms/grid/GridEntry.cs index 04283952..ce9d552d 100644 --- a/Source/LibationWinForms/grid/GridEntry.cs +++ b/Source/LibationWinForms/grid/GridEntry.cs @@ -26,10 +26,16 @@ namespace LibationWinForms public string AudibleProductId => Book.AudibleProductId; [Browsable(false)] public LibraryBook LibraryBook { get; private set; } + [Browsable(false)] + public string LongDescription { get; private set; } #endregion #region Model properties exposed to the view private Image _cover; + + private DateTime lastStatusUpdate = default; + private LiberatedStatus _bookStatus; + private LiberatedStatus? _pdfStatus; public Image Cover { get => _cover; @@ -61,10 +67,21 @@ namespace LibationWinForms // these 2 values being in 1 field is the trick behind getting the liberated+pdf 'stoplight' icon to draw. See: LiberateDataGridViewImageButtonCell.Paint public (LiberatedStatus BookStatus, LiberatedStatus? PdfStatus) Liberate { - get => (LibraryCommands.Liberated_Status(LibraryBook.Book), LibraryCommands.Pdf_Status(LibraryBook.Book)); + get + { + //Cache these statuses for faster sorting. + if ((DateTime.Now - lastStatusUpdate).TotalSeconds > 2) + { + UpdateLiberatedStatus(notify: false); + lastStatusUpdate = DateTime.Now; + } + return (_bookStatus, _pdfStatus); + } set { + _bookStatus = value.BookStatus; + _pdfStatus = value.PdfStatus; LibraryBook.Book.UserDefinedItem.BookStatus = value.BookStatus; LibraryBook.Book.UserDefinedItem.PdfStatus = value.PdfStatus; } @@ -87,6 +104,7 @@ namespace LibationWinForms { DownloadInProgress = true; await BookLiberation.ProcessorAutomationController.BackupSingleBookAsync(LibraryBook); + UpdateLiberatedStatus(); } finally { @@ -131,7 +149,8 @@ namespace LibationWinForms Narrators = Book.NarratorNames; Category = string.Join(" > ", Book.CategoriesNames); Misc = GetMiscDisplay(libraryBook); - Description = GetDescriptionDisplay(Book); + LongDescription = GetDescriptionDisplay(Book); + Description = TrimTextToWord(LongDescription, 62); } UserDefinedItem.ItemChanged += UserDefinedItem_ItemChanged; @@ -212,6 +231,14 @@ namespace LibationWinForms Committed?.Invoke(this, null); } + private void UpdateLiberatedStatus(bool notify = true) + { + _bookStatus = LibraryCommands.Liberated_Status(LibraryBook.Book); + _pdfStatus = LibraryCommands.Pdf_Status(LibraryBook.Book); + if (notify) + NotifyPropertyChanged(nameof(Liberate)); + } + #endregion #region Data Sorting @@ -262,12 +289,16 @@ namespace LibationWinForms private static string GetDescriptionDisplay(Book book) { var doc = new HtmlAgilityPack.HtmlDocument(); - doc.LoadHtml(book?.Description ?? ""); - var noHtml = doc.DocumentNode.InnerText; + doc.LoadHtml(book?.Description?.Replace("

", "\r\n\r\n

") ?? ""); + return doc.DocumentNode.InnerText.Trim(); + } + + private static string TrimTextToWord(string text, int maxLength) + { return - noHtml.Length < 63 ? - noHtml : - noHtml.Substring(0, 60) + "..."; + text.Length <= maxLength ? + text : + text.Substring(0, maxLength - 3) + "..."; } /// diff --git a/Source/LibationWinForms/grid/ProductsGrid.Designer.cs b/Source/LibationWinForms/grid/ProductsGrid.Designer.cs index 689bd848..b3eaecd5 100644 --- a/Source/LibationWinForms/grid/ProductsGrid.Designer.cs +++ b/Source/LibationWinForms/grid/ProductsGrid.Designer.cs @@ -28,195 +28,207 @@ /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); - this.gridEntryBindingSource = new LibationWinForms.SyncBindingSource(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.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(); - 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.AllowUserToResizeRows = 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.dataGridViewTextBoxColumn8, - this.dataGridViewTextBoxColumn9, - this.dataGridViewTextBoxColumn10, - 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(1510, 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 = 75; - // - // 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.Width = 200; - // - // 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; - this.dataGridViewTextBoxColumn4.ToolTipText = "Recording Length"; - // - // 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; - // - // ProductRating - // - this.dataGridViewTextBoxColumn8.DataPropertyName = "ProductRating"; - this.dataGridViewTextBoxColumn8.HeaderText = "Product Rating"; - this.dataGridViewTextBoxColumn8.Name = "ProductRating"; - this.dataGridViewTextBoxColumn8.ReadOnly = true; - this.dataGridViewTextBoxColumn8.Width = 108; - // - // PurchaseDate - // - this.dataGridViewTextBoxColumn9.DataPropertyName = "PurchaseDate"; - this.dataGridViewTextBoxColumn9.HeaderText = "Purchase Date"; - this.dataGridViewTextBoxColumn9.Name = "PurchaseDate"; - this.dataGridViewTextBoxColumn9.ReadOnly = true; - // - // MyRating - // - this.dataGridViewTextBoxColumn10.DataPropertyName = "MyRating"; - this.dataGridViewTextBoxColumn10.HeaderText = "My Rating"; - this.dataGridViewTextBoxColumn10.Name = "MyRating"; - this.dataGridViewTextBoxColumn10.ReadOnly = true; - this.dataGridViewTextBoxColumn10.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 = "Tags and Details"; - 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(1510, 380); - ((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 LibationWinForms.SyncBindingSource(this.components); + this.gridEntryDataGridView = new System.Windows.Forms.DataGridView(); + this.liberateGVColumn = new LibationWinForms.LiberateDataGridViewImageButtonColumn(); + this.coverGVColumn = new System.Windows.Forms.DataGridViewImageColumn(); + this.titleGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.authorsGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.narratorsGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.lengthGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.seriesGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.descriptionGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.categoryGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.productRatingGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.purchaseDateGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.myRatingGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.miscGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.tagAndDetailsGVColumn = new LibationWinForms.EditTagsDataGridViewImageButtonColumn(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + ((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.AllowUserToOrderColumns = true; + this.gridEntryDataGridView.AllowUserToResizeRows = false; + this.gridEntryDataGridView.AutoGenerateColumns = false; + this.gridEntryDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.gridEntryDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.liberateGVColumn, + this.coverGVColumn, + this.titleGVColumn, + this.authorsGVColumn, + this.narratorsGVColumn, + this.lengthGVColumn, + this.seriesGVColumn, + this.descriptionGVColumn, + this.categoryGVColumn, + this.productRatingGVColumn, + this.purchaseDateGVColumn, + this.myRatingGVColumn, + this.miscGVColumn, + this.tagAndDetailsGVColumn}); + this.gridEntryDataGridView.ContextMenuStrip = this.contextMenuStrip1; + 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(1510, 380); + this.gridEntryDataGridView.TabIndex = 0; + this.gridEntryDataGridView.CellToolTipTextNeeded += new System.Windows.Forms.DataGridViewCellToolTipTextNeededEventHandler(this.gridEntryDataGridView_CellToolTipTextNeeded); + this.gridEntryDataGridView.ColumnDisplayIndexChanged += new System.Windows.Forms.DataGridViewColumnEventHandler(this.gridEntryDataGridView_ColumnDisplayIndexChanged); + this.gridEntryDataGridView.ColumnWidthChanged += new System.Windows.Forms.DataGridViewColumnEventHandler(this.gridEntryDataGridView_ColumnWidthChanged); + // + // liberateGVColumn + // + this.liberateGVColumn.DataPropertyName = "Liberate"; + this.liberateGVColumn.HeaderText = "Liberate"; + this.liberateGVColumn.Name = "liberateGVColumn"; + this.liberateGVColumn.ReadOnly = true; + this.liberateGVColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.liberateGVColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic; + this.liberateGVColumn.Width = 75; + // + // coverGVColumn + // + this.coverGVColumn.DataPropertyName = "Cover"; + this.coverGVColumn.HeaderText = "Cover"; + this.coverGVColumn.Name = "coverGVColumn"; + this.coverGVColumn.ReadOnly = true; + this.coverGVColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.coverGVColumn.ToolTipText = "Cover Art"; + this.coverGVColumn.Width = 80; + // + // titleGVColumn + // + this.titleGVColumn.DataPropertyName = "Title"; + this.titleGVColumn.HeaderText = "Title"; + this.titleGVColumn.Name = "titleGVColumn"; + this.titleGVColumn.ReadOnly = true; + this.titleGVColumn.Width = 200; + // + // authorsGVColumn + // + this.authorsGVColumn.DataPropertyName = "Authors"; + this.authorsGVColumn.HeaderText = "Authors"; + this.authorsGVColumn.Name = "authorsGVColumn"; + this.authorsGVColumn.ReadOnly = true; + // + // narratorsGVColumn + // + this.narratorsGVColumn.DataPropertyName = "Narrators"; + this.narratorsGVColumn.HeaderText = "Narrators"; + this.narratorsGVColumn.Name = "narratorsGVColumn"; + this.narratorsGVColumn.ReadOnly = true; + // + // lengthGVColumn + // + this.lengthGVColumn.DataPropertyName = "Length"; + this.lengthGVColumn.HeaderText = "Length"; + this.lengthGVColumn.Name = "lengthGVColumn"; + this.lengthGVColumn.ReadOnly = true; + this.lengthGVColumn.ToolTipText = "Recording Length"; + // + // seriesGVColumn + // + this.seriesGVColumn.DataPropertyName = "Series"; + this.seriesGVColumn.HeaderText = "Series"; + this.seriesGVColumn.Name = "seriesGVColumn"; + this.seriesGVColumn.ReadOnly = true; + // + // descriptionGVColumn + // + this.descriptionGVColumn.DataPropertyName = "Description"; + this.descriptionGVColumn.HeaderText = "Description"; + this.descriptionGVColumn.Name = "descriptionGVColumn"; + this.descriptionGVColumn.ReadOnly = true; + this.descriptionGVColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False; + // + // categoryGVColumn + // + this.categoryGVColumn.DataPropertyName = "Category"; + this.categoryGVColumn.HeaderText = "Category"; + this.categoryGVColumn.Name = "categoryGVColumn"; + this.categoryGVColumn.ReadOnly = true; + // + // productRatingGVColumn + // + this.productRatingGVColumn.DataPropertyName = "ProductRating"; + this.productRatingGVColumn.HeaderText = "Product Rating"; + this.productRatingGVColumn.Name = "productRatingGVColumn"; + this.productRatingGVColumn.ReadOnly = true; + this.productRatingGVColumn.Width = 108; + // + // purchaseDateGVColumn + // + this.purchaseDateGVColumn.DataPropertyName = "PurchaseDate"; + this.purchaseDateGVColumn.HeaderText = "Purchase Date"; + this.purchaseDateGVColumn.Name = "purchaseDateGVColumn"; + this.purchaseDateGVColumn.ReadOnly = true; + // + // myRatingGVColumn + // + this.myRatingGVColumn.DataPropertyName = "MyRating"; + this.myRatingGVColumn.HeaderText = "My Rating"; + this.myRatingGVColumn.Name = "myRatingGVColumn"; + this.myRatingGVColumn.ReadOnly = true; + this.myRatingGVColumn.Width = 108; + // + // miscGVColumn + // + this.miscGVColumn.DataPropertyName = "Misc"; + this.miscGVColumn.HeaderText = "Misc"; + this.miscGVColumn.Name = "miscGVColumn"; + this.miscGVColumn.ReadOnly = true; + this.miscGVColumn.Width = 135; + // + // tagAndDetailsGVColumn + // + this.tagAndDetailsGVColumn.DataPropertyName = "DisplayTags"; + this.tagAndDetailsGVColumn.HeaderText = "Tags and Details"; + this.tagAndDetailsGVColumn.Name = "tagAndDetailsGVColumn"; + this.tagAndDetailsGVColumn.ReadOnly = true; + this.tagAndDetailsGVColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.tagAndDetailsGVColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic; + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(61, 4); + // + // 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(1510, 380); + ((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).EndInit(); + this.ResumeLayout(false); } @@ -224,19 +236,20 @@ private LibationWinForms.SyncBindingSource gridEntryBindingSource; private System.Windows.Forms.DataGridView gridEntryDataGridView; - 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 dataGridViewTextBoxColumn8; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn9; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn10; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn11; - private EditTagsDataGridViewImageButtonColumn dataGridViewImageButtonBoxColumn2; - } + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private LiberateDataGridViewImageButtonColumn liberateGVColumn; + private System.Windows.Forms.DataGridViewImageColumn coverGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn titleGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn authorsGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn narratorsGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn lengthGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn seriesGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn descriptionGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn categoryGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn productRatingGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn purchaseDateGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn myRatingGVColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn miscGVColumn; + private EditTagsDataGridViewImageButtonColumn tagAndDetailsGVColumn; + } } diff --git a/Source/LibationWinForms/grid/ProductsGrid.cs b/Source/LibationWinForms/grid/ProductsGrid.cs index d5c0dc52..239288b6 100644 --- a/Source/LibationWinForms/grid/ProductsGrid.cs +++ b/Source/LibationWinForms/grid/ProductsGrid.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; @@ -8,6 +9,7 @@ using Dinah.Core; using Dinah.Core.DataBinding; using Dinah.Core.Threading; using Dinah.Core.Windows.Forms; +using LibationFileManager; using LibationWinForms.Dialogs; namespace LibationWinForms @@ -44,6 +46,7 @@ namespace LibationWinForms EnableDoubleBuffering(); } + private void EnableDoubleBuffering() { var propertyInfo = _dataGridView.GetType().GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); @@ -56,20 +59,36 @@ namespace LibationWinForms private async void DataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e) { // handle grid button click: https://stackoverflow.com/a/13687844 - if (e.RowIndex < 0 || _dataGridView.Columns[e.ColumnIndex] is not DataGridViewButtonColumn) + if (e.RowIndex < 0) return; - var liveGridEntry = getGridEntry(e.RowIndex); + var clickedColumn = _dataGridView.Columns[e.ColumnIndex]; - switch (_dataGridView.Columns[e.ColumnIndex].DataPropertyName) + if (clickedColumn == liberateGVColumn) + await Liberate_Click(getGridEntry(e.RowIndex)); + else if (clickedColumn == tagAndDetailsGVColumn) + Details_Click(getGridEntry(e.RowIndex)); + else if (clickedColumn == descriptionGVColumn) + Description_Click(getGridEntry(e.RowIndex), _dataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false)); + } + + private void Description_Click(GridEntry liveGridEntry, Rectangle cellDisplay) + { + var displayWindow = new DescriptionDisplay { - case nameof(liveGridEntry.Liberate): - await Liberate_Click(liveGridEntry); - break; - case nameof(liveGridEntry.DisplayTags): - Details_Click(liveGridEntry); - break; + SpawnLocation = PointToScreen(cellDisplay.Location + new Size(cellDisplay.Width, 0)), + DescriptionText = liveGridEntry.LongDescription, + BorderThickness = 2, + }; + + void CloseWindow (object o, EventArgs e) + { + displayWindow.Close(); } + + _dataGridView.Scroll += CloseWindow; + displayWindow.FormClosed += (_,_) => _dataGridView.Scroll -= CloseWindow; + displayWindow.Show(this); } private static async Task Liberate_Click(GridEntry liveGridEntry) @@ -79,7 +98,7 @@ namespace LibationWinForms // liberated: open explorer to file if (libraryBook.Book.Audio_Exists) { - var filePath = LibationFileManager.AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); + var filePath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); if (!Go.To.File(filePath)) { var suffix = string.IsNullOrWhiteSpace(filePath) ? "" : $":\r\n{filePath}"; @@ -225,5 +244,108 @@ namespace LibationWinForms #region DataGridView Macro private GridEntry getGridEntry(int rowIndex) => _dataGridView.GetBoundItem(rowIndex); #endregion + + #region Column Customizations + + protected override void OnVisibleChanged(EventArgs e) + { + contextMenuStrip1.Items.Add(new ToolStripLabel("Show / Hide Columns")); + contextMenuStrip1.Items.Add(new ToolStripSeparator()); + + //Restore Grid Display Settings + var config = Configuration.Instance; + var gridColumnsVisibilities = config.GridColumnsVisibilities; + var gridColumnsWidths = config.GridColumnsWidths; + var displayIndices = config.GridColumnsDisplayIndices; + + var cmsKiller = new ContextMenuStrip(); + + foreach (DataGridViewColumn column in _dataGridView.Columns) + { + var itemName = column.DataPropertyName; + var visible = gridColumnsVisibilities.GetValueOrDefault(itemName, true); + + var menuItem = new ToolStripMenuItem() + { + Text = column.HeaderText, + Checked = visible, + Tag = itemName + }; + menuItem.Click += HideMenuItem_Click; + contextMenuStrip1.Items.Add(menuItem); + + column.Width = gridColumnsWidths.GetValueOrDefault(itemName, column.Width); + column.MinimumWidth = 10; + column.HeaderCell.ContextMenuStrip = contextMenuStrip1; + column.Visible = visible; + + //Setting a default ContextMenuStrip will allow the columns to handle the + //Show() event so it is not passed up to the _dataGridView.ContextMenuStrip. + //This allows the ContextMenuStrip to be shown if right-clicking in the gray + //background of _dataGridView but not shown if right-clicking inside cells. + column.ContextMenuStrip = cmsKiller; + } + + //We must set DisplayIndex properties in ascending order + foreach (var itemName in displayIndices.OrderBy(i => i.Value).Select(i => i.Key)) + { + var column = _dataGridView.Columns + .Cast() + .Single(c => c.DataPropertyName == itemName); + + column.DisplayIndex = displayIndices.GetValueOrDefault(itemName, column.Index); + } + + base.OnVisibleChanged(e); + } + + private void gridEntryDataGridView_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e) + { + var config = Configuration.Instance; + + var dictionary = config.GridColumnsDisplayIndices; + dictionary[e.Column.DataPropertyName] = e.Column.DisplayIndex; + config.GridColumnsDisplayIndices = dictionary; + } + + private void gridEntryDataGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e) + { + var config = Configuration.Instance; + + var dictionary = config.GridColumnsWidths; + dictionary[e.Column.DataPropertyName] = e.Column.Width; + config.GridColumnsWidths = dictionary; + } + + private void HideMenuItem_Click(object sender, EventArgs e) + { + var menuItem = sender as ToolStripMenuItem; + var propertyName = menuItem.Tag as string; + + var column = _dataGridView.Columns + .Cast() + .FirstOrDefault(c => c.DataPropertyName == propertyName); + + if (column != null) + { + var visible = menuItem.Checked; + menuItem.Checked = !visible; + column.Visible = !visible; + + var config = Configuration.Instance; + + var dictionary = config.GridColumnsVisibilities; + dictionary[propertyName] = column.Visible; + config.GridColumnsVisibilities = dictionary; + } + } + + private void gridEntryDataGridView_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e) + { + if (e.ColumnIndex == descriptionGVColumn.Index) + e.ToolTipText = "Click to see full description"; + } + + #endregion } } diff --git a/Source/LibationWinForms/grid/ProductsGrid.resx b/Source/LibationWinForms/grid/ProductsGrid.resx index 6ee0745a..8a560af5 100644 --- a/Source/LibationWinForms/grid/ProductsGrid.resx +++ b/Source/LibationWinForms/grid/ProductsGrid.resx @@ -1,5 +1,4 @@ - - + @@ -61,4 +60,10 @@ 17, 17 + + 197, 17 + + + 81 + \ No newline at end of file