From 763a6cb31ad179a910a06ae335c76339864a2e25 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Fri, 13 May 2022 00:21:41 -0600 Subject: [PATCH] Added VirtualFlowControl and BookQueue --- .../ProcessQueue/BookQueue.cs | 175 +++++++++++ .../ProcessQueue/ProcessBook.cs | 53 ++-- .../ProcessBookControl.Designer.cs | 139 +++++---- .../ProcessQueue/ProcessBookControl.cs | 176 +++++++---- .../ProcessQueue/ProcessBookControl.resx | 170 ++++++----- .../ProcessQueue/ProcessBookQueue.Designer.cs | 64 ++-- .../ProcessQueue/ProcessBookQueue.cs | 277 ++++++------------ .../VirtualFlowControl.Designer.cs | 58 ++++ .../ProcessQueue/VirtualFlowControl.cs | 146 +++++++++ .../ProcessQueue/VirtualFlowControl.resx | 60 ++++ 10 files changed, 902 insertions(+), 416 deletions(-) create mode 100644 Source/LibationWinForms/ProcessQueue/BookQueue.cs create mode 100644 Source/LibationWinForms/ProcessQueue/VirtualFlowControl.Designer.cs create mode 100644 Source/LibationWinForms/ProcessQueue/VirtualFlowControl.cs create mode 100644 Source/LibationWinForms/ProcessQueue/VirtualFlowControl.resx diff --git a/Source/LibationWinForms/ProcessQueue/BookQueue.cs b/Source/LibationWinForms/ProcessQueue/BookQueue.cs new file mode 100644 index 00000000..c36554ab --- /dev/null +++ b/Source/LibationWinForms/ProcessQueue/BookQueue.cs @@ -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 where T : class + { + public T Current { get; private set; } + private readonly LinkedList Queued = new(); + private readonly List 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 QueuedItems() + { + lock (lockObject) + return Queued.ToList(); + } + public List 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 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); + } + + } +} diff --git a/Source/LibationWinForms/ProcessQueue/ProcessBook.cs b/Source/LibationWinForms/ProcessQueue/ProcessBook.cs index df142e56..2792ca81 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessBook.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessBook.cs @@ -16,22 +16,39 @@ namespace LibationWinForms.ProcessQueue None, Success, Cancelled, + ValidationFail, FailedRetry, FailedSkip, FailedAbort } + public enum ProcessBookStatus + { + Queued, + Cancelled, + Working, + Completed, + Failed + } internal enum QueuePosition { Absent, + Completed, Current, Fisrt, OneUp, OneDown, 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(ProcessBook sender, T arg); internal delegate void ProcessControlEventArgs(ProcessBook sender, EventArgs arg); @@ -41,7 +58,7 @@ namespace LibationWinForms.ProcessQueue public event ProcessControlEventArgs Cancelled; public event ProcessControlReorderHandler RequestMove; public GridEntry Entry { get; } - public ILiberationBaseForm BookControl { get; } + //public ProcessBookControl BookControl { get; } private Func _makeFirstProc; private Processable _firstProcessable; @@ -55,20 +72,15 @@ namespace LibationWinForms.ProcessQueue public ProcessBook(GridEntry entry, LogMe logme) { Entry = entry; - BookControl = new ProcessBookControl(Entry.Title, Entry.Cover); - BookControl.CancelAction = Cancel; - BookControl.MoveUpAction = MoveUp; - BookControl.MoveDownAction = MoveDown; + //BookControl = new ProcessBookControl(Entry.Title, Entry.Cover); + //BookControl.CancelAction = Cancel; + //BookControl.RequestMoveAction = MoveRequested; Logger = logme; } - public QueuePosition? MoveUp() + public QueuePosition? MoveRequested(QueuePositionRequest requestedPosition) { - return RequestMove?.Invoke(this, QueuePosition.OneUp); - } - public QueuePosition? MoveDown() - { - return RequestMove?.Invoke(this, QueuePosition.OneDown); + return RequestMove?.Invoke(this, requestedPosition); } public void Cancel() @@ -94,11 +106,9 @@ namespace LibationWinForms.ProcessQueue ProcessBookResult result = ProcessBookResult.None; try { - var firstProc = FirstProcessable; + LinkProcessable(FirstProcessable); - LinkProcessable(firstProc); - - var statusHandler = await firstProc.ProcessSingleAsync(Entry.LibraryBook, validate: true); + var statusHandler = await FirstProcessable.ProcessSingleAsync(Entry.LibraryBook, validate: true); if (statusHandler.IsSuccess) @@ -108,6 +118,11 @@ namespace LibationWinForms.ProcessQueue Logger.Info($"Process was cancelled {Entry.LibraryBook.Book}"); 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) Logger.Error(errorMessage); @@ -121,7 +136,7 @@ namespace LibationWinForms.ProcessQueue if (result == ProcessBookResult.None) result = showRetry(Entry.LibraryBook); - BookControl.SetResult(result); + //BookControl.SetResult(result); } return result; @@ -149,8 +164,8 @@ namespace LibationWinForms.ProcessQueue private void Processable_Begin(object sender, LibraryBook libraryBook) { - BookControl.RegisterFileLiberator((Processable)sender, Logger); - BookControl.Processable_Begin(sender, libraryBook); + //BookControl.RegisterFileLiberator((Processable)sender, Logger); + //BookControl.Processable_Begin(sender, libraryBook); } private async void Processable_Completed(object sender, LibraryBook e) diff --git a/Source/LibationWinForms/ProcessQueue/ProcessBookControl.Designer.cs b/Source/LibationWinForms/ProcessQueue/ProcessBookControl.Designer.cs index ee395dd3..e77e0211 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessBookControl.Designer.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessBookControl.Designer.cs @@ -30,13 +30,16 @@ { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProcessBookControl)); this.pictureBox1 = new System.Windows.Forms.PictureBox(); - this.bookInfoLbl = new System.Windows.Forms.Label(); this.progressBar1 = new System.Windows.Forms.ProgressBar(); 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.statusLbl = new System.Windows.Forms.Label(); + this.bookInfoLbl = new System.Windows.Forms.Label(); this.moveUpBtn = 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(); this.SuspendLayout(); // @@ -49,18 +52,6 @@ this.pictureBox1.TabIndex = 0; 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 // 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.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.label1.AutoSize = true; - this.label1.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.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(28, 13); - this.label1.TabIndex = 3; - this.label1.Text = "ETA:"; - this.label1.TextAlign = System.Drawing.ContentAlignment.TopRight; + this.etaLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.etaLbl.AutoSize = true; + this.etaLbl.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.etaLbl.Location = new System.Drawing.Point(304, 66); + this.etaLbl.Name = "etaLbl"; + this.etaLbl.Size = new System.Drawing.Size(28, 13); + this.etaLbl.TabIndex = 3; + this.etaLbl.Text = "ETA:"; + this.etaLbl.TextAlign = System.Drawing.ContentAlignment.TopRight; // // cancelBtn // @@ -101,7 +92,7 @@ this.cancelBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; this.cancelBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 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.Name = "cancelBtn"; this.cancelBtn.Size = new System.Drawing.Size(20, 20); @@ -109,53 +100,100 @@ this.cancelBtn.UseVisualStyleBackColor = false; 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 // - this.moveUpBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.moveUpBtn.BackColor = System.Drawing.Color.Transparent; + this.moveUpBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Right))); this.moveUpBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveUpBtn.BackgroundImage"))); - this.moveUpBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; - this.moveUpBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat; - 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.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; + this.moveUpBtn.Location = new System.Drawing.Point(314, 24); this.moveUpBtn.Name = "moveUpBtn"; - this.moveUpBtn.Size = new System.Drawing.Size(25, 10); - this.moveUpBtn.TabIndex = 4; - this.moveUpBtn.UseVisualStyleBackColor = false; - this.moveUpBtn.Click += new System.EventHandler(this.moveUpBtn_Click); + this.moveUpBtn.Size = new System.Drawing.Size(30, 17); + this.moveUpBtn.TabIndex = 5; + this.moveUpBtn.UseVisualStyleBackColor = true; + this.moveUpBtn.Click += new System.EventHandler(this.moveUpBtn_Click_1); // // moveDownBtn // - this.moveDownBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.moveDownBtn.BackColor = System.Drawing.Color.Transparent; + this.moveDownBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Right))); this.moveDownBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveDownBtn.BackgroundImage"))); - this.moveDownBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; - this.moveDownBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat; - 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.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; + this.moveDownBtn.Location = new System.Drawing.Point(314, 40); 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.UseVisualStyleBackColor = false; + this.moveDownBtn.UseVisualStyleBackColor = true; 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 // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.SystemColors.ControlLight; this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.Controls.Add(this.moveLastBtn); this.Controls.Add(this.moveDownBtn); + this.Controls.Add(this.moveFirstBtn); this.Controls.Add(this.moveUpBtn); 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.progressBar1); this.Controls.Add(this.bookInfoLbl); 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.Size = new System.Drawing.Size(375, 86); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); @@ -167,12 +205,15 @@ #endregion private System.Windows.Forms.PictureBox pictureBox1; - private System.Windows.Forms.Label bookInfoLbl; private System.Windows.Forms.ProgressBar progressBar1; 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.Label statusLbl; + private System.Windows.Forms.Label bookInfoLbl; private System.Windows.Forms.Button moveUpBtn; private System.Windows.Forms.Button moveDownBtn; + private System.Windows.Forms.Button moveFirstBtn; + private System.Windows.Forms.Button moveLastBtn; } } diff --git a/Source/LibationWinForms/ProcessQueue/ProcessBookControl.cs b/Source/LibationWinForms/ProcessQueue/ProcessBookControl.cs index f0875715..76f73368 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessBookControl.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessBookControl.cs @@ -1,6 +1,7 @@ using System; using System.Drawing; using System.Windows.Forms; +using System.Windows.Forms.Layout; using DataLayer; using Dinah.Core.Net.Http; using Dinah.Core.Threading; @@ -11,7 +12,7 @@ using LibationWinForms.ProcessQueue; namespace LibationWinForms.ProcessQueue { - internal interface ILiberationBaseForm + internal interface ILiberatiofffnBaseForm { Action CancelAction { get; set; } Func MoveUpAction { get; set; } @@ -25,11 +26,11 @@ namespace LibationWinForms.ProcessQueue 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 Func MoveUpAction { get; set; } - public Func MoveDownAction { get; set; } + public Func RequestMoveAction { get; set; } public string DecodeActionName { get; } = "Decoding"; private Func GetCoverArtDelegate; protected Processable Processable { get; private set; } @@ -37,47 +38,118 @@ namespace LibationWinForms.ProcessQueue public ProcessBookControl() { InitializeComponent(); - label1.Text = "Queued"; + statusLbl.Text = "Queued"; remainingTimeLbl.Visible = false; progressBar1.Visible = false; + etaLbl.Visible = false; } - public void SetResult(ProcessBookResult status) + public void SetCover(Image cover) { - var statusTxt = status switch - { - ProcessBookResult.Success => "Finished", - ProcessBookResult.Cancelled => "Cancelled", - ProcessBookResult.FailedRetry => "Error, Retry", - ProcessBookResult.FailedSkip => "Error, Skip", - ProcessBookResult.FailedAbort => "Error, Abort", - _ => throw new NotImplementedException(), - }; + pictureBox1.Image = cover; + } + public void SetTitle(string title) + { + bookInfoLbl.Text = title; + } - Color backColor = status switch + public void SetResult(ProcessBookResult result) + { + string statusText = default; + switch (result) { - ProcessBookResult.Success => Color.PaleGreen, - ProcessBookResult.Cancelled => Color.Khaki, - ProcessBookResult.FailedRetry => Color.LightCoral, - ProcessBookResult.FailedSkip => Color.LightCoral, - ProcessBookResult.FailedAbort => Color.Firebrick, - _ => throw new NotImplementedException(), - }; + case ProcessBookResult.Success: + statusText = "Finished"; + Status = ProcessBookStatus.Completed; + break; + case ProcessBookResult.Cancelled: + 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(() => { - cancelBtn.Visible = false; - moveDownBtn.Visible = false; - moveUpBtn.Visible = false; - remainingTimeLbl.Visible = false; - progressBar1.Visible = false; - label1.Text = statusTxt; + SuspendLayout(); + + cancelBtn.Visible = Status is ProcessBookStatus.Queued or ProcessBookStatus.Working; + moveLastBtn.Visible = Status == ProcessBookStatus.Queued; + moveDownBtn.Visible = Status == ProcessBookStatus.Queued; + 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; + + 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() { + this.title = title; pictureBox1.Image = cover; bookInfoLbl.Text = title; } @@ -190,14 +262,11 @@ namespace LibationWinForms.ProcessQueue #region Processable event handlers public void Processable_Begin(object sender, LibraryBook libraryBook) { + Status = ProcessBookStatus.Working; + LogMe.Info($"{Environment.NewLine}{Processable.Name} Step, Begin: {libraryBook.Book}"); - this.UIThreadAsync(() => - { - label1.Text = "ETA:"; - remainingTimeLbl.Visible = true; - progressBar1.Visible = true; - }); + SetStatus(ProcessBookStatus.Working, ""); GetCoverArtDelegate = () => PictureStorage.GetPictureSynchronously( new PictureDefinition( @@ -265,38 +334,29 @@ namespace LibationWinForms.ProcessQueue 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) { - HandleMovePositionResult(MoveDownAction?.Invoke()); + RequestMoveAction?.Invoke(QueuePositionRequest.OneDown); } - private void HandleMovePositionResult(QueuePosition? result) + public override string ToString() { - if (result.HasValue) - 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; + return title ?? "NO TITLE"; } } } diff --git a/Source/LibationWinForms/ProcessQueue/ProcessBookControl.resx b/Source/LibationWinForms/ProcessQueue/ProcessBookControl.resx index 180633dc..a91b8cad 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessBookControl.resx +++ b/Source/LibationWinForms/ProcessQueue/ProcessBookControl.resx @@ -57,24 +57,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True - - - True - - - True - - - True - - - True - - - True - @@ -737,62 +719,114 @@ /x9W31o+WFcHNAAAAABJRU5ErkJggg== - - True - - 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 - - True - - iVBORw0KGgoAAAANSUhEUgAAAKoAAABXCAYAAACUet5FAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1 - MAAA6mAAADqYAAAXb5JfxUYAAAAJcEhZcwAACwwAAAsMAT9AIsgAAAQ+SURBVHhe7dLLcRsxFERRrRyH - Q3DICtEZ0NOy6aKoq+H0fB+AXpxNVwFvc99ut1tEeThGVINjRDU4RlSDY0Q1OEZUg6O83X78mvyeTEPE - 4d6pwzsc76bHiTXOMBup4Pho+iSxxpFeRio4Pps+S6xxhEWRCo5k+jSxxp4WRyo4kunjxBp7sSIVHMn0 - eWKNPdiRCo5kOpBYY6tVkQqOZDryLLGGY3WkgiOZDpHEGktsilRwJNOx7yTWmPM+waYcOBIdm5FYg3xE - KtSUA0dyPzgjscaj/5EKNeXAkTwenZFYQz5FKtSUA0fyfHhGYh3bl0iFmnLgSOj4jMQ6JoxUqCkHjoSO - v5BYx/JtpEJNOXAkdHyBxDqG2UiFmnLgSOj4Qom1by8jFWrKgSOh44bE2qdFkQo15cCR0HFTYu3L4kiF - mnLgSOj4Com1D1akQk05cCR0fKXE2jY7UqGmHDgSOr5BYm3TqkiFmnLgSOj4Rom1LasjFWrKgSOh4ztI - rG3YFKlQUw4cCR3fSWKtbXOkQk05cCR0fEeJtaZdIhVqyoEjoeM7S6y17BapUFMOHAkdP0BirWHXSIWa - cuBI6PhBEuu1do9UqCkHjoSOHyixXuOQSIWacuBI6PjBEuu5DotUqCkHjoSOnyCxnuPQSIWacuBI6PhJ - EuuxDo9UqCkHjoSOnyixHuOUSIWacuBI6PjJEuu+TotUqCkHjoSOXyCx7uPUSIWacuBI6PhFEus2p0cq - 1JQDR0LHL5RY17kkUqGmHDgSOn6xxOq5LFKhphw4EjpeQGJd5tJIhZpy4EjoeBGJdd7lkQo15cCR0PFC - EisrEalQUw4cCR0vJrF+ViZSoaYcOBI6XlBi/atUpEJNOXAkdLyo0WMtF6lQUw4cCR0vbNRYS0Yq1JQD - R0LHixst1rKRCjXlwJHQ8QaMEmvpSIWacuBI6Hgjeo+1fKRCTTlwJHS8Ib3G2kSkQk05cCR0vDG9xdpM - pEJNOXAkdLxBvcTaVKRCTTlwJHS8Ua3H2lykQk05cCR0vGGtxtpkpEJNOXAkdLxxrcXabKRCTTlwJHS8 - A63E2nSkQk05cCR0vBPVY20+UqGmHDgSOt6RqrF2EalQUw4cCR3vTLVYu4lUqCkHjoSOd6hKrF1FKtSU - A0dCxzt1dazdRSrUlANHQsc7dlWsXUYq1JQDR0LHO3d2rN1GKtSUA0dCxwdwVqxdRyrUlANHQscHcXSs - 3Ucq1JQDR0LHB3JUrENEKtSUA0dCxwezd6zDRCrUlANHQscHtFesQ0Uq1JQDR0LHB7U11uEiFWrKgSOh - 4wNbG+uQkQo15cCR0PHBubEOG6lQUw4cCR2PxbEOHalQUw4cCR2PD69iHT5SoaYcOBI6Hv99F2si/Yea - cuBI6Hh88hxrIn1ATTlwJHQ8vrjHmkifUFMOHAkdD/QTtuFRUw4cI6rBMaKW29sfKR2pZX+g2KEAAAAA - SUVORK5CYII= + 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 + jfkqyMbMAAAAAElFTkSuQmCC + + + + + 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== - - True - \ No newline at end of file diff --git a/Source/LibationWinForms/ProcessQueue/ProcessBookQueue.Designer.cs b/Source/LibationWinForms/ProcessQueue/ProcessBookQueue.Designer.cs index 62848fbe..fd0d0322 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessBookQueue.Designer.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessBookQueue.Designer.cs @@ -30,9 +30,10 @@ { this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.toolStripProgressBar1 = new System.Windows.Forms.ToolStripProgressBar(); + this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); this.tabControl1 = new System.Windows.Forms.TabControl(); 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.btnCleanFinished = new System.Windows.Forms.Button(); this.cancelAllBtn = new System.Windows.Forms.Button(); @@ -40,7 +41,7 @@ this.panel2 = new System.Windows.Forms.Panel(); this.clearLogBtn = new System.Windows.Forms.Button(); 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.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); @@ -56,7 +57,7 @@ this.toolStripStatusLabel1}); this.statusStrip1.Location = new System.Drawing.Point(0, 486); 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.Text = "statusStrip1"; // @@ -65,6 +66,12 @@ this.toolStripProgressBar1.Name = "toolStripProgressBar1"; 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 // 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))); this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); this.tabControl1.Location = new System.Drawing.Point(0, 0); this.tabControl1.Margin = new System.Windows.Forms.Padding(0); this.tabControl1.Name = "tabControl1"; 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; // // tabPage1 // - this.tabPage1.Controls.Add(this.flowLayoutPanel1); + this.tabPage1.Controls.Add(this.virtualFlowControl2); this.tabPage1.Controls.Add(this.panel1); this.tabPage1.Location = new System.Drawing.Point(4, 24); this.tabPage1.Name = "tabPage1"; 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.Text = "Process Queue"; this.tabPage1.UseVisualStyleBackColor = true; // - // flowLayoutPanel1 + // virtualFlowControl2 // - this.flowLayoutPanel1.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.flowLayoutPanel1.AutoScroll = true; - this.flowLayoutPanel1.BackColor = System.Drawing.SystemColors.ControlDarkDark; - this.flowLayoutPanel1.Location = new System.Drawing.Point(3, 3); - 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); + this.virtualFlowControl2.Dock = System.Windows.Forms.DockStyle.Fill; + this.virtualFlowControl2.Location = new System.Drawing.Point(3, 3); + this.virtualFlowControl2.Name = "virtualFlowControl2"; + this.virtualFlowControl2.Size = new System.Drawing.Size(391, 422); + this.virtualFlowControl2.TabIndex = 3; + this.virtualFlowControl2.VirtualControlCount = 0; // // panel1 // @@ -113,14 +116,14 @@ this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; this.panel1.Location = new System.Drawing.Point(3, 425); 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; // // btnCleanFinished // this.btnCleanFinished.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | 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.Size = new System.Drawing.Size(90, 23); this.btnCleanFinished.TabIndex = 3; @@ -147,7 +150,7 @@ this.tabPage2.Location = new System.Drawing.Point(4, 24); this.tabPage2.Name = "tabPage2"; 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.Text = "Log"; this.tabPage2.UseVisualStyleBackColor = true; @@ -159,7 +162,7 @@ this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom; this.panel2.Location = new System.Drawing.Point(3, 425); 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; // // clearLogBtn @@ -189,11 +192,15 @@ this.logMeTbox.Size = new System.Drawing.Size(346, 419); this.logMeTbox.TabIndex = 0; // - // toolStripStatusLabel1 + // tabPage3 // - this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; - this.toolStripStatusLabel1.Size = new System.Drawing.Size(211, 17); - this.toolStripStatusLabel1.Spring = true; + this.tabPage3.Location = new System.Drawing.Point(4, 24); + this.tabPage3.Name = "tabPage3"; + 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 // @@ -203,7 +210,7 @@ this.Controls.Add(this.tabControl1); this.Controls.Add(this.statusStrip1); 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.PerformLayout(); this.tabControl1.ResumeLayout(false); @@ -222,7 +229,6 @@ private System.Windows.Forms.ToolStripProgressBar toolStripProgressBar1; private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage tabPage1; - private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.Panel panel1; private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.TextBox logMeTbox; @@ -231,5 +237,7 @@ private System.Windows.Forms.Panel panel2; private System.Windows.Forms.Button clearLogBtn; private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; + private System.Windows.Forms.TabPage tabPage3; + private VirtualFlowControl virtualFlowControl2; } } diff --git a/Source/LibationWinForms/ProcessQueue/ProcessBookQueue.cs b/Source/LibationWinForms/ProcessQueue/ProcessBookQueue.cs index af748764..3c0b37c6 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessBookQueue.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessBookQueue.cs @@ -12,11 +12,8 @@ namespace LibationWinForms.ProcessQueue { internal partial class ProcessBookQueue : UserControl, ILogForm { - private ProcessBook CurrentBook; - private readonly LinkedList BookQueue = new(); - private readonly List CompletedBooks = new(); + TrackedQueue Queue = new(); private readonly LogMe Logger; - private readonly object lockObject = new(); public Task QueueRunner { get; private set; } @@ -29,7 +26,6 @@ namespace LibationWinForms.ProcessQueue InitializeComponent(); Logger = LogMe.RegisterForm(this); - this.popoutBtn.DisplayStyle = ToolStripItemDisplayStyle.Text; this.popoutBtn.Name = "popoutBtn"; this.popoutBtn.Text = "Pop Out"; @@ -38,17 +34,35 @@ namespace LibationWinForms.ProcessQueue this.popoutBtn.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; statusStrip1.Items.Add(popoutBtn); - } - public async Task AddDownloadDecrypt(IEnumerable entries) - { - foreach (var entry in entries) - await AddDownloadDecryptAsync(entry); + + virtualFlowControl2.RequestData += VirtualFlowControl1_RequestData; + } + private void VirtualFlowControl1_RequestData(int firstIndex, int numVisible, IReadOnlyList 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 entries) + { + SuspendLayout(); + foreach (var entry in entries) + await AddDownloadDecryptAsync(entry); + ResumeLayout(); + } + int count = 0; public async Task AddDownloadDecryptAsync(GridEntry gridEntry) { - if (BookExists(gridEntry.LibraryBook)) - return; + //if (Queue.Any(b=> b?.Entry?.AudibleProductId == gridEntry.AudibleProductId)) + //return; ProcessBook pbook = new ProcessBook(gridEntry, Logger); pbook.Completed += Pbook_Completed; @@ -63,24 +77,24 @@ namespace LibationWinForms.ProcessQueue if (libStatus.PdfStatus != LiberatedStatus.Liberated) pbook.AddPdfProcessable(); - EnqueueBook(pbook); + Queue.EnqueueBook(pbook); - await AddBookControlAsync(pbook.BookControl); + //await AddBookControlAsync(pbook.BookControl); + count++; + + virtualFlowControl2.VirtualControlCount = count; if (!Running) { - QueueRunner = QueueLoop(); + //QueueRunner = QueueLoop(); } + toolStripStatusLabel1.Text = count.ToString(); } private async void Pbook_Cancelled(ProcessBook sender, EventArgs e) { - lock (lockObject) - { - if (BookQueue.Contains(sender)) - BookQueue.Remove(sender); - } - await RemoveBookControlAsync(sender.BookControl); + Queue.Remove(sender); + //await RemoveBookControlAsync(sender.BookControl); } /// @@ -89,76 +103,54 @@ namespace LibationWinForms.ProcessQueue /// The requesting /// The requested position /// The resultant position - 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) - 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; + var direction = Queue.MoveQueuePosition(sender, requested); - if (direction == QueuePosition.OneUp) - { - var oneUp = node.Previous; - 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); - } + if (direction is QueuePosition.Absent or QueuePosition.Current or QueuePosition.Completed) + return direction; + return direction; - var index = flowLayoutPanel1.Controls.IndexOf((Control)sender.BookControl); + /* - index = direction switch + var firstQueue = autosizeFlowLayout1.Controls.Cast().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.OneDown => index + 1, - QueuePosition.Last => flowLayoutPanel1.Controls.Count - 1, - _ => throw new NotImplementedException(), + QueuePosition.Last => autosizeFlowLayout1.Controls.Count - 1, + _ => -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; + */ } private async Task QueueLoop() { - while (MoreInQueue()) + while (Queue.MoveNext()) { - var nextBook = NextBook(); - nextBook.BookControl.SetQueuePosition(QueuePosition.Current); - PeekBook()?.BookControl.SetQueuePosition(QueuePosition.Fisrt); + var nextBook = Queue.Current; var result = await nextBook.ProcessOneAsync(); - AddCompletedBook(nextBook); - switch (result) { case ProcessBookResult.FailedRetry: - EnqueueBook(nextBook); + Queue.EnqueueBook(nextBook); break; case ProcessBookResult.FailedAbort: 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) { - if (CurrentBook == sender) - CurrentBook = default; + } private async void cancelAllBtn_Click(object sender, EventArgs e) { - List l1 = new(); - lock (lockObject) - { - l1.AddRange(BookQueue); - BookQueue.Clear(); - } - CurrentBook?.Cancel(); - CurrentBook = default; + List l1 = Queue.QueuedItems(); - 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) { - List l1 = new(); - lock (lockObject) - { - l1.AddRange(CompletedBooks); - CompletedBooks.Clear(); - } - - await RemoveBookControlsAsync(l1.Select(l => l.BookControl)); + List l1 = Queue.CompletedItems(); + Queue.ClearCompleted(); + //await RemoveBookControlsAsync(l1.Select(l => l.BookControl)); } - private async Task AddBookControlAsync(ILiberationBaseForm control) + private async Task AddBookControlAsync(ProcessBookControl control) { await Task.Run(() => Invoke(() => { - SetBookControlWidth((Control)control); - flowLayoutPanel1.Controls.Add((Control)control); - flowLayoutPanel1.SetFlowBreak((Control)control, true); - Refresh(); + /* + control.Width = autosizeFlowLayout1.DesiredBookControlWidth; + autosizeFlowLayout1.Controls.Add(control); + 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(() => { - flowLayoutPanel1.Controls.Remove((Control)control); + //autosizeFlowLayout1.Controls.Remove(control); })); } - private async Task RemoveBookControlsAsync(IEnumerable control) + private async Task RemoveBookControlsAsync(IEnumerable control) { await Task.Run(() => Invoke(() => { + /* SuspendLayout(); foreach (var l in control) - flowLayoutPanel1.Controls.Remove((Control)l); + autosizeFlowLayout1.Controls.Remove(l); ResumeLayout(); + */ })); } @@ -282,62 +228,5 @@ namespace LibationWinForms.ProcessQueue 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) - { - - } } } diff --git a/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.Designer.cs b/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.Designer.cs new file mode 100644 index 00000000..3b215429 --- /dev/null +++ b/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.Designer.cs @@ -0,0 +1,58 @@ +namespace LibationWinForms.ProcessQueue +{ + partial class VirtualFlowControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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; + } +} diff --git a/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.cs b/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.cs new file mode 100644 index 00000000..c6a1966c --- /dev/null +++ b/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.cs @@ -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); + } + } +} diff --git a/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.resx b/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.resx new file mode 100644 index 00000000..f298a7be --- /dev/null +++ b/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file