Merge pull request #86 from Mbucari/master

Use new Dinah.Core.Threading and remove unnecessary DataGridViewImageButtonColumn
This commit is contained in:
rmcrackan 2021-08-19 17:32:00 -04:00 committed by GitHub
commit 7e288c0c08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 43 additions and 198 deletions

View File

@ -1,6 +1,6 @@
using System.ComponentModel;
using Dinah.Core.Threading;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;
namespace LibationWinForms
{
@ -8,9 +8,7 @@ namespace LibationWinForms
{
public event PropertyChangedEventHandler PropertyChanged;
public AsyncNotifyPropertyChanged() { }
protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
=>BeginInvoke(PropertyChanged, new object[] { this, new PropertyChangedEventArgs(propertyName) });
=> this.UIThread(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
}
}

View File

@ -1,6 +1,6 @@
using DataLayer;
using Dinah.Core.Net.Http;
using Dinah.Core.Windows.Forms;
using Dinah.Core.Threading;
using FileLiberator;
using System;
using System.Windows.Forms;
@ -122,8 +122,8 @@ namespace LibationWinForms.BookLiberation.BaseForms
/// <summary>
/// If the form was shown using Show (not ShowDialog), Form.Close calls Form.Dispose
/// </summary>
private void OnStreamingCompletedClose(object sender, string completedString) => this.UIThread(() => Close());
private void OnCompletedDispose(object sender, LibraryBook e) => this.UIThread(() => Dispose());
private void OnStreamingCompletedClose(object sender, string completedString) => this.UIThread(Close);
private void OnCompletedDispose(object sender, LibraryBook e) => this.UIThread(Dispose);
/// <summary>
/// If StreamingBegin is fired from a worker thread, the window will be created on that
@ -132,7 +132,7 @@ namespace LibationWinForms.BookLiberation.BaseForms
/// could cause it to freeze. Form.BeginInvoke won't work until the form is created
/// (ie. shown) because Control doesn't get a window handle until it is Shown.
/// </summary>
private void OnStreamingBeginShow(object sender, string beginString) => Invoker.Invoke(Show);
private void OnStreamingBeginShow(object sender, string beginString) => Invoker.UIThread(Show);
#endregion

View File

@ -0,0 +1,18 @@
using System.Drawing;
using System.Windows.Forms;
namespace LibationWinForms
{
public class DataGridViewImageButtonCell : DataGridViewButtonCell
{
protected void DrawButtonImage(Graphics graphics, Image 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));
}
}
}

View File

@ -1,50 +0,0 @@
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 DrawButtonImage(Graphics graphics, Image 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));
}
}
}

View File

@ -3,10 +3,12 @@ using System.Windows.Forms;
namespace LibationWinForms
{
public class EditTagsDataGridViewImageButtonColumn : DataGridViewImageButtonColumn
public class EditTagsDataGridViewImageButtonColumn : DataGridViewButtonColumn
{
protected override DataGridViewImageButtonCell NewCell()
=> new EditTagsDataGridViewImageButtonCell();
public EditTagsDataGridViewImageButtonColumn()
{
CellTemplate = new EditTagsDataGridViewImageButtonCell();
}
}
internal class EditTagsDataGridViewImageButtonCell : DataGridViewImageButtonCell

View File

@ -7,6 +7,7 @@ using System.Linq;
using ApplicationServices;
using DataLayer;
using Dinah.Core.DataBinding;
using Dinah.Core;
using Dinah.Core.Drawing;
namespace LibationWinForms
@ -47,9 +48,9 @@ namespace LibationWinForms
Title = Book.Title;
Series = Book.SeriesNames;
Length = Book.LengthInMinutes == 0 ? "" : $"{Book.LengthInMinutes / 60} hr {Book.LengthInMinutes % 60} min";
MyRating = ValueOrDefault(Book.UserDefinedItem.Rating?.ToStarString(), "");
MyRating = Book.UserDefinedItem.Rating?.ToStarString()?.DefaultIfNullOrWhiteSpace("");
PurchaseDate = libraryBook.DateAdded.ToString("d");
ProductRating = ValueOrDefault(Book.Rating?.ToStarString(), "");
ProductRating = Book.Rating?.ToStarString()?.DefaultIfNullOrWhiteSpace("");
Authors = Book.AuthorNames;
Narrators = Book.NarratorNames;
Category = string.Join(" > ", Book.CategoriesNames);
@ -207,8 +208,8 @@ namespace LibationWinForms
{
var details = new List<string>();
var locale = ValueOrDefault(libraryBook.Book.Locale, "[unknown]");
var acct = ValueOrDefault(libraryBook.Account, "[unknown]");
var locale = libraryBook.Book.Locale.DefaultIfNullOrWhiteSpace("[unknown]");
var acct = libraryBook.Account.DefaultIfNullOrWhiteSpace("[unknown]");
details.Add($"Account: {locale} - {acct}");
@ -228,10 +229,6 @@ namespace LibationWinForms
return string.Join("\r\n", details);
}
//Maybe add to Dinah StringExtensions?
private static string ValueOrDefault(string value, string defaultValue)
=> string.IsNullOrWhiteSpace(value) ? defaultValue : value;
#endregion
}
}

View File

@ -6,10 +6,12 @@ using System.Linq;
namespace LibationWinForms
{
public class LiberateDataGridViewImageButtonColumn : DataGridViewImageButtonColumn
public class LiberateDataGridViewImageButtonColumn : DataGridViewButtonColumn
{
protected override DataGridViewImageButtonCell NewCell()
=> new LiberateDataGridViewImageButtonCell();
public LiberateDataGridViewImageButtonColumn()
{
CellTemplate = new LiberateDataGridViewImageButtonCell();
}
}
internal class LiberateDataGridViewImageButtonCell : DataGridViewImageButtonCell

View File

@ -92,7 +92,7 @@
this.gridEntryDataGridView.ReadOnly = true;
this.gridEntryDataGridView.RowHeadersVisible = false;
this.gridEntryDataGridView.RowTemplate.Height = 82;
this.gridEntryDataGridView.Size = new System.Drawing.Size(1505, 380);
this.gridEntryDataGridView.Size = new System.Drawing.Size(1510, 380);
this.gridEntryDataGridView.TabIndex = 0;
//
// dataGridViewImageButtonBoxColumn1
@ -103,7 +103,7 @@
this.dataGridViewImageButtonBoxColumn1.ReadOnly = true;
this.dataGridViewImageButtonBoxColumn1.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.dataGridViewImageButtonBoxColumn1.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
this.dataGridViewImageButtonBoxColumn1.Width = 70;
this.dataGridViewImageButtonBoxColumn1.Width = 75;
//
// dataGridViewImageColumn1
//
@ -213,7 +213,7 @@
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(1505, 380);
this.Size = new System.Drawing.Size(1510, 380);
((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).EndInit();
this.ResumeLayout(false);

View File

@ -1,122 +0,0 @@
using System;
using System.ComponentModel;
using System.Threading;
namespace LibationWinForms
{
public class SynchronizeInvoker : ISynchronizeInvoke
{
public bool InvokeRequired => Thread.CurrentThread.ManagedThreadId != InstanceThreadId;
private int InstanceThreadId { get; set; } = Thread.CurrentThread.ManagedThreadId;
private SynchronizationContext SyncContext { get; } = SynchronizationContext.Current;
public SynchronizeInvoker()
{
if (SyncContext is null)
throw new NullReferenceException($"Could not capture a current {nameof(SynchronizationContext)}");
}
public IAsyncResult BeginInvoke(Action action) => BeginInvoke(action, null);
public IAsyncResult BeginInvoke(Delegate method) => BeginInvoke(method, null);
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
var tme = new ThreadMethodEntry(method, args);
if (InvokeRequired)
{
SyncContext.Post(OnSendOrPostCallback, tme);
}
else
{
tme.Complete();
tme.CompletedSynchronously = true;
}
return tme;
}
public object EndInvoke(IAsyncResult result)
{
if (result is not ThreadMethodEntry crossThread)
throw new ArgumentException($"{nameof(result)} was not returned by {nameof(SynchronizeInvoker)}.{nameof(BeginInvoke)}");
if (!crossThread.IsCompleted)
crossThread.AsyncWaitHandle.WaitOne();
return crossThread.ReturnValue;
}
public object Invoke(Action action) => Invoke(action, null);
public object Invoke(Delegate method) => Invoke(method, null);
public object Invoke(Delegate method, object[] args)
{
var tme = new ThreadMethodEntry(method, args);
if (InvokeRequired)
{
SyncContext.Send(OnSendOrPostCallback, tme);
}
else
{
tme.Complete();
tme.CompletedSynchronously = true;
}
return tme.ReturnValue;
}
/// <summary>
/// This callback executes on the SynchronizationContext thread.
/// </summary>
private static void OnSendOrPostCallback(object asyncArgs)
{
var e = asyncArgs as ThreadMethodEntry;
e.Complete();
}
private class ThreadMethodEntry : IAsyncResult
{
public object AsyncState => null;
public bool CompletedSynchronously { get; internal set; }
public bool IsCompleted { get; private set; }
public object ReturnValue { get; private set; }
public WaitHandle AsyncWaitHandle => completedEvent;
private Delegate method;
private object[] args;
private ManualResetEvent completedEvent;
public ThreadMethodEntry(Delegate method, object[] args)
{
this.method = method;
this.args = args;
completedEvent = new ManualResetEvent(initialState: false);
}
public void Complete()
{
try
{
switch (method)
{
case Action actiton:
actiton();
break;
default:
ReturnValue = method.DynamicInvoke(args);
break;
}
}
finally
{
IsCompleted = true;
completedEvent.Set();
}
}
~ThreadMethodEntry()
{
completedEvent.Close();
}
}
}
}