Refactor Classic process queue
The queue is now more MVVM-like.
This commit is contained in:
parent
7e79e98771
commit
747451d243
@ -22,6 +22,49 @@ namespace LibationWinForms.ProcessQueue
|
|||||||
public static Color QueuedColor = SystemColors.Control;
|
public static Color QueuedColor = SystemColors.Control;
|
||||||
public static Color SuccessColor = Color.PaleGreen;
|
public static Color SuccessColor = Color.PaleGreen;
|
||||||
|
|
||||||
|
private ProcessBookViewModelBase m_Context;
|
||||||
|
public ProcessBookViewModelBase Context
|
||||||
|
{
|
||||||
|
get => m_Context;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (m_Context != value)
|
||||||
|
{
|
||||||
|
OnContextChanging();
|
||||||
|
m_Context = value;
|
||||||
|
OnContextChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnContextChanging()
|
||||||
|
{
|
||||||
|
if (Context is not null)
|
||||||
|
Context.PropertyChanged -= Context_PropertyChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnContextChanged()
|
||||||
|
{
|
||||||
|
Context.PropertyChanged += Context_PropertyChanged;
|
||||||
|
Context_PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Context_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
SuspendLayout();
|
||||||
|
if (e.PropertyName is null or nameof(Context.Cover))
|
||||||
|
SetCover(Context.Cover as Image);
|
||||||
|
if (e.PropertyName is null or nameof(Context.Title) or nameof(Context.Author) or nameof(Context.Narrator))
|
||||||
|
SetBookInfo($"{Context.Title}\r\nBy {Context.Author}\r\nNarrated by {Context.Narrator}");
|
||||||
|
if (e.PropertyName is null or nameof(Context.Status) or nameof(Context.StatusText))
|
||||||
|
SetStatus(Context.Status, Context.StatusText);
|
||||||
|
if (e.PropertyName is null or nameof(Context.Progress))
|
||||||
|
SetProgress(Context.Progress);
|
||||||
|
if (e.PropertyName is null or nameof(Context.TimeRemaining))
|
||||||
|
SetRemainingTime(Context.TimeRemaining);
|
||||||
|
ResumeLayout();
|
||||||
|
}
|
||||||
|
|
||||||
public ProcessBookControl()
|
public ProcessBookControl()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|||||||
@ -162,7 +162,6 @@
|
|||||||
this.virtualFlowControl2.Name = "virtualFlowControl2";
|
this.virtualFlowControl2.Name = "virtualFlowControl2";
|
||||||
this.virtualFlowControl2.Size = new System.Drawing.Size(390, 424);
|
this.virtualFlowControl2.Size = new System.Drawing.Size(390, 424);
|
||||||
this.virtualFlowControl2.TabIndex = 3;
|
this.virtualFlowControl2.TabIndex = 3;
|
||||||
this.virtualFlowControl2.VirtualControlCount = 0;
|
|
||||||
//
|
//
|
||||||
// panel1
|
// panel1
|
||||||
//
|
//
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
using LibationFileManager;
|
using LibationFileManager;
|
||||||
using LibationUiBase;
|
using LibationUiBase;
|
||||||
using LibationUiBase.ProcessQueue;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
@ -34,12 +31,11 @@ internal partial class ProcessQueueControl : UserControl
|
|||||||
numericUpDown1.Value = speedLimitMBps > numericUpDown1.Maximum || speedLimitMBps < numericUpDown1.Minimum ? 0 : speedLimitMBps;
|
numericUpDown1.Value = speedLimitMBps > numericUpDown1.Maximum || speedLimitMBps < numericUpDown1.Minimum ? 0 : speedLimitMBps;
|
||||||
statusStrip1.Items.Add(PopoutButton);
|
statusStrip1.Items.Add(PopoutButton);
|
||||||
|
|
||||||
virtualFlowControl2.RequestData += VirtualFlowControl1_RequestData;
|
|
||||||
virtualFlowControl2.ButtonClicked += VirtualFlowControl2_ButtonClicked;
|
virtualFlowControl2.ButtonClicked += VirtualFlowControl2_ButtonClicked;
|
||||||
|
|
||||||
ViewModel.LogWritten += (_, text) => WriteLine(text);
|
ViewModel.LogWritten += (_, text) => WriteLine(text);
|
||||||
ViewModel.PropertyChanged += ProcessQueue_PropertyChanged;
|
ViewModel.PropertyChanged += ProcessQueue_PropertyChanged;
|
||||||
ViewModel.BookPropertyChanged += ProcessBook_PropertyChanged;
|
virtualFlowControl2.Items = ViewModel.Items;
|
||||||
Load += ProcessQueueControl_Load;
|
Load += ProcessQueueControl_Load;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,15 +56,13 @@ internal partial class ProcessQueueControl : UserControl
|
|||||||
ViewModel.Queue.ClearQueue();
|
ViewModel.Queue.ClearQueue();
|
||||||
if (ViewModel.Queue.Current is not null)
|
if (ViewModel.Queue.Current is not null)
|
||||||
await ViewModel.Queue.Current.CancelAsync();
|
await ViewModel.Queue.Current.CancelAsync();
|
||||||
virtualFlowControl2.VirtualControlCount = ViewModel.Queue.Count;
|
virtualFlowControl2.RefreshDisplay();
|
||||||
UpdateAllControls();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnClearFinished_Click(object? sender, EventArgs e)
|
private void btnClearFinished_Click(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
ViewModel.Queue.ClearCompleted();
|
ViewModel.Queue.ClearCompleted();
|
||||||
virtualFlowControl2.VirtualControlCount = ViewModel.Queue.Count;
|
virtualFlowControl2.RefreshDisplay();
|
||||||
UpdateAllControls();
|
|
||||||
|
|
||||||
if (!ViewModel.Running)
|
if (!ViewModel.Running)
|
||||||
runningTimeLbl.Text = string.Empty;
|
runningTimeLbl.Text = string.Empty;
|
||||||
@ -92,22 +86,13 @@ internal partial class ProcessQueueControl : UserControl
|
|||||||
|
|
||||||
#region View-Model update event handling
|
#region View-Model update event handling
|
||||||
|
|
||||||
private void ProcessBook_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (sender is not ProcessBookViewModel pbvm)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int index = ViewModel.Queue.IndexOf(pbvm);
|
|
||||||
UpdateControl(index, e.PropertyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProcessQueue_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
private void ProcessQueue_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.PropertyName is null or nameof(ViewModel.QueuedCount))
|
if (e.PropertyName is null or nameof(ViewModel.QueuedCount))
|
||||||
{
|
{
|
||||||
queueNumberLbl.Text = ViewModel.QueuedCount.ToString();
|
queueNumberLbl.Text = ViewModel.QueuedCount.ToString();
|
||||||
queueNumberLbl.Visible = ViewModel.QueuedCount > 0;
|
queueNumberLbl.Visible = ViewModel.QueuedCount > 0;
|
||||||
virtualFlowControl2.VirtualControlCount = ViewModel.Queue.Count;
|
virtualFlowControl2.RefreshDisplay();
|
||||||
}
|
}
|
||||||
if (e.PropertyName is null or nameof(ViewModel.ErrorCount))
|
if (e.PropertyName is null or nameof(ViewModel.ErrorCount))
|
||||||
{
|
{
|
||||||
@ -134,107 +119,41 @@ internal partial class ProcessQueueControl : UserControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Index of the first <see cref="ProcessBookViewModel"/> visible in the <see cref="VirtualFlowControl"/>
|
|
||||||
/// </summary>
|
|
||||||
private int FirstVisible = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// Number of <see cref="ProcessBookViewModel"/> visible in the <see cref="VirtualFlowControl"/>
|
|
||||||
/// </summary>
|
|
||||||
private int NumVisible = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// Controls displaying the <see cref="ProcessBookViewModel"/> state, starting with <see cref="FirstVisible"/>
|
|
||||||
/// </summary>
|
|
||||||
private IReadOnlyList<ProcessBookControl>? Panels;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the display of a single <see cref="ProcessBookControl"/> at <paramref name="queueIndex"/> within <see cref="Queue"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="queueIndex">index of the <see cref="ProcessBookViewModel"/> within the <see cref="Queue"/></param>
|
|
||||||
/// <param name="propertyName">The nme of the property that needs updating. If null, all properties are updated.</param>
|
|
||||||
private void UpdateControl(int queueIndex, string? propertyName = null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int i = queueIndex - FirstVisible;
|
|
||||||
|
|
||||||
if (Panels is null || i > NumVisible || i < 0) return;
|
|
||||||
|
|
||||||
var proc = ViewModel.Queue[queueIndex];
|
|
||||||
|
|
||||||
Invoke(() =>
|
|
||||||
{
|
|
||||||
Panels[i].SuspendLayout();
|
|
||||||
if (propertyName is null or nameof(proc.Cover))
|
|
||||||
Panels[i].SetCover(proc.Cover as Image);
|
|
||||||
if (propertyName is null or nameof(proc.Title) or nameof(proc.Author) or nameof(proc.Narrator))
|
|
||||||
Panels[i].SetBookInfo($"{proc.Title}\r\nBy {proc.Author}\r\nNarrated by {proc.Narrator}");
|
|
||||||
if (propertyName is null or nameof(proc.Status) or nameof(proc.StatusText))
|
|
||||||
Panels[i].SetStatus(proc.Status, proc.StatusText);
|
|
||||||
if (propertyName is null or nameof(proc.Progress))
|
|
||||||
Panels[i].SetProgress(proc.Progress);
|
|
||||||
if (propertyName is null or nameof(proc.TimeRemaining))
|
|
||||||
Panels[i].SetRemainingTime(proc.TimeRemaining);
|
|
||||||
Panels[i].ResumeLayout();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Serilog.Log.Logger.Error(ex, "Error updating the queued item's display.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateAllControls()
|
|
||||||
{
|
|
||||||
int numToShow = Math.Min(NumVisible, ViewModel.Queue.Count - FirstVisible);
|
|
||||||
|
|
||||||
for (int i = 0; i < numToShow; i++)
|
|
||||||
UpdateControl(FirstVisible + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// View notified the model that a botton was clicked
|
/// View notified the model that a botton was clicked
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="queueIndex">index of the <see cref="ProcessBookViewModel"/> within <see cref="Queue"/></param>
|
/// <param name="sender">the <see cref="ProcessBookControl"/> whose button was clicked</param>
|
||||||
/// <param name="panelClicked">The clicked control to update</param>
|
/// <param name="buttonName">The name of the button clicked</param>
|
||||||
private async void VirtualFlowControl2_ButtonClicked(int queueIndex, string buttonName, ProcessBookControl panelClicked)
|
private async void VirtualFlowControl2_ButtonClicked(object? sender, string buttonName)
|
||||||
{
|
{
|
||||||
|
if (sender is not ProcessBookControl control || control.Context is not ProcessBookViewModel item)
|
||||||
|
return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var item = ViewModel.Queue[queueIndex];
|
if (buttonName is nameof(ProcessBookControl.cancelBtn))
|
||||||
if (buttonName == nameof(panelClicked.cancelBtn))
|
|
||||||
{
|
{
|
||||||
if (item is not null)
|
await item.CancelAsync();
|
||||||
|
ViewModel.Queue.RemoveQueued(item);
|
||||||
|
virtualFlowControl2.RefreshDisplay();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QueuePosition? position = buttonName switch
|
||||||
{
|
{
|
||||||
await item.CancelAsync();
|
nameof(ProcessBookControl.moveFirstBtn) => QueuePosition.Fisrt,
|
||||||
if (ViewModel.Queue.RemoveQueued(item))
|
nameof(ProcessBookControl.moveUpBtn) => QueuePosition.OneUp,
|
||||||
virtualFlowControl2.VirtualControlCount = ViewModel.Queue.Count;
|
nameof(ProcessBookControl.moveDownBtn) => QueuePosition.OneDown,
|
||||||
|
nameof(ProcessBookControl.moveLastBtn) => QueuePosition.Last,
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (position is not null)
|
||||||
|
{
|
||||||
|
ViewModel.Queue.MoveQueuePosition(item, position.Value);
|
||||||
|
virtualFlowControl2.RefreshDisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (buttonName == nameof(panelClicked.moveFirstBtn))
|
|
||||||
{
|
|
||||||
ViewModel.Queue.MoveQueuePosition(item, QueuePosition.Fisrt);
|
|
||||||
UpdateAllControls();
|
|
||||||
}
|
|
||||||
else if (buttonName == nameof(panelClicked.moveUpBtn))
|
|
||||||
{
|
|
||||||
ViewModel.Queue.MoveQueuePosition(item, QueuePosition.OneUp);
|
|
||||||
UpdateControl(queueIndex);
|
|
||||||
if (queueIndex > 0)
|
|
||||||
UpdateControl(queueIndex - 1);
|
|
||||||
}
|
|
||||||
else if (buttonName == nameof(panelClicked.moveDownBtn))
|
|
||||||
{
|
|
||||||
ViewModel.Queue.MoveQueuePosition(item, QueuePosition.OneDown);
|
|
||||||
UpdateControl(queueIndex);
|
|
||||||
if (queueIndex + 1 < ViewModel.Queue.Count)
|
|
||||||
UpdateControl(queueIndex + 1);
|
|
||||||
}
|
|
||||||
else if (buttonName == nameof(panelClicked.moveLastBtn))
|
|
||||||
{
|
|
||||||
ViewModel.Queue.MoveQueuePosition(item, QueuePosition.Last);
|
|
||||||
UpdateAllControls();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch(Exception ex)
|
||||||
{
|
{
|
||||||
@ -242,17 +161,6 @@ internal partial class ProcessQueueControl : UserControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// View needs updating
|
|
||||||
/// </summary>
|
|
||||||
private void VirtualFlowControl1_RequestData(int firstIndex, int numVisible, IReadOnlyList<ProcessBookControl> panelsToFill)
|
|
||||||
{
|
|
||||||
FirstVisible = firstIndex;
|
|
||||||
NumVisible = numVisible;
|
|
||||||
Panels = panelsToFill;
|
|
||||||
UpdateAllControls();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void numericUpDown1_ValueChanged(object? sender, EventArgs e)
|
private void numericUpDown1_ValueChanged(object? sender, EventArgs e)
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
using DataLayer;
|
using DataLayer;
|
||||||
using LibationUiBase.ProcessQueue;
|
using LibationUiBase.ProcessQueue;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
namespace LibationWinForms.ProcessQueue;
|
namespace LibationWinForms.ProcessQueue;
|
||||||
@ -13,62 +9,16 @@ namespace LibationWinForms.ProcessQueue;
|
|||||||
internal class ProcessQueueViewModel : ProcessQueueViewModelBase
|
internal class ProcessQueueViewModel : ProcessQueueViewModelBase
|
||||||
{
|
{
|
||||||
public event EventHandler<string>? LogWritten;
|
public event EventHandler<string>? LogWritten;
|
||||||
/// <summary>
|
public List<ProcessBookViewModelBase> Items { get; }
|
||||||
/// Fires when a ProcessBookViewModelBase in the queue has a property changed
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler<PropertyChangedEventArgs>? BookPropertyChanged;
|
|
||||||
private ObservableCollection<ProcessBookViewModelBase> Items { get; }
|
|
||||||
|
|
||||||
public ProcessQueueViewModel() : base(CreateEmptyList())
|
public ProcessQueueViewModel() : base(new List<ProcessBookViewModelBase>())
|
||||||
{
|
{
|
||||||
Items = Queue.UnderlyingList as ObservableCollection<ProcessBookViewModelBase>
|
Items = Queue.UnderlyingList as List<ProcessBookViewModelBase>
|
||||||
?? throw new ArgumentNullException(nameof(Queue.UnderlyingList));
|
?? throw new ArgumentNullException(nameof(Queue.UnderlyingList));
|
||||||
Items.CollectionChanged += Items_CollectionChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Items_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
switch (e.Action)
|
|
||||||
{
|
|
||||||
case NotifyCollectionChangedAction.Add:
|
|
||||||
subscribe(e.NewItems);
|
|
||||||
break;
|
|
||||||
case NotifyCollectionChangedAction.Remove:
|
|
||||||
unubscribe(e.OldItems);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
void subscribe(IList? items)
|
|
||||||
{
|
|
||||||
foreach (var item in e.NewItems?.OfType<ProcessBookViewModel>() ?? [])
|
|
||||||
item.PropertyChanged += Item_PropertyChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unubscribe(IList? items)
|
|
||||||
{
|
|
||||||
foreach (var item in e.NewItems?.OfType<ProcessBookViewModel>() ?? [])
|
|
||||||
item.PropertyChanged -= Item_PropertyChanged;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Item_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
|
||||||
=> BookPropertyChanged?.Invoke(sender, e);
|
|
||||||
|
|
||||||
public override void WriteLine(string text) => Invoke(() => LogWritten?.Invoke(this, text.Trim()));
|
public override void WriteLine(string text) => Invoke(() => LogWritten?.Invoke(this, text.Trim()));
|
||||||
|
|
||||||
protected override ProcessBookViewModelBase CreateNewProcessBook(LibraryBook libraryBook)
|
protected override ProcessBookViewModelBase CreateNewProcessBook(LibraryBook libraryBook)
|
||||||
=> new ProcessBookViewModel(libraryBook, Logger);
|
=> new ProcessBookViewModel(libraryBook, Logger);
|
||||||
|
|
||||||
private static ObservableCollection<ProcessBookViewModelBase> CreateEmptyList()
|
|
||||||
=> new ProcessBookCollection();
|
|
||||||
|
|
||||||
private class ProcessBookCollection : ObservableCollection<ProcessBookViewModelBase>
|
|
||||||
{
|
|
||||||
protected override void ClearItems()
|
|
||||||
{
|
|
||||||
//ObservableCollection doesn't raise Remove for each item on Clear, so we need to do it ourselves.
|
|
||||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, this));
|
|
||||||
base.ClearItems();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,44 +1,42 @@
|
|||||||
using System;
|
using LibationUiBase.ProcessQueue;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace LibationWinForms.ProcessQueue
|
namespace LibationWinForms.ProcessQueue
|
||||||
{
|
{
|
||||||
|
|
||||||
internal delegate void RequestDataDelegate(int queueIndex, int numVisible, IReadOnlyList<ProcessBookControl> panelsToFill);
|
|
||||||
internal delegate void ControlButtonClickedDelegate(int queueIndex, string buttonName, ProcessBookControl panelClicked);
|
|
||||||
internal partial class VirtualFlowControl : UserControl
|
internal partial class VirtualFlowControl : UserControl
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Triggered when the <see cref="VirtualFlowControl"/> needs to update the displayed <see cref="ProcessBookControl"/>s
|
|
||||||
/// </summary>
|
|
||||||
public event RequestDataDelegate RequestData;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Triggered when one of the <see cref="ProcessBookControl"/>'s buttons has been clicked
|
/// Triggered when one of the <see cref="ProcessBookControl"/>'s buttons has been clicked
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event ControlButtonClickedDelegate ButtonClicked;
|
public event EventHandler<string> ButtonClicked;
|
||||||
|
|
||||||
|
private List<ProcessBookViewModelBase> m_Items;
|
||||||
|
public List<ProcessBookViewModelBase> Items
|
||||||
|
{
|
||||||
|
get => m_Items;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_Items = value;
|
||||||
|
if (m_Items is not null)
|
||||||
|
RefreshDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshDisplay()
|
||||||
|
{
|
||||||
|
AdjustScrollBar();
|
||||||
|
DoVirtualScroll();
|
||||||
|
}
|
||||||
|
|
||||||
#region Dynamic Properties
|
#region Dynamic Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of virtual <see cref="ProcessBookControl"/>s in the <see cref="VirtualFlowControl"/>
|
/// The number of virtual <see cref="ProcessBookControl"/>s in the <see cref="VirtualFlowControl"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int VirtualControlCount
|
public int VirtualControlCount => Items?.Count ?? 0;
|
||||||
{
|
|
||||||
get => _virtualControlCount;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_virtualControlCount == 0)
|
|
||||||
vScrollBar1.Value = 0;
|
|
||||||
|
|
||||||
_virtualControlCount = value;
|
|
||||||
AdjustScrollBar();
|
|
||||||
DoVirtualScroll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _virtualControlCount;
|
|
||||||
|
|
||||||
int ScrollValue => Math.Max(vScrollBar1.Value, 0);
|
int ScrollValue => Math.Max(vScrollBar1.Value, 0);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -100,12 +98,7 @@ namespace LibationWinForms.ProcessQueue
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
panel1.Resize += (_, _) =>
|
panel1.Resize += (_, _) => RefreshDisplay();
|
||||||
{
|
|
||||||
AdjustScrollBar();
|
|
||||||
DoVirtualScroll();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var control = InitControl(0);
|
var control = InitControl(0);
|
||||||
VirtualControlHeight = this.DpiUnscale(control.Height + control.Margin.Top + control.Margin.Bottom);
|
VirtualControlHeight = this.DpiUnscale(control.Height + control.Margin.Top + control.Margin.Bottom);
|
||||||
@ -151,9 +144,7 @@ namespace LibationWinForms.ProcessQueue
|
|||||||
while (form is not ProcessBookControl)
|
while (form is not ProcessBookControl)
|
||||||
form = form.Parent;
|
form = form.Parent;
|
||||||
|
|
||||||
int clickedIndex = BookControls.IndexOf((ProcessBookControl)form);
|
ButtonClicked?.Invoke(form, button.Name);
|
||||||
|
|
||||||
ButtonClicked?.Invoke(FirstVisibleVirtualIndex + clickedIndex, button.Name, BookControls[clickedIndex]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -186,7 +177,8 @@ namespace LibationWinForms.ProcessQueue
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculated the virtual controls that are in view at the currrent scroll position and windows size,
|
/// Calculated the virtual controls that are in view at the currrent scroll position and windows size,
|
||||||
/// positions <see cref="panel1"/> to simulate scroll activity, then fires <see cref="RequestData"/> to notify the model to update all visible controls
|
/// positions <see cref="panel1"/> to simulate scroll activity, then fires updates the controls with
|
||||||
|
/// the context corresponding to the virtual scroll position
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void DoVirtualScroll()
|
private void DoVirtualScroll()
|
||||||
{
|
{
|
||||||
@ -203,10 +195,15 @@ namespace LibationWinForms.ProcessQueue
|
|||||||
numVisible = Math.Min(numVisible, VirtualControlCount);
|
numVisible = Math.Min(numVisible, VirtualControlCount);
|
||||||
numVisible = Math.Min(numVisible, VirtualControlCount - firstVisible);
|
numVisible = Math.Min(numVisible, VirtualControlCount - firstVisible);
|
||||||
|
|
||||||
RequestData?.Invoke(firstVisible, numVisible, BookControls);
|
for (int i = 0; i < numVisible; i++)
|
||||||
|
{
|
||||||
|
BookControls[i].Context = Items[firstVisible + i];
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < BookControls.Count; i++)
|
for (int i = 0; i < BookControls.Count; i++)
|
||||||
|
{
|
||||||
BookControls[i].Visible = i < numVisible;
|
BookControls[i].Visible = i < numVisible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user