Added VirtualFlowControl and BookQueue

This commit is contained in:
Michael Bucari-Tovo 2022-05-13 00:21:41 -06:00
parent 24cb1aa84f
commit 763a6cb31a
10 changed files with 902 additions and 416 deletions

View File

@ -0,0 +1,175 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibationWinForms.ProcessQueue
{
internal class TrackedQueue<T> where T : class
{
public T Current { get; private set; }
private readonly LinkedList<T> Queued = new();
private readonly List<T> Completed = new();
private readonly object lockObject = new();
public int Count => Queued.Count + Completed.Count + (Current == null ? 0 : 1);
public T this[int index]
{
get
{
if (index < Completed.Count)
return Completed[index];
index -= Completed.Count;
if (index == 0&& Current != null) return Current;
if (Current != null) index--;
if (index < Queued.Count) return Queued.ElementAt(index);
throw new IndexOutOfRangeException();
}
}
public List<T> QueuedItems()
{
lock (lockObject)
return Queued.ToList();
}
public List<T> CompletedItems()
{
lock (lockObject)
return Completed.ToList();
}
public bool QueueCount
{
get
{
lock (lockObject)
return Queued.Count > 0;
}
}
public bool CompleteCount
{
get
{
lock (lockObject)
return Completed.Count > 0;
}
}
public void ClearQueue()
{
lock (lockObject)
{
Queued.Clear();
}
}
public void ClearCompleted()
{
lock (lockObject)
{
Completed.Clear();
}
}
public bool Any(Func<T, bool> predicate)
{
lock (lockObject)
{
return (Current != null && predicate(Current)) || Completed.Any(predicate) || Queued.Any(predicate);
}
}
public QueuePosition MoveQueuePosition(T item, QueuePositionRequest requestedPosition)
{
lock (lockObject)
{
if (Queued.Count == 0)
{
if (Current != null && Current == item)
return QueuePosition.Current;
if (Completed.Contains(item))
return QueuePosition.Completed;
return QueuePosition.Absent;
}
var node = Queued.Find(item);
if (node is null) return QueuePosition.Absent;
if ((requestedPosition == QueuePositionRequest.Fisrt || requestedPosition == QueuePositionRequest.OneUp) && Queued.First.Value == item)
return QueuePosition.Fisrt;
if ((requestedPosition == QueuePositionRequest.Last || requestedPosition == QueuePositionRequest.OneDown) && Queued.Last.Value == item)
return QueuePosition.Last;
if (requestedPosition == QueuePositionRequest.OneUp)
{
var oneUp = node.Previous;
Queued.Remove(node);
Queued.AddBefore(oneUp, node.Value);
return Queued.First.Value == item? QueuePosition.Fisrt : QueuePosition.OneUp;
}
else if (requestedPosition == QueuePositionRequest.OneDown)
{
var oneDown = node.Next;
Queued.Remove(node);
Queued.AddAfter(oneDown, node.Value);
return Queued.Last.Value == item ? QueuePosition.Last : QueuePosition.OneDown;
}
else if (requestedPosition == QueuePositionRequest.Fisrt)
{
Queued.Remove(node);
Queued.AddFirst(node);
return QueuePosition.Fisrt;
}
else
{
Queued.Remove(node);
Queued.AddLast(node);
return QueuePosition.Last;
}
}
}
public bool Remove(T item)
{
lock (lockObject)
{
return Queued.Remove(item);
}
}
public bool MoveNext()
{
lock (lockObject)
{
if (Current != null)
Completed.Add(Current);
if (Queued.Count == 0) return false;
Current = Queued.First.Value;
Queued.RemoveFirst();
return true;
}
}
public T PeekNext()
{
lock (lockObject)
return Queued.Count > 0 ? Queued.First.Value : default;
}
public void EnqueueBook(T item)
{
lock (lockObject)
Queued.AddLast(item);
}
}
}

View File

@ -16,22 +16,39 @@ namespace LibationWinForms.ProcessQueue
None, None,
Success, Success,
Cancelled, Cancelled,
ValidationFail,
FailedRetry, FailedRetry,
FailedSkip, FailedSkip,
FailedAbort FailedAbort
} }
public enum ProcessBookStatus
{
Queued,
Cancelled,
Working,
Completed,
Failed
}
internal enum QueuePosition internal enum QueuePosition
{ {
Absent, Absent,
Completed,
Current, Current,
Fisrt, Fisrt,
OneUp, OneUp,
OneDown, OneDown,
Last Last
} }
internal enum QueuePositionRequest
{
Fisrt,
OneUp,
OneDown,
Last
}
internal delegate QueuePosition ProcessControlReorderHandler(ProcessBook sender, QueuePosition arg); internal delegate QueuePosition ProcessControlReorderHandler(ProcessBook sender, QueuePositionRequest arg);
internal delegate void ProcessControlEventArgs<T>(ProcessBook sender, T arg); internal delegate void ProcessControlEventArgs<T>(ProcessBook sender, T arg);
internal delegate void ProcessControlEventArgs(ProcessBook sender, EventArgs arg); internal delegate void ProcessControlEventArgs(ProcessBook sender, EventArgs arg);
@ -41,7 +58,7 @@ namespace LibationWinForms.ProcessQueue
public event ProcessControlEventArgs Cancelled; public event ProcessControlEventArgs Cancelled;
public event ProcessControlReorderHandler RequestMove; public event ProcessControlReorderHandler RequestMove;
public GridEntry Entry { get; } public GridEntry Entry { get; }
public ILiberationBaseForm BookControl { get; } //public ProcessBookControl BookControl { get; }
private Func<Processable> _makeFirstProc; private Func<Processable> _makeFirstProc;
private Processable _firstProcessable; private Processable _firstProcessable;
@ -55,20 +72,15 @@ namespace LibationWinForms.ProcessQueue
public ProcessBook(GridEntry entry, LogMe logme) public ProcessBook(GridEntry entry, LogMe logme)
{ {
Entry = entry; Entry = entry;
BookControl = new ProcessBookControl(Entry.Title, Entry.Cover); //BookControl = new ProcessBookControl(Entry.Title, Entry.Cover);
BookControl.CancelAction = Cancel; //BookControl.CancelAction = Cancel;
BookControl.MoveUpAction = MoveUp; //BookControl.RequestMoveAction = MoveRequested;
BookControl.MoveDownAction = MoveDown;
Logger = logme; Logger = logme;
} }
public QueuePosition? MoveUp() public QueuePosition? MoveRequested(QueuePositionRequest requestedPosition)
{ {
return RequestMove?.Invoke(this, QueuePosition.OneUp); return RequestMove?.Invoke(this, requestedPosition);
}
public QueuePosition? MoveDown()
{
return RequestMove?.Invoke(this, QueuePosition.OneDown);
} }
public void Cancel() public void Cancel()
@ -94,11 +106,9 @@ namespace LibationWinForms.ProcessQueue
ProcessBookResult result = ProcessBookResult.None; ProcessBookResult result = ProcessBookResult.None;
try try
{ {
var firstProc = FirstProcessable; LinkProcessable(FirstProcessable);
LinkProcessable(firstProc); var statusHandler = await FirstProcessable.ProcessSingleAsync(Entry.LibraryBook, validate: true);
var statusHandler = await firstProc.ProcessSingleAsync(Entry.LibraryBook, validate: true);
if (statusHandler.IsSuccess) if (statusHandler.IsSuccess)
@ -108,6 +118,11 @@ namespace LibationWinForms.ProcessQueue
Logger.Info($"Process was cancelled {Entry.LibraryBook.Book}"); Logger.Info($"Process was cancelled {Entry.LibraryBook.Book}");
return result = ProcessBookResult.Cancelled; return result = ProcessBookResult.Cancelled;
} }
else if (statusHandler.Errors.Contains("Validation failed"))
{
Logger.Info($"Validation failed {Entry.LibraryBook.Book}");
return result = ProcessBookResult.ValidationFail;
}
foreach (var errorMessage in statusHandler.Errors) foreach (var errorMessage in statusHandler.Errors)
Logger.Error(errorMessage); Logger.Error(errorMessage);
@ -121,7 +136,7 @@ namespace LibationWinForms.ProcessQueue
if (result == ProcessBookResult.None) if (result == ProcessBookResult.None)
result = showRetry(Entry.LibraryBook); result = showRetry(Entry.LibraryBook);
BookControl.SetResult(result); //BookControl.SetResult(result);
} }
return result; return result;
@ -149,8 +164,8 @@ namespace LibationWinForms.ProcessQueue
private void Processable_Begin(object sender, LibraryBook libraryBook) private void Processable_Begin(object sender, LibraryBook libraryBook)
{ {
BookControl.RegisterFileLiberator((Processable)sender, Logger); //BookControl.RegisterFileLiberator((Processable)sender, Logger);
BookControl.Processable_Begin(sender, libraryBook); //BookControl.Processable_Begin(sender, libraryBook);
} }
private async void Processable_Completed(object sender, LibraryBook e) private async void Processable_Completed(object sender, LibraryBook e)

View File

@ -30,13 +30,16 @@
{ {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProcessBookControl)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProcessBookControl));
this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.bookInfoLbl = new System.Windows.Forms.Label();
this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.remainingTimeLbl = new System.Windows.Forms.Label(); this.remainingTimeLbl = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label(); this.etaLbl = new System.Windows.Forms.Label();
this.cancelBtn = new System.Windows.Forms.Button(); this.cancelBtn = new System.Windows.Forms.Button();
this.statusLbl = new System.Windows.Forms.Label();
this.bookInfoLbl = new System.Windows.Forms.Label();
this.moveUpBtn = new System.Windows.Forms.Button(); this.moveUpBtn = new System.Windows.Forms.Button();
this.moveDownBtn = new System.Windows.Forms.Button(); this.moveDownBtn = new System.Windows.Forms.Button();
this.moveFirstBtn = new System.Windows.Forms.Button();
this.moveLastBtn = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
@ -49,18 +52,6 @@
this.pictureBox1.TabIndex = 0; this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false; this.pictureBox1.TabStop = false;
// //
// bookInfoLbl
//
this.bookInfoLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.bookInfoLbl.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.bookInfoLbl.Location = new System.Drawing.Point(89, 3);
this.bookInfoLbl.Name = "bookInfoLbl";
this.bookInfoLbl.Size = new System.Drawing.Size(255, 56);
this.bookInfoLbl.TabIndex = 1;
this.bookInfoLbl.Text = "[multi-\r\nline\r\nbook\r\n info]";
//
// progressBar1 // progressBar1
// //
this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
@ -81,17 +72,17 @@
this.remainingTimeLbl.Text = "--:--"; this.remainingTimeLbl.Text = "--:--";
this.remainingTimeLbl.TextAlign = System.Drawing.ContentAlignment.TopRight; this.remainingTimeLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
// //
// label1 // etaLbl
// //
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.etaLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.label1.AutoSize = true; this.etaLbl.AutoSize = true;
this.label1.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.etaLbl.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.label1.Location = new System.Drawing.Point(304, 66); this.etaLbl.Location = new System.Drawing.Point(304, 66);
this.label1.Name = "label1"; this.etaLbl.Name = "etaLbl";
this.label1.Size = new System.Drawing.Size(28, 13); this.etaLbl.Size = new System.Drawing.Size(28, 13);
this.label1.TabIndex = 3; this.etaLbl.TabIndex = 3;
this.label1.Text = "ETA:"; this.etaLbl.Text = "ETA:";
this.label1.TextAlign = System.Drawing.ContentAlignment.TopRight; this.etaLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
// //
// cancelBtn // cancelBtn
// //
@ -101,7 +92,7 @@
this.cancelBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; this.cancelBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.cancelBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.cancelBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.cancelBtn.ForeColor = System.Drawing.SystemColors.Control; this.cancelBtn.ForeColor = System.Drawing.SystemColors.Control;
this.cancelBtn.Location = new System.Drawing.Point(352, 3); this.cancelBtn.Location = new System.Drawing.Point(348, 6);
this.cancelBtn.Margin = new System.Windows.Forms.Padding(0); this.cancelBtn.Margin = new System.Windows.Forms.Padding(0);
this.cancelBtn.Name = "cancelBtn"; this.cancelBtn.Name = "cancelBtn";
this.cancelBtn.Size = new System.Drawing.Size(20, 20); this.cancelBtn.Size = new System.Drawing.Size(20, 20);
@ -109,53 +100,100 @@
this.cancelBtn.UseVisualStyleBackColor = false; this.cancelBtn.UseVisualStyleBackColor = false;
this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click); this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click);
// //
// statusLbl
//
this.statusLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.statusLbl.AutoSize = true;
this.statusLbl.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.statusLbl.Location = new System.Drawing.Point(89, 66);
this.statusLbl.Name = "statusLbl";
this.statusLbl.Size = new System.Drawing.Size(50, 13);
this.statusLbl.TabIndex = 3;
this.statusLbl.Text = "[STATUS]";
this.statusLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// bookInfoLbl
//
this.bookInfoLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.bookInfoLbl.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.bookInfoLbl.Location = new System.Drawing.Point(89, 6);
this.bookInfoLbl.Name = "bookInfoLbl";
this.bookInfoLbl.Size = new System.Drawing.Size(219, 56);
this.bookInfoLbl.TabIndex = 1;
this.bookInfoLbl.Text = "[multi-\r\nline\r\nbook\r\n info]";
//
// moveUpBtn // moveUpBtn
// //
this.moveUpBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.moveUpBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
this.moveUpBtn.BackColor = System.Drawing.Color.Transparent; | System.Windows.Forms.AnchorStyles.Right)));
this.moveUpBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveUpBtn.BackgroundImage"))); this.moveUpBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveUpBtn.BackgroundImage")));
this.moveUpBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; this.moveUpBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.moveUpBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.moveUpBtn.Location = new System.Drawing.Point(314, 24);
this.moveUpBtn.ForeColor = System.Drawing.SystemColors.Control;
this.moveUpBtn.Location = new System.Drawing.Point(347, 39);
this.moveUpBtn.Margin = new System.Windows.Forms.Padding(0);
this.moveUpBtn.Name = "moveUpBtn"; this.moveUpBtn.Name = "moveUpBtn";
this.moveUpBtn.Size = new System.Drawing.Size(25, 10); this.moveUpBtn.Size = new System.Drawing.Size(30, 17);
this.moveUpBtn.TabIndex = 4; this.moveUpBtn.TabIndex = 5;
this.moveUpBtn.UseVisualStyleBackColor = false; this.moveUpBtn.UseVisualStyleBackColor = true;
this.moveUpBtn.Click += new System.EventHandler(this.moveUpBtn_Click); this.moveUpBtn.Click += new System.EventHandler(this.moveUpBtn_Click_1);
// //
// moveDownBtn // moveDownBtn
// //
this.moveDownBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.moveDownBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
this.moveDownBtn.BackColor = System.Drawing.Color.Transparent; | System.Windows.Forms.AnchorStyles.Right)));
this.moveDownBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveDownBtn.BackgroundImage"))); this.moveDownBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveDownBtn.BackgroundImage")));
this.moveDownBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; this.moveDownBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.moveDownBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.moveDownBtn.Location = new System.Drawing.Point(314, 40);
this.moveDownBtn.ForeColor = System.Drawing.SystemColors.Control;
this.moveDownBtn.Location = new System.Drawing.Point(347, 49);
this.moveDownBtn.Margin = new System.Windows.Forms.Padding(0);
this.moveDownBtn.Name = "moveDownBtn"; this.moveDownBtn.Name = "moveDownBtn";
this.moveDownBtn.Size = new System.Drawing.Size(25, 10); this.moveDownBtn.Size = new System.Drawing.Size(30, 17);
this.moveDownBtn.TabIndex = 5; this.moveDownBtn.TabIndex = 5;
this.moveDownBtn.UseVisualStyleBackColor = false; this.moveDownBtn.UseVisualStyleBackColor = true;
this.moveDownBtn.Click += new System.EventHandler(this.moveDownBtn_Click); this.moveDownBtn.Click += new System.EventHandler(this.moveDownBtn_Click);
// //
// moveFirstBtn
//
this.moveFirstBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.moveFirstBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveFirstBtn.BackgroundImage")));
this.moveFirstBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.moveFirstBtn.Location = new System.Drawing.Point(314, 3);
this.moveFirstBtn.Name = "moveFirstBtn";
this.moveFirstBtn.Size = new System.Drawing.Size(30, 17);
this.moveFirstBtn.TabIndex = 5;
this.moveFirstBtn.UseVisualStyleBackColor = true;
this.moveFirstBtn.Click += new System.EventHandler(this.moveFirstBtn_Click);
//
// moveLastBtn
//
this.moveLastBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.moveLastBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveLastBtn.BackgroundImage")));
this.moveLastBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.moveLastBtn.Location = new System.Drawing.Point(314, 63);
this.moveLastBtn.Name = "moveLastBtn";
this.moveLastBtn.Size = new System.Drawing.Size(30, 17);
this.moveLastBtn.TabIndex = 5;
this.moveLastBtn.UseVisualStyleBackColor = true;
this.moveLastBtn.Click += new System.EventHandler(this.moveLastBtn_Click);
//
// ProcessBookControl // ProcessBookControl
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.ControlLight; this.BackColor = System.Drawing.SystemColors.ControlLight;
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.Controls.Add(this.moveLastBtn);
this.Controls.Add(this.moveDownBtn); this.Controls.Add(this.moveDownBtn);
this.Controls.Add(this.moveFirstBtn);
this.Controls.Add(this.moveUpBtn); this.Controls.Add(this.moveUpBtn);
this.Controls.Add(this.cancelBtn); this.Controls.Add(this.cancelBtn);
this.Controls.Add(this.label1); this.Controls.Add(this.statusLbl);
this.Controls.Add(this.etaLbl);
this.Controls.Add(this.remainingTimeLbl); this.Controls.Add(this.remainingTimeLbl);
this.Controls.Add(this.progressBar1); this.Controls.Add(this.progressBar1);
this.Controls.Add(this.bookInfoLbl); this.Controls.Add(this.bookInfoLbl);
this.Controls.Add(this.pictureBox1); this.Controls.Add(this.pictureBox1);
this.Margin = new System.Windows.Forms.Padding(2, 1, 2, 1); this.Margin = new System.Windows.Forms.Padding(2);
this.Name = "ProcessBookControl"; this.Name = "ProcessBookControl";
this.Size = new System.Drawing.Size(375, 86); this.Size = new System.Drawing.Size(375, 86);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
@ -167,12 +205,15 @@
#endregion #endregion
private System.Windows.Forms.PictureBox pictureBox1; private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Label bookInfoLbl;
private System.Windows.Forms.ProgressBar progressBar1; private System.Windows.Forms.ProgressBar progressBar1;
private System.Windows.Forms.Label remainingTimeLbl; private System.Windows.Forms.Label remainingTimeLbl;
private System.Windows.Forms.Label label1; private System.Windows.Forms.Label etaLbl;
private System.Windows.Forms.Button cancelBtn; private System.Windows.Forms.Button cancelBtn;
private System.Windows.Forms.Label statusLbl;
private System.Windows.Forms.Label bookInfoLbl;
private System.Windows.Forms.Button moveUpBtn; private System.Windows.Forms.Button moveUpBtn;
private System.Windows.Forms.Button moveDownBtn; private System.Windows.Forms.Button moveDownBtn;
private System.Windows.Forms.Button moveFirstBtn;
private System.Windows.Forms.Button moveLastBtn;
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Forms.Layout;
using DataLayer; using DataLayer;
using Dinah.Core.Net.Http; using Dinah.Core.Net.Http;
using Dinah.Core.Threading; using Dinah.Core.Threading;
@ -11,7 +12,7 @@ using LibationWinForms.ProcessQueue;
namespace LibationWinForms.ProcessQueue namespace LibationWinForms.ProcessQueue
{ {
internal interface ILiberationBaseForm internal interface ILiberatiofffnBaseForm
{ {
Action CancelAction { get; set; } Action CancelAction { get; set; }
Func<QueuePosition?> MoveUpAction { get; set; } Func<QueuePosition?> MoveUpAction { get; set; }
@ -25,11 +26,11 @@ namespace LibationWinForms.ProcessQueue
Padding Margin { get; set; } Padding Margin { get; set; }
} }
internal partial class ProcessBookControl : UserControl, ILiberationBaseForm internal partial class ProcessBookControl : UserControl
{ {
public ProcessBookStatus Status { get; private set; } = ProcessBookStatus.Queued;
public Action CancelAction { get; set; } public Action CancelAction { get; set; }
public Func<QueuePosition?> MoveUpAction { get; set; } public Func<QueuePositionRequest, QueuePosition?> RequestMoveAction { get; set; }
public Func<QueuePosition?> MoveDownAction { get; set; }
public string DecodeActionName { get; } = "Decoding"; public string DecodeActionName { get; } = "Decoding";
private Func<byte[]> GetCoverArtDelegate; private Func<byte[]> GetCoverArtDelegate;
protected Processable Processable { get; private set; } protected Processable Processable { get; private set; }
@ -37,47 +38,118 @@ namespace LibationWinForms.ProcessQueue
public ProcessBookControl() public ProcessBookControl()
{ {
InitializeComponent(); InitializeComponent();
label1.Text = "Queued"; statusLbl.Text = "Queued";
remainingTimeLbl.Visible = false; remainingTimeLbl.Visible = false;
progressBar1.Visible = false; progressBar1.Visible = false;
etaLbl.Visible = false;
} }
public void SetResult(ProcessBookResult status) public void SetCover(Image cover)
{ {
var statusTxt = status switch pictureBox1.Image = cover;
{ }
ProcessBookResult.Success => "Finished", public void SetTitle(string title)
ProcessBookResult.Cancelled => "Cancelled", {
ProcessBookResult.FailedRetry => "Error, Retry", bookInfoLbl.Text = title;
ProcessBookResult.FailedSkip => "Error, Skip", }
ProcessBookResult.FailedAbort => "Error, Abort",
_ => throw new NotImplementedException(),
};
Color backColor = status switch public void SetResult(ProcessBookResult result)
{
string statusText = default;
switch (result)
{ {
ProcessBookResult.Success => Color.PaleGreen, case ProcessBookResult.Success:
ProcessBookResult.Cancelled => Color.Khaki, statusText = "Finished";
ProcessBookResult.FailedRetry => Color.LightCoral, Status = ProcessBookStatus.Completed;
ProcessBookResult.FailedSkip => Color.LightCoral, break;
ProcessBookResult.FailedAbort => Color.Firebrick, case ProcessBookResult.Cancelled:
_ => throw new NotImplementedException(), statusText = "Cancelled";
}; Status = ProcessBookStatus.Cancelled;
break;
case ProcessBookResult.FailedRetry:
statusText = "Queued";
Status = ProcessBookStatus.Queued;
break;
case ProcessBookResult.FailedSkip:
statusText = "Error, Skip";
Status = ProcessBookStatus.Failed;
break;
case ProcessBookResult.FailedAbort:
statusText = "Error, Abort";
Status = ProcessBookStatus.Failed;
break;
case ProcessBookResult.ValidationFail:
statusText = "Validate fail";
Status = ProcessBookStatus.Failed;
break;
case ProcessBookResult.None:
statusText = "UNKNOWN";
Status = ProcessBookStatus.Failed;
break;
}
SetStatus(Status, statusText);
}
public void SetStatus(ProcessBookStatus status, string statusText)
{
Color backColor = default;
switch (status)
{
case ProcessBookStatus.Completed:
backColor = Color.PaleGreen;
Status = ProcessBookStatus.Completed;
break;
case ProcessBookStatus.Cancelled:
backColor = Color.Khaki;
Status = ProcessBookStatus.Cancelled;
break;
case ProcessBookStatus.Queued:
backColor = SystemColors.Control;
Status = ProcessBookStatus.Queued;
break;
case ProcessBookStatus.Working:
backColor = SystemColors.Control;
Status = ProcessBookStatus.Working;
break;
case ProcessBookStatus.Failed:
backColor = Color.LightCoral;
Status = ProcessBookStatus.Failed;
break;
}
this.UIThreadAsync(() => this.UIThreadAsync(() =>
{ {
cancelBtn.Visible = false; SuspendLayout();
moveDownBtn.Visible = false;
moveUpBtn.Visible = false; cancelBtn.Visible = Status is ProcessBookStatus.Queued or ProcessBookStatus.Working;
remainingTimeLbl.Visible = false; moveLastBtn.Visible = Status == ProcessBookStatus.Queued;
progressBar1.Visible = false; moveDownBtn.Visible = Status == ProcessBookStatus.Queued;
label1.Text = statusTxt; moveUpBtn.Visible = Status == ProcessBookStatus.Queued;
moveFirstBtn.Visible = Status == ProcessBookStatus.Queued;
remainingTimeLbl.Visible = Status == ProcessBookStatus.Working;
progressBar1.Visible = Status == ProcessBookStatus.Working;
etaLbl.Visible = Status == ProcessBookStatus.Working;
statusLbl.Visible = Status != ProcessBookStatus.Working;
statusLbl.Text = statusText;
BackColor = backColor; BackColor = backColor;
if (status == ProcessBookStatus.Working)
{
bookInfoLbl.Width += moveLastBtn.Width + moveLastBtn.Padding.Left + moveLastBtn.Padding.Right;
}
else
{
bookInfoLbl.Width -= moveLastBtn.Width + moveLastBtn.Padding.Left + moveLastBtn.Padding.Right;
}
ResumeLayout();
}); });
} }
public ProcessBookControl(string title, Image cover) : this() public ProcessBookControl(string title, Image cover) : this()
{ {
this.title = title;
pictureBox1.Image = cover; pictureBox1.Image = cover;
bookInfoLbl.Text = title; bookInfoLbl.Text = title;
} }
@ -190,14 +262,11 @@ namespace LibationWinForms.ProcessQueue
#region Processable event handlers #region Processable event handlers
public void Processable_Begin(object sender, LibraryBook libraryBook) public void Processable_Begin(object sender, LibraryBook libraryBook)
{ {
Status = ProcessBookStatus.Working;
LogMe.Info($"{Environment.NewLine}{Processable.Name} Step, Begin: {libraryBook.Book}"); LogMe.Info($"{Environment.NewLine}{Processable.Name} Step, Begin: {libraryBook.Book}");
this.UIThreadAsync(() => SetStatus(ProcessBookStatus.Working, "");
{
label1.Text = "ETA:";
remainingTimeLbl.Visible = true;
progressBar1.Visible = true;
});
GetCoverArtDelegate = () => PictureStorage.GetPictureSynchronously( GetCoverArtDelegate = () => PictureStorage.GetPictureSynchronously(
new PictureDefinition( new PictureDefinition(
@ -265,38 +334,29 @@ namespace LibationWinForms.ProcessQueue
CancelAction?.Invoke(); CancelAction?.Invoke();
} }
private void moveUpBtn_Click(object sender, EventArgs e) private void moveLastBtn_Click(object sender, EventArgs e)
{ {
HandleMovePositionResult(MoveUpAction?.Invoke()); RequestMoveAction?.Invoke(QueuePositionRequest.Last);
} }
private void moveFirstBtn_Click(object sender, EventArgs e)
{
RequestMoveAction?.Invoke(QueuePositionRequest.Fisrt);
}
private void moveUpBtn_Click_1(object sender, EventArgs e)
{
RequestMoveAction?.Invoke(QueuePositionRequest.OneUp);
}
private void moveDownBtn_Click(object sender, EventArgs e) private void moveDownBtn_Click(object sender, EventArgs e)
{ {
HandleMovePositionResult(MoveDownAction?.Invoke()); RequestMoveAction?.Invoke(QueuePositionRequest.OneDown);
} }
private void HandleMovePositionResult(QueuePosition? result) public override string ToString()
{ {
if (result.HasValue) return title ?? "NO TITLE";
SetQueuePosition(result.Value);
else
SetQueuePosition(QueuePosition.Absent);
}
public void SetQueuePosition(QueuePosition status)
{
if (status is QueuePosition.Absent or QueuePosition.Current)
{
moveUpBtn.Visible = false;
moveDownBtn.Visible = false;
}
if (status == QueuePosition.Absent)
cancelBtn.Enabled = false;
moveUpBtn.Enabled = status != QueuePosition.Fisrt;
moveDownBtn.Enabled = status != QueuePosition.Last;
} }
} }
} }

View File

@ -57,24 +57,6 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<metadata name="pictureBox1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="bookInfoLbl.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="progressBar1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="remainingTimeLbl.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="label1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="cancelBtn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="cancelBtn.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="cancelBtn.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
@ -737,62 +719,114 @@
/x9W31o+WFcHNAAAAABJRU5ErkJggg== /x9W31o+WFcHNAAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<metadata name="moveUpBtn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="moveUpBtn.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="moveUpBtn.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
</value> </value>
</data> </data>
<metadata name="moveDownBtn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="moveDownBtn.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="moveDownBtn.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
SUVORK5CYII= k4jTqP3QHyOvz3tlGAnrAXoYxoYTiVOpLcF1/lw+V4YRsR6gh2EKOJU4mdoyXPXTMkN8AqwH6GGYEk6n
qwOe1+XVMkyE9QA9DFPDCcUpxTefV+XJMkyI9QA9DHPAKfXa4T/D1FgPUMMY40ENY4wHNYwxHtQwxnhQ
wxjjQQ1jjAc1jDEe1DDGiJcX/wKcO4zm90rrbQAAAABJRU5ErkJggg==
</value>
</data>
<data name="moveFirstBtn.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAMgAAABZCAYAAAB7Ymt4AAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1
MAAA6mAAADqYAAAXb5JfxUYAAAAJcEhZcwAACwwAAAsMAT9AIsgAAAT8SURBVHhe7dlvp+ZVFMbxIWKI
iJ4OEdELiIiIIeZpRERERO8ghoiI6DUMERHRC4iIiOgFRERPI3oUp3WNWWPfa52z53fv+/dv//b34kNn
KR3n3Je9lnPr6urqWpZ7Rv8AjOTeSQ/KL0r6F4v/CBgFBQEqKAhQQUGACgoCVFAQoIKCABUUBKigIEAF
BQEqKAhQQUGACgoCVFAQoIKCABUUBKigIEAFBQEqKAhQQUGACgoCVFAQoIKCABWTC0KWz23zpSl/QdF3
5nlDVspJD8ovSmTxvGx+M2UZbvKXedOQFXLSg/KLElk0H5l/TVmCKb4wTxuyUFIP4sCRRaJV6XtTfujP
pVfnJUMWSOpBHDgye7QiaVUqP+yt9Pp8aMjMST2IA0dmi1YirUblB3wuHPAzJ/UgDhyZJVqFph7irf40
dw2ZIakHceDIxdEK1HKIt/rccMBfmNSDOHCkOVp5tPqUH961/Go44C9I6kEcONIUrTpaecoP7dr0an1g
SENSD+LAkbOy5CHeigO+IakHceDI5KxxiLfigD8zqQdx4MikrH2It+KAn5jUgzhwpJotD/FWHPATknoQ
B47cmD0c4q044J+Q1IM4cCRFK4pWlfID16tvzXOGhKQexIEjJ9FqohWl/JD1Tq/gG4YUST2IA0ceRytJ
D4d4q88MB/yjpB7EgSMPVxCtIuWH6ah+MRzwltSDOHCDR6tHr4d4Kw54S+pBHLhBo1VDK0f5wRnN0Ad8
6kEcuAGjFUOrRvlhGdWwB3zqQRy4wfK++ceUHxIMeMCnHsSBGyQjHeKthjrgUw/iwA2QEQ/xVnpd9coe
PqkHceAOHA7xdnptnzWHTepBHLiDhkP8cnp1XzeHTOpBHLgDhkN8Xp+awx3wqQdx4A4UrQQc4sv42Rzq
gE89iAN3kGgV4BBf1qEO+NSDOHCdR0+/VoDyF4llHeKATz2IA9dxXjR6+stfHtbR/QGfehAHrtO8ZzjE
t9ftAZ96EAeus+hp/8aUvyRsS6+4XvOuknoQB66j6En/w5S/HOyDXnO96t0k9SAOXAd5yugp/8+UvxTs
j173Lg741IM4cDsPh3h/9Mrv/oBPPYgDt+NwiPdLr/2uD/jUgzhwOwyH+HHs9oBPPYgDt7NwiB/PLg/4
1IM4cDsJh/jx7eqATz2IA7eDvGA4xMewmwM+9SAO3MZ513CIj8UPeG0NmyX1IA7cRtFT+7Upf3AYi7YG
bQ+bJPUgDtwGec38bsofFsak7UFbxOpJPYgDt2L0pH5iOMQRaZtY9YBPPYgDt1L0lP5kyh8KUNJWsdoB
n3oQB26FvGM4xDHFagd86kEcuAXzjPnKlD8AYIrFD/jUgzhwC+VVwyGOSyx6wKcexIGbORzimNsiB3zq
QRy4GcMhjqVoG9GfB2ZL6kEcuJnCIY6laSvRdjLLAZ96EAfuwnCIY23aUi4+4FMP4sBdEA5xbEXbiraW
5qQexIFriJ64+4ZDHFvT9tJ0wKcexIE7M3rafjTlNwlsqemATz2IA3dG3jZ/m/KbA/bg7AM+9SAO3ITo
EH9gym8I2KPJB3zqQRy4J+QVwyGOnkw64FMP4sDdED1VHxsOcfRKB7y2n2uTehAH7prcMT+Y8n8G9Ejb
j/4ckZJ6EAcu5C3DIY4j0RakP0ucHPCpB3HgHoVDHEenP088PuBTD+LAWTjEMQptRw8P+NMeXN36HzdL
jfkqyMbMAAAAAElFTkSuQmCC
</value>
</data>
<data name="moveLastBtn.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAMgAAABZCAYAAAB7Ymt4AAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1
MAAA6mAAADqYAAAXb5JfxUYAAAAJcEhZcwAACwwAAAsMAT9AIsgAAAUASURBVHhe7Zntpq1lFIYXERER
+wAiIjqAiIiIfQYRERHRGURERMQ+hoiIiA4gIiKivxER/YroV6zGncbezxxjrrHmmvP9eJ73vS6uH+uW
vVdrz9szbuvq+vr6wP95w/zLVIC4ZX8xX4w9cHPwiGfM78z2D0Pckp+ZT5qpB24ODnnM/MD8x2z/YMSR
/dN83XxI7IGbg+O8ZOopav8SxBH91tR1dEDsgZuDm3nK/Nxs/zLEUdQV9L6pqygRe+Dm4HYY8Dia/w1x
80ZiD9wcnIaeqO/N9ptA7NGHQ7wi9sDNwenoqfrQZMBjj+rKORjiFbEHbg7uzsvmr2b7zSGuqX49kYZ4
ReyBm4Pz0ID/wmy/ScSl1TWjX0scHeIVsQduDi6DAY9rqSGuX0ecReyBm4PLYcDj0urXD7pizib2wM3B
NDDgcQl1rehquZjYAzcH08KAx7nUlXKnIV4Re+DmYHoY8Dilukp0ndx5iFfEHrg5mI83TQY8XqKuEV0l
kxN74OZgXp41GfB4jhcP8YrYAzcH8/O4qSey/Z9HvMnJhnhF7IGbg+XQU/mb2f4wEFsnHeIVsQduDpZF
T+aXZvtDQZxliFfEHrg5WAcGPLqzDfGK2AM3B+vBgEf9OmC2IV4Re+DmYF0Y8PtU14OuiNWIPXBz0AcM
+P2oq0HXw6rEHrg56AcG/PbVtaCrYXViD9wc9MdbJgN+W+o6WHyIV8QeuDnok+fMH8z2h4xjqqtglSFe
EXvg5qBf9BR/ZLY/bBxHXQG6Brok9sDNQf+8YjLgx1Kvv66Abok9cHMwBk+bDPgx7GaIV8QeuDkYCwZ8
v3Y3xCtiD9wcjAcDvj+7HOIVsQduDsaEAd+HXQ/xitgDNwdjw4Bfz+6HeEXsgZuD8WHAL69e7+6HeEXs
gZuD7fC2+bfZ/kPitOq11qs9PLEHbg62hZ78H832HxWnUa+0XutNEHvg5mB76On/2Gz/cfF89Srrdd4U
sQduDrbLqyYD/jL1Gg87xCtiD9wcbBsG/PnqFR56iFfEHrg52AcM+NPVq6vXd9PEHrg52A8M+Nv9yrxn
bp7YAzcH+4IBf9xNDvGK2AM3B/uEAf/IzQ7xitgDNwf7RaeETor2w7I3Nz3EK2IP3BzAO+beBvwuhnhF
7IGbAxA6MX4y2w/RVt3NEK+IPXBzAI5OjU/M9sO0JfVK6rUEI/bAzQFEXjO3NuD1Ou5uiFfEHrg5gGNs
acDrVdzlEK+IPXBzABUjD/jfTb2GcITYAzcHcBsjDvivzd0P8YrYAzcHcAqjDHi9du+acAuxB24O4C7o
ZNHp0n4oe1Gv3PMmnEDsgZsDuCs6XXTCtB/Otf3UfMKEE4k9cHMA56JTZu0BzxA/k9gDNwdwCTpp1hrw
DPELiD1wcwCXotNmyQHPEJ+A2AM3BzAVSwx4hvhExB64OYApmXPAM8QnJPbAzQHMwZQD/g+TIT4xsQdu
DmAuphjw35gM8RmIPXBzAHOik0inUfuhP0W9Pu+ZMBOxB+7hF7AUOpF0KrUluMmfzRdMmJG2B62HX8CS
6FTSydSWIfrAZIgvQNuD1sMvrq7u679F3Jn32x60Hn5BQXCfUhDEQgqCWEhBEAspCGIhBUEspCCIhRQE
sZCCIBZSEMRCCoJYSEEQCykIYiEFQSykIIiFFASxkIIgFlIQxEIKglhIQRALKQhiIQVBLKQgiIU3FOT6
6l8KOJAbKVKmPQAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root> </root>

View File

@ -30,9 +30,10 @@
{ {
this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStripProgressBar1 = new System.Windows.Forms.ToolStripProgressBar(); this.toolStripProgressBar1 = new System.Windows.Forms.ToolStripProgressBar();
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage(); this.tabPage1 = new System.Windows.Forms.TabPage();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.virtualFlowControl2 = new LibationWinForms.ProcessQueue.VirtualFlowControl();
this.panel1 = new System.Windows.Forms.Panel(); this.panel1 = new System.Windows.Forms.Panel();
this.btnCleanFinished = new System.Windows.Forms.Button(); this.btnCleanFinished = new System.Windows.Forms.Button();
this.cancelAllBtn = new System.Windows.Forms.Button(); this.cancelAllBtn = new System.Windows.Forms.Button();
@ -40,7 +41,7 @@
this.panel2 = new System.Windows.Forms.Panel(); this.panel2 = new System.Windows.Forms.Panel();
this.clearLogBtn = new System.Windows.Forms.Button(); this.clearLogBtn = new System.Windows.Forms.Button();
this.logMeTbox = new System.Windows.Forms.TextBox(); this.logMeTbox = new System.Windows.Forms.TextBox();
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); this.tabPage3 = new System.Windows.Forms.TabPage();
this.statusStrip1.SuspendLayout(); this.statusStrip1.SuspendLayout();
this.tabControl1.SuspendLayout(); this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout(); this.tabPage1.SuspendLayout();
@ -56,7 +57,7 @@
this.toolStripStatusLabel1}); this.toolStripStatusLabel1});
this.statusStrip1.Location = new System.Drawing.Point(0, 486); this.statusStrip1.Location = new System.Drawing.Point(0, 486);
this.statusStrip1.Name = "statusStrip1"; this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(359, 22); this.statusStrip1.Size = new System.Drawing.Size(404, 22);
this.statusStrip1.TabIndex = 1; this.statusStrip1.TabIndex = 1;
this.statusStrip1.Text = "statusStrip1"; this.statusStrip1.Text = "statusStrip1";
// //
@ -65,6 +66,12 @@
this.toolStripProgressBar1.Name = "toolStripProgressBar1"; this.toolStripProgressBar1.Name = "toolStripProgressBar1";
this.toolStripProgressBar1.Size = new System.Drawing.Size(100, 16); this.toolStripProgressBar1.Size = new System.Drawing.Size(100, 16);
// //
// toolStripStatusLabel1
//
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
this.toolStripStatusLabel1.Size = new System.Drawing.Size(287, 17);
this.toolStripStatusLabel1.Spring = true;
//
// tabControl1 // tabControl1
// //
this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@ -72,38 +79,34 @@
| System.Windows.Forms.AnchorStyles.Right))); | System.Windows.Forms.AnchorStyles.Right)));
this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Controls.Add(this.tabPage3);
this.tabControl1.Location = new System.Drawing.Point(0, 0); this.tabControl1.Location = new System.Drawing.Point(0, 0);
this.tabControl1.Margin = new System.Windows.Forms.Padding(0); this.tabControl1.Margin = new System.Windows.Forms.Padding(0);
this.tabControl1.Name = "tabControl1"; this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0; this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(360, 486); this.tabControl1.Size = new System.Drawing.Size(405, 486);
this.tabControl1.TabIndex = 3; this.tabControl1.TabIndex = 3;
// //
// tabPage1 // tabPage1
// //
this.tabPage1.Controls.Add(this.flowLayoutPanel1); this.tabPage1.Controls.Add(this.virtualFlowControl2);
this.tabPage1.Controls.Add(this.panel1); this.tabPage1.Controls.Add(this.panel1);
this.tabPage1.Location = new System.Drawing.Point(4, 24); this.tabPage1.Location = new System.Drawing.Point(4, 24);
this.tabPage1.Name = "tabPage1"; this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3); this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(352, 458); this.tabPage1.Size = new System.Drawing.Size(397, 458);
this.tabPage1.TabIndex = 0; this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "Process Queue"; this.tabPage1.Text = "Process Queue";
this.tabPage1.UseVisualStyleBackColor = true; this.tabPage1.UseVisualStyleBackColor = true;
// //
// flowLayoutPanel1 // virtualFlowControl2
// //
this.flowLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) this.virtualFlowControl2.Dock = System.Windows.Forms.DockStyle.Fill;
| System.Windows.Forms.AnchorStyles.Left) this.virtualFlowControl2.Location = new System.Drawing.Point(3, 3);
| System.Windows.Forms.AnchorStyles.Right))); this.virtualFlowControl2.Name = "virtualFlowControl2";
this.flowLayoutPanel1.AutoScroll = true; this.virtualFlowControl2.Size = new System.Drawing.Size(391, 422);
this.flowLayoutPanel1.BackColor = System.Drawing.SystemColors.ControlDarkDark; this.virtualFlowControl2.TabIndex = 3;
this.flowLayoutPanel1.Location = new System.Drawing.Point(3, 3); this.virtualFlowControl2.VirtualControlCount = 0;
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
this.flowLayoutPanel1.Size = new System.Drawing.Size(346, 419);
this.flowLayoutPanel1.TabIndex = 0;
this.flowLayoutPanel1.ClientSizeChanged += new System.EventHandler(this.flowLayoutPanel1_ClientSizeChanged);
this.flowLayoutPanel1.Layout += new System.Windows.Forms.LayoutEventHandler(this.flowLayoutPanel1_Layout);
// //
// panel1 // panel1
// //
@ -113,14 +116,14 @@
this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom;
this.panel1.Location = new System.Drawing.Point(3, 425); this.panel1.Location = new System.Drawing.Point(3, 425);
this.panel1.Name = "panel1"; this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(346, 30); this.panel1.Size = new System.Drawing.Size(391, 30);
this.panel1.TabIndex = 2; this.panel1.TabIndex = 2;
// //
// btnCleanFinished // btnCleanFinished
// //
this.btnCleanFinished.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) this.btnCleanFinished.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right))); | System.Windows.Forms.AnchorStyles.Right)));
this.btnCleanFinished.Location = new System.Drawing.Point(253, 3); this.btnCleanFinished.Location = new System.Drawing.Point(298, 3);
this.btnCleanFinished.Name = "btnCleanFinished"; this.btnCleanFinished.Name = "btnCleanFinished";
this.btnCleanFinished.Size = new System.Drawing.Size(90, 23); this.btnCleanFinished.Size = new System.Drawing.Size(90, 23);
this.btnCleanFinished.TabIndex = 3; this.btnCleanFinished.TabIndex = 3;
@ -147,7 +150,7 @@
this.tabPage2.Location = new System.Drawing.Point(4, 24); this.tabPage2.Location = new System.Drawing.Point(4, 24);
this.tabPage2.Name = "tabPage2"; this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3); this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(352, 458); this.tabPage2.Size = new System.Drawing.Size(397, 458);
this.tabPage2.TabIndex = 1; this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "Log"; this.tabPage2.Text = "Log";
this.tabPage2.UseVisualStyleBackColor = true; this.tabPage2.UseVisualStyleBackColor = true;
@ -159,7 +162,7 @@
this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom; this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom;
this.panel2.Location = new System.Drawing.Point(3, 425); this.panel2.Location = new System.Drawing.Point(3, 425);
this.panel2.Name = "panel2"; this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(346, 30); this.panel2.Size = new System.Drawing.Size(391, 30);
this.panel2.TabIndex = 1; this.panel2.TabIndex = 1;
// //
// clearLogBtn // clearLogBtn
@ -189,11 +192,15 @@
this.logMeTbox.Size = new System.Drawing.Size(346, 419); this.logMeTbox.Size = new System.Drawing.Size(346, 419);
this.logMeTbox.TabIndex = 0; this.logMeTbox.TabIndex = 0;
// //
// toolStripStatusLabel1 // tabPage3
// //
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; this.tabPage3.Location = new System.Drawing.Point(4, 24);
this.toolStripStatusLabel1.Size = new System.Drawing.Size(211, 17); this.tabPage3.Name = "tabPage3";
this.toolStripStatusLabel1.Spring = true; this.tabPage3.Padding = new System.Windows.Forms.Padding(3);
this.tabPage3.Size = new System.Drawing.Size(397, 458);
this.tabPage3.TabIndex = 2;
this.tabPage3.Text = "tabPage3";
this.tabPage3.UseVisualStyleBackColor = true;
// //
// ProcessBookQueue // ProcessBookQueue
// //
@ -203,7 +210,7 @@
this.Controls.Add(this.tabControl1); this.Controls.Add(this.tabControl1);
this.Controls.Add(this.statusStrip1); this.Controls.Add(this.statusStrip1);
this.Name = "ProcessBookQueue"; this.Name = "ProcessBookQueue";
this.Size = new System.Drawing.Size(359, 508); this.Size = new System.Drawing.Size(404, 508);
this.statusStrip1.ResumeLayout(false); this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout(); this.statusStrip1.PerformLayout();
this.tabControl1.ResumeLayout(false); this.tabControl1.ResumeLayout(false);
@ -222,7 +229,6 @@
private System.Windows.Forms.ToolStripProgressBar toolStripProgressBar1; private System.Windows.Forms.ToolStripProgressBar toolStripProgressBar1;
private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.Panel panel1; private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.TabPage tabPage2;
private System.Windows.Forms.TextBox logMeTbox; private System.Windows.Forms.TextBox logMeTbox;
@ -231,5 +237,7 @@
private System.Windows.Forms.Panel panel2; private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.Button clearLogBtn; private System.Windows.Forms.Button clearLogBtn;
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
private System.Windows.Forms.TabPage tabPage3;
private VirtualFlowControl virtualFlowControl2;
} }
} }

View File

@ -12,11 +12,8 @@ namespace LibationWinForms.ProcessQueue
{ {
internal partial class ProcessBookQueue : UserControl, ILogForm internal partial class ProcessBookQueue : UserControl, ILogForm
{ {
private ProcessBook CurrentBook; TrackedQueue<ProcessBook> Queue = new();
private readonly LinkedList<ProcessBook> BookQueue = new();
private readonly List<ProcessBook> CompletedBooks = new();
private readonly LogMe Logger; private readonly LogMe Logger;
private readonly object lockObject = new();
public Task QueueRunner { get; private set; } public Task QueueRunner { get; private set; }
@ -29,7 +26,6 @@ namespace LibationWinForms.ProcessQueue
InitializeComponent(); InitializeComponent();
Logger = LogMe.RegisterForm(this); Logger = LogMe.RegisterForm(this);
this.popoutBtn.DisplayStyle = ToolStripItemDisplayStyle.Text; this.popoutBtn.DisplayStyle = ToolStripItemDisplayStyle.Text;
this.popoutBtn.Name = "popoutBtn"; this.popoutBtn.Name = "popoutBtn";
this.popoutBtn.Text = "Pop Out"; this.popoutBtn.Text = "Pop Out";
@ -38,17 +34,35 @@ namespace LibationWinForms.ProcessQueue
this.popoutBtn.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; this.popoutBtn.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
statusStrip1.Items.Add(popoutBtn); statusStrip1.Items.Add(popoutBtn);
}
public async Task AddDownloadDecrypt(IEnumerable<GridEntry> entries) virtualFlowControl2.RequestData += VirtualFlowControl1_RequestData;
{
foreach (var entry in entries)
await AddDownloadDecryptAsync(entry);
} }
private void VirtualFlowControl1_RequestData(int firstIndex, int numVisible, IReadOnlyList<ProcessBookControl> panelsToFill)
{
int numToShow = Math.Min(numVisible, Queue.Count - firstIndex);
for (int i = 0; i < numToShow; i++)
{
var proc = Queue[firstIndex + i];
panelsToFill[i].SetCover(proc.Entry.Cover);
panelsToFill[i].SetTitle(proc.Entry.Title);
}
}
public async Task AddDownloadDecrypt(IEnumerable<GridEntry> entries)
{
SuspendLayout();
foreach (var entry in entries)
await AddDownloadDecryptAsync(entry);
ResumeLayout();
}
int count = 0;
public async Task AddDownloadDecryptAsync(GridEntry gridEntry) public async Task AddDownloadDecryptAsync(GridEntry gridEntry)
{ {
if (BookExists(gridEntry.LibraryBook)) //if (Queue.Any(b=> b?.Entry?.AudibleProductId == gridEntry.AudibleProductId))
return; //return;
ProcessBook pbook = new ProcessBook(gridEntry, Logger); ProcessBook pbook = new ProcessBook(gridEntry, Logger);
pbook.Completed += Pbook_Completed; pbook.Completed += Pbook_Completed;
@ -63,24 +77,24 @@ namespace LibationWinForms.ProcessQueue
if (libStatus.PdfStatus != LiberatedStatus.Liberated) if (libStatus.PdfStatus != LiberatedStatus.Liberated)
pbook.AddPdfProcessable(); pbook.AddPdfProcessable();
EnqueueBook(pbook); Queue.EnqueueBook(pbook);
await AddBookControlAsync(pbook.BookControl); //await AddBookControlAsync(pbook.BookControl);
count++;
virtualFlowControl2.VirtualControlCount = count;
if (!Running) if (!Running)
{ {
QueueRunner = QueueLoop(); //QueueRunner = QueueLoop();
} }
toolStripStatusLabel1.Text = count.ToString();
} }
private async void Pbook_Cancelled(ProcessBook sender, EventArgs e) private async void Pbook_Cancelled(ProcessBook sender, EventArgs e)
{ {
lock (lockObject) Queue.Remove(sender);
{ //await RemoveBookControlAsync(sender.BookControl);
if (BookQueue.Contains(sender))
BookQueue.Remove(sender);
}
await RemoveBookControlAsync(sender.BookControl);
} }
/// <summary> /// <summary>
@ -89,76 +103,54 @@ namespace LibationWinForms.ProcessQueue
/// <param name="sender">The requesting <see cref="ProcessBook"/></param> /// <param name="sender">The requesting <see cref="ProcessBook"/></param>
/// <param name="direction">The requested position</param> /// <param name="direction">The requested position</param>
/// <returns>The resultant position</returns> /// <returns>The resultant position</returns>
private QueuePosition RequestMove(ProcessBook sender, QueuePosition direction) private QueuePosition RequestMove(ProcessBook sender, QueuePositionRequest requested)
{ {
var node = BookQueue.Find(sender);
if (node == null || direction == QueuePosition.Absent) var direction = Queue.MoveQueuePosition(sender, requested);
return QueuePosition.Absent;
if (CurrentBook != null && CurrentBook == sender)
return QueuePosition.Current;
if ((direction == QueuePosition.Fisrt || direction == QueuePosition.OneUp) && BookQueue.First.Value == sender)
return QueuePosition.Fisrt;
if ((direction == QueuePosition.Last || direction == QueuePosition.OneDown) && BookQueue.Last.Value == sender)
return QueuePosition.Last;
if (direction == QueuePosition.OneUp) if (direction is QueuePosition.Absent or QueuePosition.Current or QueuePosition.Completed)
{ return direction;
var oneUp = node.Previous; return direction;
BookQueue.Remove(node);
BookQueue.AddBefore(oneUp, node.Value);
}
else if (direction == QueuePosition.OneDown)
{
var oneDown = node.Next;
BookQueue.Remove(node);
BookQueue.AddAfter(oneDown, node.Value);
}
else if (direction == QueuePosition.Fisrt)
{
BookQueue.Remove(node);
BookQueue.AddFirst(node);
}
else
{
BookQueue.Remove(node);
BookQueue.AddLast(node);
}
var index = flowLayoutPanel1.Controls.IndexOf((Control)sender.BookControl); /*
index = direction switch var firstQueue = autosizeFlowLayout1.Controls.Cast<ProcessBookControl>().FirstOrDefault(c => c.Status == ProcessBookStatus.Queued);
if (firstQueue is null) return QueuePosition.Current;
int firstQueueIndex = autosizeFlowLayout1.Controls.IndexOf(firstQueue);
var index = autosizeFlowLayout1.Controls.IndexOf(sender.BookControl);
int newIndex = direction switch
{ {
QueuePosition.Fisrt => 0, QueuePosition.Fisrt => firstQueueIndex,
QueuePosition.OneUp => index - 1, QueuePosition.OneUp => index - 1,
QueuePosition.OneDown => index + 1, QueuePosition.OneDown => index + 1,
QueuePosition.Last => flowLayoutPanel1.Controls.Count - 1, QueuePosition.Last => autosizeFlowLayout1.Controls.Count - 1,
_ => throw new NotImplementedException(), _ => -1,
}; };
flowLayoutPanel1.Controls.SetChildIndex((Control)sender.BookControl, index); if (newIndex < 0) return direction;
autosizeFlowLayout1.Controls.SetChildIndex(sender.BookControl, newIndex);
if (index == 0) return QueuePosition.Fisrt;
if (index == flowLayoutPanel1.Controls.Count - 1) return QueuePosition.Last;
return direction; return direction;
*/
} }
private async Task QueueLoop() private async Task QueueLoop()
{ {
while (MoreInQueue()) while (Queue.MoveNext())
{ {
var nextBook = NextBook(); var nextBook = Queue.Current;
nextBook.BookControl.SetQueuePosition(QueuePosition.Current);
PeekBook()?.BookControl.SetQueuePosition(QueuePosition.Fisrt);
var result = await nextBook.ProcessOneAsync(); var result = await nextBook.ProcessOneAsync();
AddCompletedBook(nextBook);
switch (result) switch (result)
{ {
case ProcessBookResult.FailedRetry: case ProcessBookResult.FailedRetry:
EnqueueBook(nextBook); Queue.EnqueueBook(nextBook);
break; break;
case ProcessBookResult.FailedAbort: case ProcessBookResult.FailedAbort:
return; return;
@ -166,108 +158,62 @@ namespace LibationWinForms.ProcessQueue
} }
} }
private bool BookExists(LibraryBook libraryBook)
{
lock (lockObject)
{
return CurrentBook?.Entry?.AudibleProductId == libraryBook.Book.AudibleProductId ||
CompletedBooks.Union(BookQueue).Any(p => p.Entry.AudibleProductId == libraryBook.Book.AudibleProductId);
}
}
private ProcessBook NextBook()
{
lock (lockObject)
{
CurrentBook = BookQueue.First.Value;
BookQueue.RemoveFirst();
return CurrentBook;
}
}
private ProcessBook PeekBook()
{
lock (lockObject)
return BookQueue.Count > 0 ? BookQueue.First.Value : default;
}
private void EnqueueBook(ProcessBook pbook)
{
lock (lockObject)
BookQueue.AddLast(pbook);
}
private void AddCompletedBook(ProcessBook pbook)
{
lock (lockObject)
CompletedBooks.Add(pbook);
}
private bool MoreInQueue()
{
lock (lockObject)
return BookQueue.Count > 0;
}
private void Pbook_Completed(object sender, EventArgs e) private void Pbook_Completed(object sender, EventArgs e)
{ {
if (CurrentBook == sender)
CurrentBook = default;
} }
private async void cancelAllBtn_Click(object sender, EventArgs e) private async void cancelAllBtn_Click(object sender, EventArgs e)
{ {
List<ProcessBook> l1 = new(); List<ProcessBook> l1 = Queue.QueuedItems();
lock (lockObject)
{
l1.AddRange(BookQueue);
BookQueue.Clear();
}
CurrentBook?.Cancel();
CurrentBook = default;
await RemoveBookControlsAsync(l1.Select(l => l.BookControl)); Queue.ClearQueue();
Queue.Current?.Cancel();
//await RemoveBookControlsAsync(l1.Select(l => l.BookControl));
} }
private async void btnCleanFinished_Click(object sender, EventArgs e) private async void btnCleanFinished_Click(object sender, EventArgs e)
{ {
List<ProcessBook> l1 = new(); List<ProcessBook> l1 = Queue.CompletedItems();
lock (lockObject) Queue.ClearCompleted();
{ //await RemoveBookControlsAsync(l1.Select(l => l.BookControl));
l1.AddRange(CompletedBooks);
CompletedBooks.Clear();
}
await RemoveBookControlsAsync(l1.Select(l => l.BookControl));
} }
private async Task AddBookControlAsync(ILiberationBaseForm control) private async Task AddBookControlAsync(ProcessBookControl control)
{ {
await Task.Run(() => Invoke(() => await Task.Run(() => Invoke(() =>
{ {
SetBookControlWidth((Control)control); /*
flowLayoutPanel1.Controls.Add((Control)control); control.Width = autosizeFlowLayout1.DesiredBookControlWidth;
flowLayoutPanel1.SetFlowBreak((Control)control, true); autosizeFlowLayout1.Controls.Add(control);
Refresh(); autosizeFlowLayout1.SetFlowBreak(control, true);
*/
//Refresh();
//System.Threading.Thread.Sleep(1000);
})); }));
} }
private async Task RemoveBookControlAsync(ILiberationBaseForm control) private async Task RemoveBookControlAsync(ProcessBookControl control)
{ {
await Task.Run(() => Invoke(() => await Task.Run(() => Invoke(() =>
{ {
flowLayoutPanel1.Controls.Remove((Control)control); //autosizeFlowLayout1.Controls.Remove(control);
})); }));
} }
private async Task RemoveBookControlsAsync(IEnumerable<ILiberationBaseForm> control) private async Task RemoveBookControlsAsync(IEnumerable<ProcessBookControl> control)
{ {
await Task.Run(() => Invoke(() => await Task.Run(() => Invoke(() =>
{ {
/*
SuspendLayout(); SuspendLayout();
foreach (var l in control) foreach (var l in control)
flowLayoutPanel1.Controls.Remove((Control)l); autosizeFlowLayout1.Controls.Remove(l);
ResumeLayout(); ResumeLayout();
*/
})); }));
} }
@ -282,62 +228,5 @@ namespace LibationWinForms.ProcessQueue
logMeTbox.Clear(); logMeTbox.Clear();
} }
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
private static extern long GetWindowLongPtr(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
private static extern bool ShowScrollBar(IntPtr hWnd, SBOrientation bar, bool show);
public const int WS_VSCROLL = 0x200000;
public const int WS_HSCROLL = 0x100000;
enum SBOrientation : int
{
SB_HORZ = 0,
SB_VERT = 1,
SB_CTL = 2,
SB_BOTH = 3
}
private void flowLayoutPanel1_ClientSizeChanged(object sender, EventArgs e)
{
ReorderControls();
}
private void flowLayoutPanel1_Layout(object sender, LayoutEventArgs e)
{
ReorderControls();
}
bool V_SHOWN = false;
private void ReorderControls()
{
bool hShown = (GetWindowLongPtr(flowLayoutPanel1.Handle, -16) & WS_HSCROLL) != 0;
bool vShown = (GetWindowLongPtr(flowLayoutPanel1.Handle, -16) & WS_VSCROLL) != 0;
if (hShown)
ShowScrollBar(flowLayoutPanel1.Handle, SBOrientation.SB_HORZ, false);
if (vShown != V_SHOWN)
{
flowLayoutPanel1.SuspendLayout();
foreach (Control c in flowLayoutPanel1.Controls)
SetBookControlWidth(c);
flowLayoutPanel1.ResumeLayout();
V_SHOWN = vShown;
}
}
private void SetBookControlWidth(Control book)
{
book.Width = flowLayoutPanel1.ClientRectangle.Width - book.Margin.Left - book.Margin.Right;
}
private void toolStripSplitButton1_ButtonClick(object sender, EventArgs e)
{
}
} }
} }

View File

@ -0,0 +1,58 @@
namespace LibationWinForms.ProcessQueue
{
partial class VirtualFlowControl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// panel1
//
this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panel1.BackColor = System.Drawing.Color.PaleGreen;
this.panel1.Location = new System.Drawing.Point(0, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(359, 507);
this.panel1.TabIndex = 0;
//
// VirtualFlowControl
//
this.Controls.Add(this.panel1);
this.Name = "VirtualFlowControl";
this.Size = new System.Drawing.Size(379, 507);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel panel1;
}
}

View File

@ -0,0 +1,146 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace LibationWinForms.ProcessQueue
{
internal delegate void RequestDataDelegate(int firstIndex, int numVisible, ProcessBookControl[] panelsToFill);
internal partial class VirtualFlowControl : UserControl
{
public event RequestDataDelegate RequestData;
public int VirtualControlCount
{
get => _virtualControlCount;
set
{
if (_virtualControlCount == 0)
vScrollBar1.Value = 0;
_virtualControlCount = value;
AdjustScrollBar();
DoVirtualScroll();
}
}
private int _virtualControlCount;
private int VirtualHeight => _virtualControlCount * CONTROL_HEIGHT - vScrollBar1.Height;
private readonly int PROCESSBOOKCONTROL_MARGIN;
private readonly int CONTROL_HEIGHT;
private const int WM_MOUSEWHEEL = 522;
private const int NUM_ACTUAL_CONTROLS = 20;
private const int SCROLL_SMALL_CHANGE = 120;
private const int SCROLL_LARGE_CHANGE = 3 * SCROLL_SMALL_CHANGE;
private readonly VScrollBar vScrollBar1;
private readonly ProcessBookControl[] BookControls = new ProcessBookControl[NUM_ACTUAL_CONTROLS];
public VirtualFlowControl()
{
InitializeComponent();
vScrollBar1 = new VScrollBar
{
Minimum = 0,
Value = 0,
SmallChange = SCROLL_SMALL_CHANGE,
LargeChange = SCROLL_LARGE_CHANGE,
Dock = DockStyle.Right
};
Controls.Add(vScrollBar1);
panel1.Resize += (_, _) => AdjustScrollBar();
if (this.DesignMode)
return;
vScrollBar1.Scroll += (_, _) => DoVirtualScroll();
for (int i = 0; i < NUM_ACTUAL_CONTROLS; i++)
{
BookControls[i] = new ProcessBookControl();
if (i == 0)
{
PROCESSBOOKCONTROL_MARGIN = BookControls[i].Margin.Left + BookControls[i].Margin.Right;
CONTROL_HEIGHT = BookControls[i].Height + BookControls[i].Margin.Top + BookControls[i].Margin.Bottom;
}
BookControls[i].Location = new Point(2, CONTROL_HEIGHT * i);
BookControls[i].Width = panel1.ClientRectangle.Width - PROCESSBOOKCONTROL_MARGIN;
BookControls[i].Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
panel1.Controls.Add(BookControls[i]);
}
panel1.Height += SCROLL_SMALL_CHANGE;
}
private void AdjustScrollBar()
{
int maxFullVisible = DisplayRectangle.Height / CONTROL_HEIGHT;
if (VirtualControlCount <= maxFullVisible)
{
vScrollBar1.Enabled = false;
for (int i = VirtualControlCount; i < NUM_ACTUAL_CONTROLS; i++)
BookControls[i].Visible = false;
}
else
{
vScrollBar1.Enabled = true;
//https://stackoverflow.com/a/2882878/3335599
vScrollBar1.Maximum = VirtualHeight + vScrollBar1.LargeChange - 1;
}
}
private void DoVirtualScroll()
{
//https://stackoverflow.com/a/2882878/3335599
int scrollValue = Math.Max(Math.Min(VirtualHeight, vScrollBar1.Value), 0);
int position = scrollValue % CONTROL_HEIGHT;
panel1.Location = new Point(0, -position);
int firstVisible = scrollValue / CONTROL_HEIGHT;
int window = DisplayRectangle.Height;
int count = window / CONTROL_HEIGHT;
if (window % CONTROL_HEIGHT != 0)
count++;
count = Math.Min(count, VirtualControlCount);
RequestData?.Invoke(firstVisible, count, BookControls);
for (int i = 0; i < BookControls.Length; i++)
BookControls[i].Visible = i <= count && VirtualControlCount > 0;
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEWHEEL)
{
//https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-mousewheel
int wheelDelta = -(short)(((ulong)m.WParam) >> 16 & 0xffff);
if (wheelDelta > 0)
vScrollBar1.Value = Math.Min(vScrollBar1.Value + wheelDelta, vScrollBar1.Maximum);
else
vScrollBar1.Value = Math.Max(vScrollBar1.Value + wheelDelta, vScrollBar1.Minimum);
DoVirtualScroll();
}
base.WndProc(ref m);
}
}
}

View File

@ -0,0 +1,60 @@
<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>