Merge pull request #86 from Mbucari/master
Use new Dinah.Core.Threading and remove unnecessary DataGridViewImageButtonColumn
This commit is contained in:
commit
7e288c0c08
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
18
LibationWinForms/DataGridViewImageButtonCell.cs
Normal file
18
LibationWinForms/DataGridViewImageButtonCell.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
6
LibationWinForms/ProductsGrid.Designer.cs
generated
6
LibationWinForms/ProductsGrid.Designer.cs
generated
@ -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);
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user