Consolidated base forms
This commit is contained in:
parent
2c20d03506
commit
3e2d69606b
4
FileLiberator/IFileLiberator.cs
Normal file
4
FileLiberator/IFileLiberator.cs
Normal file
@ -0,0 +1,4 @@
|
||||
namespace FileLiberator
|
||||
{
|
||||
public interface IFileLiberator { }
|
||||
}
|
||||
@ -5,7 +5,7 @@ using Dinah.Core.ErrorHandling;
|
||||
|
||||
namespace FileLiberator
|
||||
{
|
||||
public interface IProcessable
|
||||
public interface IProcessable : IFileLiberator
|
||||
{
|
||||
event EventHandler<LibraryBook> Begin;
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ using Dinah.Core.Net.Http;
|
||||
|
||||
namespace FileLiberator
|
||||
{
|
||||
public interface IStreamable
|
||||
public interface IStreamable : IFileLiberator
|
||||
{
|
||||
event EventHandler<string> StreamingBegin;
|
||||
event EventHandler<DownloadProgress> StreamingProgressChanged;
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<!-- <PublishSingleFile>true</PublishSingleFile> -->
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
||||
<Version>5.4.9.274</Version>
|
||||
<Version>5.4.9.279</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
|
||||
@ -3,9 +3,9 @@ using System;
|
||||
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
class AudioConvertForm : AudioDecodeBaseForm
|
||||
class AudioConvertForm : AudioDecodeForm
|
||||
{
|
||||
#region AudioDecodeBaseForm overrides
|
||||
#region AudioDecodeForm overrides
|
||||
public override string DecodeActionName => "Converting";
|
||||
#endregion
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
partial class AudioDecodeBaseForm
|
||||
partial class AudioDecodeForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
@ -1,15 +1,20 @@
|
||||
using DataLayer;
|
||||
using Dinah.Core.Net.Http;
|
||||
using Dinah.Core.Windows.Forms;
|
||||
using FileLiberator;
|
||||
using LibationWinForms.BookLiberation.BaseForms;
|
||||
using System;
|
||||
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
public partial class AudioDecodeBaseForm : ProcessBaseForm
|
||||
public partial class AudioDecodeForm
|
||||
#if DEBUG
|
||||
: DebugIntermediate
|
||||
#else
|
||||
: LiberationBaseForm
|
||||
#endif
|
||||
{
|
||||
public virtual string DecodeActionName { get; } = "Decoding";
|
||||
public AudioDecodeBaseForm() => InitializeComponent();
|
||||
public AudioDecodeForm() => InitializeComponent();
|
||||
|
||||
private Func<byte[]> GetCoverArtDelegate;
|
||||
|
||||
@ -18,41 +23,6 @@ namespace LibationWinForms.BookLiberation
|
||||
private string authorNames;
|
||||
private string narratorNames;
|
||||
|
||||
#region ProcessBaseForm overrides
|
||||
public override void SetProcessable(IStreamable streamProcessable, LogMe logMe)
|
||||
{
|
||||
base.SetProcessable(streamProcessable, logMe);
|
||||
|
||||
if (Streamable is not null && Streamable is IAudioDecodable audioDecodable)
|
||||
{
|
||||
OnUnsubscribeAll(this, EventArgs.Empty);
|
||||
|
||||
audioDecodable.RequestCoverArt += OnRequestCoverArt;
|
||||
audioDecodable.TitleDiscovered += OnTitleDiscovered;
|
||||
audioDecodable.AuthorsDiscovered += OnAuthorsDiscovered;
|
||||
audioDecodable.NarratorsDiscovered += OnNarratorsDiscovered;
|
||||
audioDecodable.CoverImageDiscovered += OnCoverImageDiscovered;
|
||||
|
||||
Disposed += OnUnsubscribeAll;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void OnUnsubscribeAll(object sender, EventArgs e)
|
||||
{
|
||||
if (Streamable is IAudioDecodable audioDecodable)
|
||||
{
|
||||
Disposed -= OnUnsubscribeAll;
|
||||
audioDecodable.RequestCoverArt -= OnRequestCoverArt;
|
||||
audioDecodable.TitleDiscovered -= OnTitleDiscovered;
|
||||
audioDecodable.AuthorsDiscovered -= OnAuthorsDiscovered;
|
||||
audioDecodable.NarratorsDiscovered -= OnNarratorsDiscovered;
|
||||
audioDecodable.CoverImageDiscovered -= OnCoverImageDiscovered;
|
||||
|
||||
audioDecodable.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
#region IProcessable event handler overrides
|
||||
public override void OnBegin(object sender, LibraryBook libraryBook)
|
||||
{
|
||||
@ -74,6 +44,7 @@ namespace LibationWinForms.BookLiberation
|
||||
#endregion
|
||||
|
||||
#region IStreamable event handler overrides
|
||||
public override void OnStreamingBegin(object sender, string beginString) { }
|
||||
public override void OnStreamingProgressChanged(object sender, DownloadProgress downloadProgress)
|
||||
{
|
||||
if (!downloadProgress.ProgressPercentage.HasValue)
|
||||
@ -87,32 +58,34 @@ namespace LibationWinForms.BookLiberation
|
||||
|
||||
public override void OnStreamingTimeRemaining(object sender, TimeSpan timeRemaining)
|
||||
=> updateRemainingTime((int)timeRemaining.TotalSeconds);
|
||||
|
||||
public override void OnStreamingCompleted(object sender, string completedString) { }
|
||||
#endregion
|
||||
|
||||
#region IAudioDecodable event handlers
|
||||
public virtual void OnRequestCoverArt(object sender, Action<byte[]> setCoverArtDelegate)
|
||||
public override void OnRequestCoverArt(object sender, Action<byte[]> setCoverArtDelegate)
|
||||
=> setCoverArtDelegate(GetCoverArtDelegate?.Invoke());
|
||||
|
||||
public virtual void OnTitleDiscovered(object sender, string title)
|
||||
public override void OnTitleDiscovered(object sender, string title)
|
||||
{
|
||||
this.UIThread(() => this.Text = DecodeActionName + " " + title);
|
||||
this.title = title;
|
||||
updateBookInfo();
|
||||
}
|
||||
|
||||
public virtual void OnAuthorsDiscovered(object sender, string authors)
|
||||
public override void OnAuthorsDiscovered(object sender, string authors)
|
||||
{
|
||||
authorNames = authors;
|
||||
updateBookInfo();
|
||||
}
|
||||
|
||||
public virtual void OnNarratorsDiscovered(object sender, string narrators)
|
||||
public override void OnNarratorsDiscovered(object sender, string narrators)
|
||||
{
|
||||
narratorNames = narrators;
|
||||
updateBookInfo();
|
||||
}
|
||||
|
||||
public virtual void OnCoverImageDiscovered(object sender, byte[] coverArt)
|
||||
public override void OnCoverImageDiscovered(object sender, byte[] coverArt)
|
||||
=> pictureBox1.UIThread(() => pictureBox1.Image = Dinah.Core.Drawing.ImageReader.ToImage(coverArt));
|
||||
#endregion
|
||||
|
||||
@ -3,9 +3,9 @@ using System;
|
||||
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
class AudioDecryptForm : AudioDecodeBaseForm
|
||||
class AudioDecryptForm : AudioDecodeForm
|
||||
{
|
||||
#region AudioDecodeBaseForm overrides
|
||||
#region AudioDecodeForm overrides
|
||||
public override string DecodeActionName => "Decrypting";
|
||||
#endregion
|
||||
|
||||
|
||||
189
LibationWinForms/BookLiberation/BaseForms/LiberationBaseForm.cs
Normal file
189
LibationWinForms/BookLiberation/BaseForms/LiberationBaseForm.cs
Normal file
@ -0,0 +1,189 @@
|
||||
using DataLayer;
|
||||
using Dinah.Core.Net.Http;
|
||||
using Dinah.Core.Windows.Forms;
|
||||
using FileLiberator;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibationWinForms.BookLiberation.BaseForms
|
||||
{
|
||||
public abstract class LiberationBaseForm : Form
|
||||
{
|
||||
protected IFileLiberator Liberation { get; private set; }
|
||||
protected LogMe LogMe { get; private set; }
|
||||
|
||||
private int InstanceThreadId { get; } = Thread.CurrentThread.ManagedThreadId;
|
||||
public new bool InvokeRequired => Thread.CurrentThread.ManagedThreadId != InstanceThreadId;
|
||||
private SynchronizationContext SyncContext { get; }
|
||||
|
||||
public LiberationBaseForm()
|
||||
{
|
||||
//Will be null if set outside constructor.
|
||||
SyncContext = SynchronizationContext.Current;
|
||||
}
|
||||
|
||||
public void RegisterLiberation(IFileLiberator liberation, LogMe logMe = null)
|
||||
{
|
||||
if (liberation is null) return;
|
||||
|
||||
Liberation = liberation;
|
||||
LogMe = logMe;
|
||||
|
||||
if (Liberation is IStreamable streamable)
|
||||
Subscribe(streamable);
|
||||
if (Liberation is IProcessable processable)
|
||||
Subscribe(processable);
|
||||
if (Liberation is IAudioDecodable audioDecodable)
|
||||
Subscribe(audioDecodable);
|
||||
}
|
||||
|
||||
#region Event Subscribers and Unsubscribers
|
||||
private void Subscribe(IStreamable streamable)
|
||||
{
|
||||
UnsubscribeStreamable(this, EventArgs.Empty);
|
||||
|
||||
streamable.StreamingBegin += ShowFormHandler;
|
||||
streamable.StreamingBegin += OnStreamingBegin;
|
||||
streamable.StreamingProgressChanged += OnStreamingProgressChanged;
|
||||
streamable.StreamingTimeRemaining += OnStreamingTimeRemaining;
|
||||
streamable.StreamingCompleted += OnStreamingCompleted;
|
||||
streamable.StreamingCompleted += OnStreamingCompletedClose;
|
||||
|
||||
FormClosed += UnsubscribeStreamable;
|
||||
}
|
||||
private void Subscribe(IProcessable processable)
|
||||
{
|
||||
UnsubscribeProcessable(this, null);
|
||||
|
||||
processable.Begin += OnBegin;
|
||||
processable.StatusUpdate += OnStatusUpdate;
|
||||
processable.Completed += OnCompleted;
|
||||
|
||||
//The form is created on IProcessable.Begin and we
|
||||
//dispose of it on IProcessable.Completed
|
||||
processable.Completed += OnCompletedDispose;
|
||||
|
||||
//Don't unsubscribe from Dispose because it fires when
|
||||
//IStreamable.StreamingCompleted closes the form, and
|
||||
//the IProcessable events need to live past that event.
|
||||
processable.Completed += UnsubscribeProcessable;
|
||||
}
|
||||
private void Subscribe(IAudioDecodable audioDecodable)
|
||||
{
|
||||
UnsubscribeAudioDecodable(this, EventArgs.Empty);
|
||||
|
||||
audioDecodable.RequestCoverArt += OnRequestCoverArt;
|
||||
audioDecodable.TitleDiscovered += OnTitleDiscovered;
|
||||
audioDecodable.AuthorsDiscovered += OnAuthorsDiscovered;
|
||||
audioDecodable.NarratorsDiscovered += OnNarratorsDiscovered;
|
||||
audioDecodable.CoverImageDiscovered += OnCoverImageDiscovered;
|
||||
|
||||
Disposed += UnsubscribeAudioDecodable;
|
||||
}
|
||||
private void UnsubscribeStreamable(object sender, EventArgs e)
|
||||
{
|
||||
if (Liberation is not IStreamable streamable)
|
||||
return;
|
||||
|
||||
FormClosed -= UnsubscribeStreamable;
|
||||
|
||||
streamable.StreamingBegin -= ShowFormHandler;
|
||||
streamable.StreamingBegin -= OnStreamingBegin;
|
||||
streamable.StreamingProgressChanged -= OnStreamingProgressChanged;
|
||||
streamable.StreamingTimeRemaining -= OnStreamingTimeRemaining;
|
||||
streamable.StreamingCompleted -= OnStreamingCompleted;
|
||||
streamable.StreamingCompleted -= OnStreamingCompletedClose;
|
||||
}
|
||||
private void UnsubscribeProcessable(object sender, LibraryBook e)
|
||||
{
|
||||
if (Liberation is not IProcessable processable)
|
||||
return;
|
||||
|
||||
processable.Completed -= UnsubscribeProcessable;
|
||||
processable.Completed -= OnCompletedDispose;
|
||||
processable.Completed -= OnCompleted;
|
||||
processable.StatusUpdate -= OnStatusUpdate;
|
||||
processable.Begin -= OnBegin;
|
||||
}
|
||||
private void UnsubscribeAudioDecodable(object sender, EventArgs e)
|
||||
{
|
||||
if (Liberation is not IAudioDecodable audioDecodable)
|
||||
return;
|
||||
|
||||
Disposed -= UnsubscribeAudioDecodable;
|
||||
audioDecodable.RequestCoverArt -= OnRequestCoverArt;
|
||||
audioDecodable.TitleDiscovered -= OnTitleDiscovered;
|
||||
audioDecodable.AuthorsDiscovered -= OnAuthorsDiscovered;
|
||||
audioDecodable.NarratorsDiscovered -= OnNarratorsDiscovered;
|
||||
audioDecodable.CoverImageDiscovered -= OnCoverImageDiscovered;
|
||||
|
||||
audioDecodable.Cancel();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Form creation and disposal handling
|
||||
|
||||
/// <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());
|
||||
|
||||
/// <summary>
|
||||
/// If StreamingBegin is fired from a worker thread, the window will be created on
|
||||
/// that UI thread. We need to make certain that we show the window on the same
|
||||
/// thread that created form, otherwise the form and the window handle will be on
|
||||
/// different threads. 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 ShowFormHandler(object sender, string beginString)
|
||||
{
|
||||
static void sendCallback(object asyncArgs)
|
||||
{
|
||||
var e = asyncArgs as AsyncCompletedEventArgs;
|
||||
((Action)e.UserState)();
|
||||
}
|
||||
|
||||
Action show = Show;
|
||||
|
||||
if (InvokeRequired)
|
||||
SyncContext.Send(
|
||||
sendCallback,
|
||||
new AsyncCompletedEventArgs(null, false, show));
|
||||
else
|
||||
show();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IStreamable event handlers
|
||||
public virtual void OnStreamingBegin(object sender, string beginString) { }
|
||||
public virtual void OnStreamingProgressChanged(object sender, DownloadProgress downloadProgress){ }
|
||||
public virtual void OnStreamingTimeRemaining(object sender, TimeSpan timeRemaining){ }
|
||||
public virtual void OnStreamingCompleted(object sender, string completedString){ }
|
||||
#endregion
|
||||
|
||||
#region IProcessable event handlers
|
||||
public virtual void OnBegin(object sender, LibraryBook libraryBook){ }
|
||||
public virtual void OnStatusUpdate(object sender, string statusUpdate){ }
|
||||
public virtual void OnCompleted(object sender, LibraryBook libraryBook){ }
|
||||
#endregion
|
||||
|
||||
#region IAudioDecodable event handlers
|
||||
public virtual void OnRequestCoverArt(object sender, Action<byte[]> setCoverArtDelegate){ }
|
||||
public virtual void OnTitleDiscovered(object sender, string title){ }
|
||||
public virtual void OnAuthorsDiscovered(object sender, string authors){ }
|
||||
public virtual void OnNarratorsDiscovered(object sender, string narrators){ }
|
||||
public virtual void OnCoverImageDiscovered(object sender, byte[] coverArt){ }
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region VS Design View Hack
|
||||
/// <summary>
|
||||
/// This class is a hack so that VS designer will work wif an abstract base class.
|
||||
/// https://stackoverflow.com/questions/1620847/how-can-i-get-visual-studio-2008-windows-forms-designer-to-render-a-form-that-im/2406058#2406058
|
||||
/// </summary>
|
||||
public class DebugIntermediate : LiberationBaseForm { }
|
||||
#endregion
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
using DataLayer;
|
||||
using Dinah.Core.Windows.Forms;
|
||||
using FileLiberator;
|
||||
using System;
|
||||
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
public class ProcessBaseForm : StreamBaseForm
|
||||
{
|
||||
protected LogMe LogMe { get; private set; }
|
||||
public virtual void SetProcessable(IStreamable streamable, LogMe logMe)
|
||||
{
|
||||
LogMe = logMe;
|
||||
SetStreamable(streamable);
|
||||
|
||||
if (Streamable is not null && Streamable is IProcessable processable)
|
||||
{
|
||||
OnUnsubscribeAll(this, null);
|
||||
|
||||
processable.Begin += OnBegin;
|
||||
processable.Completed += OnCompleted;
|
||||
processable.StatusUpdate += OnStatusUpdate;
|
||||
|
||||
//The form is created on IProcessable.Begin and we
|
||||
//dispose of it on IProcessable.Completed
|
||||
processable.Completed += OnCompletedDispose;
|
||||
|
||||
//Don't unsubscribe from Dispose because it fires when
|
||||
//IStreamable.StreamingCompleted closes the form, and
|
||||
//the IProcessable events need to live past that event.
|
||||
processable.Completed += OnUnsubscribeAll;
|
||||
}
|
||||
}
|
||||
private void OnCompletedDispose(object sender, LibraryBook e) => this.UIThread(() => Dispose());
|
||||
|
||||
private void OnUnsubscribeAll(object sender, LibraryBook e)
|
||||
{
|
||||
if (Streamable is IProcessable processable)
|
||||
{
|
||||
processable.Completed -= OnUnsubscribeAll;
|
||||
processable.Completed -= OnCompletedDispose;
|
||||
processable.Begin -= OnBegin;
|
||||
processable.Completed -= OnCompleted;
|
||||
processable.StatusUpdate -= OnStatusUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
#region IProcessable event handlers
|
||||
public virtual void OnBegin(object sender, LibraryBook libraryBook) => LogMe.Info($"Begin: {libraryBook.Book}");
|
||||
public virtual void OnStatusUpdate(object sender, string statusUpdate) => LogMe.Info("- " + statusUpdate);
|
||||
public virtual void OnCompleted(object sender, LibraryBook libraryBook) => LogMe.Info($"Completed: {libraryBook.Book}{Environment.NewLine}");
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@ -1,90 +0,0 @@
|
||||
using Dinah.Core.Net.Http;
|
||||
using Dinah.Core.Windows.Forms;
|
||||
using FileLiberator;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
public class StreamBaseForm : Form
|
||||
{
|
||||
private int InstanceThreadId { get; } = Thread.CurrentThread.ManagedThreadId;
|
||||
public new bool InvokeRequired => Thread.CurrentThread.ManagedThreadId != InstanceThreadId;
|
||||
private SynchronizationContext SyncContext { get; }
|
||||
|
||||
public StreamBaseForm()
|
||||
{
|
||||
//Will be null if set outside constructor.
|
||||
SyncContext = SynchronizationContext.Current;
|
||||
}
|
||||
|
||||
protected IStreamable Streamable { get; private set; }
|
||||
public void SetStreamable(IStreamable streamable)
|
||||
{
|
||||
Streamable = streamable;
|
||||
|
||||
if (Streamable is null) return;
|
||||
|
||||
OnUnsubscribeAll(this, EventArgs.Empty);
|
||||
|
||||
Streamable.StreamingBegin += ShowFormHandler;
|
||||
Streamable.StreamingBegin += OnStreamingBegin;
|
||||
Streamable.StreamingProgressChanged += OnStreamingProgressChanged;
|
||||
Streamable.StreamingTimeRemaining += OnStreamingTimeRemaining;
|
||||
Streamable.StreamingCompleted += OnStreamingCompleted;
|
||||
Streamable.StreamingCompleted += CloseFormHandler;
|
||||
|
||||
FormClosed += OnUnsubscribeAll;
|
||||
}
|
||||
|
||||
private void OnUnsubscribeAll(object sender, EventArgs e)
|
||||
{
|
||||
FormClosed -= OnUnsubscribeAll;
|
||||
|
||||
Streamable.StreamingBegin -= ShowFormHandler;
|
||||
Streamable.StreamingBegin -= OnStreamingBegin;
|
||||
Streamable.StreamingProgressChanged -= OnStreamingProgressChanged;
|
||||
Streamable.StreamingTimeRemaining -= OnStreamingTimeRemaining;
|
||||
Streamable.StreamingCompleted -= OnStreamingCompleted;
|
||||
Streamable.StreamingCompleted -= CloseFormHandler;
|
||||
}
|
||||
|
||||
private void ShowFormHandler(object sender, string beginString)
|
||||
{
|
||||
//If StreamingBegin is fired from a worker thread, the window will be created on
|
||||
//that UI thread. We need to make certain that we show the window on the same
|
||||
//thread that created form, otherwise the form and the window handle will be on
|
||||
//different threads. Form.BeginInvoke won't work until the form is created
|
||||
//(ie. shown) because control doesn't get a window handle until it is Shown.
|
||||
static void sendCallback(object asyncArgs)
|
||||
{
|
||||
var e = asyncArgs as AsyncCompletedEventArgs;
|
||||
((Action)e.UserState)();
|
||||
}
|
||||
|
||||
Action show = Show;
|
||||
|
||||
if (InvokeRequired)
|
||||
SyncContext.Send(
|
||||
sendCallback,
|
||||
new AsyncCompletedEventArgs(null, false, show));
|
||||
else
|
||||
show();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the form was shown using Show (not ShowDialog), Form.Close calls Form.Dispose
|
||||
/// </summary>
|
||||
private void CloseFormHandler(object sender, string completedString) => this.UIThread(() => Close());
|
||||
|
||||
|
||||
#region IStreamable event handlers
|
||||
public virtual void OnStreamingBegin(object sender, string beginString) { }
|
||||
public virtual void OnStreamingProgressChanged(object sender, DownloadProgress downloadProgress) { }
|
||||
public virtual void OnStreamingTimeRemaining(object sender, TimeSpan timeRemaining) { }
|
||||
public virtual void OnStreamingCompleted(object sender, string completedString) { }
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@ -1,4 +1,7 @@
|
||||
namespace LibationWinForms.BookLiberation
|
||||
using DataLayer;
|
||||
using System;
|
||||
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
partial class DownloadForm
|
||||
{
|
||||
@ -95,6 +98,7 @@
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label filenameLbl;
|
||||
|
||||
@ -1,13 +1,18 @@
|
||||
using DataLayer;
|
||||
using Dinah.Core.Net.Http;
|
||||
using Dinah.Core.Net.Http;
|
||||
using Dinah.Core.Windows.Forms;
|
||||
using LibationWinForms.BookLiberation.BaseForms;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
public partial class DownloadForm : ProcessBaseForm
|
||||
public partial class DownloadForm
|
||||
#if DEBUG
|
||||
: DebugIntermediate
|
||||
#else
|
||||
: LiberationBaseForm
|
||||
#endif
|
||||
{
|
||||
public DownloadForm()
|
||||
{
|
||||
@ -17,11 +22,11 @@ namespace LibationWinForms.BookLiberation
|
||||
filenameLbl.Text = "";
|
||||
}
|
||||
|
||||
|
||||
#region IStreamable event handler overrides
|
||||
public override void OnStreamingBegin(object sender, string beginString)
|
||||
{
|
||||
filenameLbl.UIThread(() => filenameLbl.Text = beginString);
|
||||
base.OnStreamingBegin(sender, beginString);
|
||||
}
|
||||
public override void OnStreamingProgressChanged(object sender, DownloadProgress downloadProgress)
|
||||
{
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using DataLayer;
|
||||
using Dinah.Core;
|
||||
using FileLiberator;
|
||||
using LibationWinForms.BookLiberation.BaseForms;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@ -126,15 +127,15 @@ namespace LibationWinForms.BookLiberation
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="IStreamProcessable"/> and links it to a new <see cref="ProcessBaseForm"/>.
|
||||
/// Create a new <see cref="IStreamProcessable"/> and links it to a new <see cref="LiberationBaseForm"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TStrProc">The <see cref="IStreamProcessable"/> derrived type to create.</typeparam>
|
||||
/// <typeparam name="TForm">The <see cref="ProcessBaseForm"/> derrived Form to create on <see cref="IProcessable.Begin"/>, Show on <see cref="IStreamable.StreamingBegin"/>, and Close & Dispose on <see cref="IStreamable.StreamingCompleted"/></typeparam>
|
||||
/// <typeparam name="TForm">The <see cref="LiberationBaseForm"/> derrived Form to create on <see cref="IProcessable.Begin"/>, Show on <see cref="IStreamable.StreamingBegin"/>, Close on <see cref="IStreamable.StreamingCompleted"/>, and Dispose on <see cref="IProcessable.Completed"/> </typeparam>
|
||||
/// <param name="logMe">The logger</param>
|
||||
/// <param name="completedAction">An additional event handler to handle <see cref="IProcessable.Completed"/></param>
|
||||
/// <returns>A new <see cref="IStreamProcessable"/> of type <typeparamref name="TStrProc"/></returns>
|
||||
private static TStrProc CreateStreamProcessable<TStrProc, TForm>(LogMe logMe, EventHandler<LibraryBook> completedAction = null)
|
||||
where TForm : ProcessBaseForm, new()
|
||||
where TForm : LiberationBaseForm, new()
|
||||
where TStrProc : IStreamProcessable, new()
|
||||
{
|
||||
var strProc = new TStrProc();
|
||||
@ -142,7 +143,7 @@ namespace LibationWinForms.BookLiberation
|
||||
strProc.Begin += (sender, libraryBook) =>
|
||||
{
|
||||
var processForm = new TForm();
|
||||
processForm.SetProcessable(strProc, logMe);
|
||||
processForm.RegisterLiberation(strProc, logMe);
|
||||
processForm.OnBegin(sender, libraryBook);
|
||||
};
|
||||
|
||||
@ -153,20 +154,20 @@ namespace LibationWinForms.BookLiberation
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="IStreamable"/> and links it to a new <see cref="StreamBaseForm"/>
|
||||
/// Creates a new <see cref="IStreamable"/> and links it to a new <see cref="LiberationBaseForm"/>
|
||||
/// </summary>
|
||||
/// <typeparam name="TStr">The <see cref="IStreamable"/> derrived type to create.</typeparam>
|
||||
/// <typeparam name="TForm">The <see cref="StreamBaseForm"/> derrived Form to create, which will Show on <see cref="IStreamable.StreamingBegin"/> and Close & Dispose on <see cref="IStreamable.StreamingCompleted"/>.</typeparam>
|
||||
/// <typeparam name="TForm">The <see cref="LiberationBaseForm"/> derrived Form to create, which will Show on <see cref="IStreamable.StreamingBegin"/> and Close, Dispose on <see cref="IStreamable.StreamingCompleted"/>.</typeparam>
|
||||
/// <param name="completedAction">An additional event handler to handle <see cref="IStreamable.StreamingCompleted"/></param>
|
||||
/// <returns>A new <see cref="IStreamable"/> of type <typeparamref name="TStr"/></returns>
|
||||
private static TStr CreateStreamable<TStr, TForm>(EventHandler<string> completedAction = null)
|
||||
where TForm : StreamBaseForm, new()
|
||||
where TForm : LiberationBaseForm, new()
|
||||
where TStr : IStreamable, new()
|
||||
{
|
||||
var streamable = new TStr();
|
||||
|
||||
var streamForm = new TForm();
|
||||
streamForm.SetStreamable(streamable);
|
||||
streamForm.RegisterLiberation(streamable);
|
||||
|
||||
if (completedAction != null)
|
||||
streamable.StreamingCompleted += completedAction;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user