Make winforms book details and search syntax dialogs nonmodal

Match Chardonnay behavior
This commit is contained in:
MBucari
2025-12-01 20:56:05 -07:00
parent c34b1e752e
commit 4bd491f5b9
8 changed files with 100 additions and 32 deletions

View File

@@ -18,6 +18,18 @@ namespace LibationWinForms
}
}
public int SelectionStart
{
get => textBox1.SelectionStart;
set => textBox1.SelectionStart = value;
}
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
textBox1.Focus();
}
public ClearableTextBox()
{
InitializeComponent();

View File

@@ -20,8 +20,7 @@ namespace LibationWinForms.Dialogs
public LiberatedStatus BookLiberatedStatus { get; private set; }
public LiberatedStatus? PdfLiberatedStatus { get; private set; }
private LibraryBook _libraryBook { get; }
private Book Book => _libraryBook.Book;
private Book Book => LibraryBook.Book;
public BookDetailsDialog()
{
@@ -29,16 +28,23 @@ namespace LibationWinForms.Dialogs
this.SetLibationIcon();
audibleLink.SetLinkLabelColors();
}
public BookDetailsDialog(LibraryBook libraryBook) : this()
public LibraryBook LibraryBook
{
_libraryBook = ArgumentValidator.EnsureNotNull(libraryBook, nameof(libraryBook));
initDetails();
initTags();
initLiberated();
get => field;
set
{
field = value;
initDetails();
initTags();
initLiberated();
}
}
// 1st draft: lazily cribbed from GridEntry.ctor()
private void initDetails()
{
audibleLink.LinkVisited = false;
this.Text = Book.TitleWithSubtitle;
dolbyAtmosPb.Visible = Book.IsSpatial;
dolbyAtmosPb.Image = Application.IsDarkModeEnabled ? Properties.Resources.Dolby_Atmos_Vertical_80_dark : Properties.Resources.Dolby_Atmos_Vertical_80;
@@ -53,7 +59,7 @@ namespace LibationWinForms.Dialogs
Narrator(s): {Book.NarratorNames}
Length: {(Book.LengthInMinutes == 0 ? "" : $"{Book.LengthInMinutes / 60} hr {Book.LengthInMinutes % 60} min")}
Category: {string.Join(", ", Book.LowestCategoryNames())}
Purchase Date: {_libraryBook.DateAdded:d}
Purchase Date: {LibraryBook.DateAdded:d}
Language: {Book.Language}
Audible ID: {Book.AudibleProductId}
""";
@@ -137,7 +143,7 @@ namespace LibationWinForms.Dialogs
private void audibleLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
var locale = AudibleApi.Localization.Get(_libraryBook.Book.Locale);
var locale = AudibleApi.Localization.Get(Book.Locale);
var link = $"https://www.audible.{locale.TopDomain}/pd/{Book.AudibleProductId}";
Go.To.Url(link);
e.Link.Visited = true;

View File

@@ -149,6 +149,7 @@ namespace LibationWinForms.Dialogs
templateTb.Text = text.Insert(selStart, itemText);
templateTb.SelectionStart = selStart + itemText.Length;
templateTb.Focus();
}
private void llblGoToWiki_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)

View File

@@ -84,7 +84,7 @@
label3.Location = new System.Drawing.Point(4, 18);
label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
label3.Name = "label3";
label3.Size = new System.Drawing.Size(218, 120);
label3.Size = new System.Drawing.Size(218, 150);
label3.TabIndex = 2;
label3.Text = resources.GetString("label3.Text");
//
@@ -155,6 +155,7 @@
lboxIdFields.Name = "lboxIdFields";
lboxIdFields.Size = new System.Drawing.Size(220, 305);
lboxIdFields.TabIndex = 0;
lboxIdFields.DoubleClick += lboxFields_DoubleClick;
//
// label9
//
@@ -194,6 +195,7 @@
lboxBoolFields.Name = "lboxBoolFields";
lboxBoolFields.Size = new System.Drawing.Size(220, 365);
lboxBoolFields.TabIndex = 0;
lboxBoolFields.DoubleClick += lboxFields_DoubleClick;
//
// label8
//
@@ -229,10 +231,11 @@
//
lboxNumberFields.Dock = System.Windows.Forms.DockStyle.Fill;
lboxNumberFields.FormattingEnabled = true;
lboxNumberFields.Location = new System.Drawing.Point(3, 141);
lboxNumberFields.Location = new System.Drawing.Point(3, 171);
lboxNumberFields.Name = "lboxNumberFields";
lboxNumberFields.Size = new System.Drawing.Size(220, 275);
lboxNumberFields.Size = new System.Drawing.Size(220, 245);
lboxNumberFields.TabIndex = 0;
lboxNumberFields.DoubleClick += lboxFields_DoubleClick;
//
// label7
//
@@ -272,6 +275,7 @@
lboxStringFields.Name = "lboxStringFields";
lboxStringFields.Size = new System.Drawing.Size(220, 350);
lboxStringFields.TabIndex = 0;
lboxStringFields.DoubleClick += lboxFields_DoubleClick;
//
// label6
//

View File

@@ -1,5 +1,5 @@
using LibationSearchEngine;
using System.ComponentModel;
using System;
using System.Linq;
using System.Windows.Forms;
@@ -7,6 +7,7 @@ namespace LibationWinForms.Dialogs
{
public partial class SearchSyntaxDialog : Form
{
public event EventHandler<string> TagDoubleClicked;
public SearchSyntaxDialog()
{
InitializeComponent();
@@ -23,5 +24,13 @@ namespace LibationWinForms.Dialogs
base.OnFormClosing(e);
this.SaveSizeAndLocation(LibationFileManager.Configuration.Instance);
}
private void lboxFields_DoubleClick(object sender, EventArgs e)
{
if (sender is ListBox { SelectedItem: string tagName })
{
TagDoubleClicked?.Invoke(this, tagName);
}
}
}
}

View File

@@ -8,7 +8,7 @@ namespace LibationWinForms
{
protected void Configure_Filter() { }
private void filterHelpBtn_Click(object sender, EventArgs e) => new SearchSyntaxDialog().ShowDialog();
private void filterHelpBtn_Click(object sender, EventArgs e) => ShowSearchSyntaxDialog();
private void filterSearchTb_TextCleared(object sender, EventArgs e)
{
@@ -45,5 +45,32 @@ namespace LibationWinForms
performFilter(lastGoodFilter);
}
}
public SearchSyntaxDialog ShowSearchSyntaxDialog()
{
var dialog = new SearchSyntaxDialog();
dialog.TagDoubleClicked += Dialog_TagDoubleClicked;
dialog.FormClosed += Dialog_Closed;
filterHelpBtn.Enabled = false;
dialog.Show(this);
return dialog;
void Dialog_Closed(object sender, FormClosedEventArgs e)
{
dialog.TagDoubleClicked -= Dialog_TagDoubleClicked;
filterHelpBtn.Enabled = true;
}
void Dialog_TagDoubleClicked(object sender, string tag)
{
if (string.IsNullOrEmpty(tag)) return;
var text = filterSearchTb.Text;
var selStart = Math.Min(Math.Max(0, filterSearchTb.SelectionStart), text.Length);
filterSearchTb.Text = text.Insert(selStart, tag);
filterSearchTb.SelectionStart = selStart + tag.Length;
filterSearchTb.Focus();
}
}
}
}

View File

@@ -14,6 +14,7 @@ using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LibationWinForms.GridView
{
public partial class ProductsDisplay : UserControl
@@ -68,7 +69,7 @@ namespace LibationWinForms.GridView
PictureStorage.PictureCached -= PictureCached;
if (!imageDisplay.Visible)
imageDisplay.Show(null);
imageDisplay.Show(this);
}
private void productsGrid_DescriptionClicked(GridEntry liveGridEntry, Rectangle cellRectangle)
@@ -90,11 +91,27 @@ namespace LibationWinForms.GridView
displayWindow.Show(this);
}
private async void productsGrid_DetailsClicked(LibraryBookEntry liveGridEntry)
private BookDetailsDialog bookDetailsForm;
private void productsGrid_DetailsClicked(LibraryBookEntry liveGridEntry)
{
var bookDetailsForm = new BookDetailsDialog(liveGridEntry.LibraryBook);
if (bookDetailsForm.ShowDialog() == DialogResult.OK)
await liveGridEntry.LibraryBook.UpdateUserDefinedItemAsync(bookDetailsForm.NewTags, bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus);
if (bookDetailsForm is null || bookDetailsForm.IsDisposed || !bookDetailsForm.Visible)
{
bookDetailsForm = new();
bookDetailsForm.RestoreSizeAndLocation(Configuration.Instance);
bookDetailsForm.FormClosed += bookDetailsForm_FormClosed;
}
bookDetailsForm.LibraryBook = liveGridEntry.LibraryBook;
if (!bookDetailsForm.Visible)
bookDetailsForm.Show(this);
async void bookDetailsForm_FormClosed(object sender, FormClosedEventArgs e)
{
bookDetailsForm.FormClosed -= bookDetailsForm_FormClosed;
bookDetailsForm.SaveSizeAndLocation(Configuration.Instance);
if (e.CloseReason is CloseReason.UserClosing && bookDetailsForm.DialogResult is DialogResult.OK)
await liveGridEntry.LibraryBook.UpdateUserDefinedItemAsync(bookDetailsForm.NewTags, bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus);
}
}
#endregion

View File

@@ -144,19 +144,10 @@ namespace LibationWinForms
LibraryCommands.ScanEnd += LibraryCommands_ScanEnd;
await tcs.Task;
LibraryCommands.ScanEnd -= LibraryCommands_ScanEnd;
MainForm.productsDisplay.VisibleCountChanged -= productsDisplay_VisibleCountChanged;
return true;
void LibraryCommands_ScanEnd(object sender, int newCount)
{
//if we imported new books, wait for the grid to update before proceeding.
if (newCount > 0)
MainForm.productsDisplay.VisibleCountChanged += productsDisplay_VisibleCountChanged;
else
tcs.SetResult();
}
void productsDisplay_VisibleCountChanged(object sender, int e) => tcs.SetResult();
void LibraryCommands_ScanEnd(object _, int __) => tcs.SetResult();
}
private async Task<bool> ShowSearching()
@@ -189,9 +180,10 @@ namespace LibationWinForms
await displayControlAsync(MainForm.filterHelpBtn);
using var filterHelp = MainForm.Invoke(() => new SearchSyntaxDialog());
MainForm.Invoke(filterHelp.ShowDialog);
using var filterHelp = MainForm.Invoke(MainForm.ShowSearchSyntaxDialog);
var tcs = new TaskCompletionSource();
filterHelp.FormClosed += (_, _) => tcs.SetResult();
await tcs.Task;
return true;
}