From 5ca0d2a3997c15e1864e0a4380046bddd1456b39 Mon Sep 17 00:00:00 2001 From: Robert McRackan Date: Tue, 13 Dec 2022 15:32:33 -0500 Subject: [PATCH] New feature #406 : Right Click Menu for Stop-Light Icon (Chardonnay UI) --- Source/LibationAvalonia/AvaloniaUtils.cs | 21 ++++- .../LibationAvalonia/ViewModels/GridEntry.cs | 2 +- .../ViewModels/ProductsDisplayViewModel.cs | 2 +- .../Views/MainWindow/MainWindow.axaml.cs | 4 +- .../Views/ProductsDisplay.axaml.cs | 74 ++++++++++++--- .../LibationWinForms/GridView/ProductsGrid.cs | 89 +++++++++---------- 6 files changed, 131 insertions(+), 61 deletions(-) diff --git a/Source/LibationAvalonia/AvaloniaUtils.cs b/Source/LibationAvalonia/AvaloniaUtils.cs index 3baee64e..66b4935d 100644 --- a/Source/LibationAvalonia/AvaloniaUtils.cs +++ b/Source/LibationAvalonia/AvaloniaUtils.cs @@ -1,4 +1,5 @@ -using Avalonia.Media; +using Avalonia.Controls; +using Avalonia.Media; using Avalonia.Threading; using System; using System.Threading; @@ -16,5 +17,23 @@ namespace LibationAvalonia return brush; return defaultBrush; } + + public static Window GetParentWindow(this IControl control) + { + Window window = null; + + var p = control.Parent; + while (p != null) + { + if (p is Window) + { + window = (Window)p; + break; + } + p = p.Parent; + } + + return window; + } } } diff --git a/Source/LibationAvalonia/ViewModels/GridEntry.cs b/Source/LibationAvalonia/ViewModels/GridEntry.cs index ec30d49f..503965be 100644 --- a/Source/LibationAvalonia/ViewModels/GridEntry.cs +++ b/Source/LibationAvalonia/ViewModels/GridEntry.cs @@ -26,7 +26,7 @@ namespace LibationAvalonia.ViewModels [Browsable(false)] public string LongDescription { get; protected set; } [Browsable(false)] public abstract DateTime DateAdded { get; } [Browsable(false)] public int ListIndex { get; set; } - [Browsable(false)] protected Book Book => LibraryBook.Book; + [Browsable(false)] public Book Book => LibraryBook.Book; #region Model properties exposed to the view diff --git a/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs b/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs index 5a86e605..8f12349a 100644 --- a/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs +++ b/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs @@ -53,7 +53,7 @@ namespace LibationAvalonia.ViewModels /// /// Call when there's been a change to the library /// - public async Task DisplayBooks(List dbBooks) + public async Task DisplayBooksAsync(List dbBooks) { try { diff --git a/Source/LibationAvalonia/Views/MainWindow/MainWindow.axaml.cs b/Source/LibationAvalonia/Views/MainWindow/MainWindow.axaml.cs index 788a189c..1a8d67f0 100644 --- a/Source/LibationAvalonia/Views/MainWindow/MainWindow.axaml.cs +++ b/Source/LibationAvalonia/Views/MainWindow/MainWindow.axaml.cs @@ -54,7 +54,7 @@ namespace LibationAvalonia.Views { this.LibraryLoaded += MainWindow_LibraryLoaded; - LibraryCommands.LibrarySizeChanged += async (_, _) => await _viewModel.ProductsDisplay.DisplayBooks(DbContexts.GetLibrary_Flat_NoTracking(includeParents: true)); + LibraryCommands.LibrarySizeChanged += async (_, _) => await _viewModel.ProductsDisplay.DisplayBooksAsync(DbContexts.GetLibrary_Flat_NoTracking(includeParents: true)); Closing += (_, _) => this.SaveSizeAndLocation(Configuration.Instance); } Opened += MainWindow_Opened; @@ -178,7 +178,7 @@ namespace LibationAvalonia.Views if (QuickFilters.UseDefault) await performFilter(QuickFilters.Filters.FirstOrDefault()); - await _viewModel.ProductsDisplay.DisplayBooks(dbBooks); + await _viewModel.ProductsDisplay.DisplayBooksAsync(dbBooks); } private void InitializeComponent() diff --git a/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs b/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs index ac57d42b..fd9810a2 100644 --- a/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs +++ b/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs @@ -1,16 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; using ApplicationServices; using Avalonia; +using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Markup.Xaml; using DataLayer; using FileLiberator; -using LibationFileManager; -using LibationAvalonia.ViewModels; -using LibationAvalonia.Dialogs; -using System; -using System.Collections.Generic; -using System.Linq; using LibationAvalonia.Controls; +using LibationAvalonia.Dialogs; +using LibationAvalonia.ViewModels; +using LibationFileManager; namespace LibationAvalonia.Views { @@ -41,7 +42,7 @@ namespace LibationAvalonia.Views }; var pdvm = new ProductsDisplayViewModel(); - pdvm.DisplayBooks(sampleEntries); + pdvm.DisplayBooksAsync(sampleEntries); DataContext = pdvm; return; @@ -74,11 +75,64 @@ namespace LibationAvalonia.Views #region Cell Context Menu public void ProductsGrid_CellContextMenuStripNeeded(object sender, DataGridCellContextMenuStripNeededEventArgs args) - { - if (args.Column.SortMemberPath == "Liberate") + { + // stop light + if (args.Column.SortMemberPath == "Liberate") { + var entry = args.GridEntry; - } + if (entry.IsSeries) + return; + + var setDownloadMenuItem = new MenuItem() + { + Header = "_Set Download status to 'Downloaded'", + IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated + }; + setDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.Liberated); + + var setNotDownloadMenuItem = new MenuItem() + { + Header = "_Set Download status to 'Not Downloaded'", + IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated + }; + setNotDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.NotLiberated); + + var removeMenuItem = new MenuItem() { Header = "_Remove from library" }; + removeMenuItem.Click += (_, __) => LibraryCommands.RemoveBook(entry.AudibleProductId); + + var locateFileMenuItem = new MenuItem() { Header = "_Locate file..." }; + locateFileMenuItem.Click += async (_, __) => + { + try + { + var openFileDialog = new OpenFileDialog() + { + Title = $"Locate the audio file for '{entry.Book.Title}'", + Filters = new() { new() { Name = "All files (*.*)", Extensions = new() { "|*.*" } } }, + AllowMultiple= false + }; + var filePaths = await openFileDialog.ShowAsync(this.GetParentWindow()); + var filePath = filePaths.SingleOrDefault(); + + if (!string.IsNullOrWhiteSpace(filePath)) + FilePathCache.Insert(entry.AudibleProductId, filePath); + } + catch (Exception ex) + { + var msg = "Error saving book's location"; + await MessageBox.ShowAdminAlert(null, msg, msg, ex); + } + }; + + args.ContextMenuItems.AddRange(new[] + { + setDownloadMenuItem, + setNotDownloadMenuItem, + removeMenuItem, + locateFileMenuItem + }); + } else { // any non-stop light column diff --git a/Source/LibationWinForms/GridView/ProductsGrid.cs b/Source/LibationWinForms/GridView/ProductsGrid.cs index 4064eb7a..e81b8376 100644 --- a/Source/LibationWinForms/GridView/ProductsGrid.cs +++ b/Source/LibationWinForms/GridView/ProductsGrid.cs @@ -136,55 +136,52 @@ namespace LibationWinForms.GridView if (entry.IsSeries) return; - var stopLightContextMenu = new ContextMenuStrip(); - e.ContextMenuStrip = stopLightContextMenu; + var setDownloadMenuItem = new ToolStripMenuItem() { - var menuItem = new ToolStripMenuItem() - { - Text = "Set Download status to 'Downloaded'", - Enabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated - }; - menuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.Liberated); - stopLightContextMenu.Items.Add(menuItem); - } + Text = "Set Download status to 'Downloaded'", + Enabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated + }; + setDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.Liberated); + + var setNotDownloadMenuItem = new ToolStripMenuItem() { - var menuItem = new ToolStripMenuItem() + Text = "Set Download status to 'Not Downloaded'", + Enabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated + }; + setNotDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.NotLiberated); + + var removeMenuItem = new ToolStripMenuItem() { Text = "Remove from library" }; + removeMenuItem.Click += (_, __) => LibraryCommands.RemoveBook(entry.AudibleProductId); + + var locateFileMenuItem = new ToolStripMenuItem() { Text = "Locate file..." }; + locateFileMenuItem.Click += (_, __) => + { + try { - Text = "Set Download status to 'Not Downloaded'", - Enabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated - }; - menuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.NotLiberated); - stopLightContextMenu.Items.Add(menuItem); - } - { - var menuItem = new ToolStripMenuItem() { Text = "Remove from library" }; - menuItem.Click += (_, __) => LibraryCommands.RemoveBook(entry.AudibleProductId); - stopLightContextMenu.Items.Add(menuItem); - } - { - var menuItem = new ToolStripMenuItem() { Text = "Locate file..." }; - menuItem.Click += (_, __) => - { - try - { - var openFileDialog = new OpenFileDialog - { - Title = $"Locate the audiofile for '{entry.Book.Title}'", - Filter = "All files (*.*)|*.*", - FilterIndex = 1 - }; - if (openFileDialog.ShowDialog() == DialogResult.OK) - FilePathCache.Insert(entry.AudibleProductId, openFileDialog.FileName); - } - catch (Exception ex) - { - var msg = "Error saving book's location"; - MessageBoxLib.ShowAdminAlert(this, msg, msg, ex); - } - }; - stopLightContextMenu.Items.Add(menuItem); - } - } + var openFileDialog = new OpenFileDialog + { + Title = $"Locate the audio file for '{entry.Book.Title}'", + Filter = "All files (*.*)|*.*", + FilterIndex = 1 + }; + if (openFileDialog.ShowDialog() == DialogResult.OK) + FilePathCache.Insert(entry.AudibleProductId, openFileDialog.FileName); + } + catch (Exception ex) + { + var msg = "Error saving book's location"; + MessageBoxLib.ShowAdminAlert(this, msg, msg, ex); + } + }; + + var stopLightContextMenu = new ContextMenuStrip(); + stopLightContextMenu.Items.Add(setDownloadMenuItem); + stopLightContextMenu.Items.Add(setNotDownloadMenuItem); + stopLightContextMenu.Items.Add(removeMenuItem); + stopLightContextMenu.Items.Add(locateFileMenuItem); + + e.ContextMenuStrip = stopLightContextMenu; + } private GridEntry getGridEntry(int rowIndex) => gridEntryDataGridView.GetBoundItem(rowIndex);