2021-08-12 12:47:02 -06:00

79 lines
2.6 KiB
C#

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 += OnStreamingBegin;
Streamable.StreamingCompleted += OnStreamingCompleted;
Streamable.StreamingProgressChanged += OnStreamingProgressChanged;
Streamable.StreamingTimeRemaining += OnStreamingTimeRemaining;
FormClosed += OnUnsubscribeAll;
}
private void OnUnsubscribeAll(object sender, EventArgs e)
{
FormClosed -= OnUnsubscribeAll;
Streamable.StreamingBegin -= OnStreamingBegin;
Streamable.StreamingCompleted -= OnStreamingCompleted;
Streamable.StreamingProgressChanged -= OnStreamingProgressChanged;
Streamable.StreamingTimeRemaining -= OnStreamingTimeRemaining;
}
#region IStreamable event handlers
public virtual void OnStreamingBegin(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();
}
public virtual void OnStreamingProgressChanged(object sender, DownloadProgress downloadProgress) { }
public virtual void OnStreamingTimeRemaining(object sender, TimeSpan timeRemaining) { }
public virtual void OnStreamingCompleted(object sender, string completedString) => this.UIThread(() => Close());
#endregion
}
}