Files
SpineViewer/SpineViewer/ViewModels/ProgressDialogViewModel.cs
2025-11-03 18:09:05 +08:00

106 lines
2.9 KiB
C#

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using NLog;
using SpineViewer.Resources;
using SpineViewer.Services;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SpineViewer.ViewModels
{
public partial class ProgressDialogViewModel : ObservableObject, IProgressReporter, IDisposable
{
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
private readonly CancellationTokenSource _cts = new();
private readonly Task _task;
public ProgressDialogViewModel(Action<IProgressReporter, CancellationToken> work)
{
_task = new(() =>
{
try
{
work(this, _cts.Token);
WorkFinished?.Invoke(this, true);
}
catch (OperationCanceledException)
{
_logger.Info("Work cancelled by user: {0}", _title);
WorkFinished?.Invoke(this, false);
}
catch (Exception ex)
{
_logger.Debug(ex.ToString());
_logger.Error("Failed to finish work: {0}, {1}", _title, ex.Message);
WorkFinished?.Invoke(this, false);
}
});
}
public void Start() => _task.Start();
public event EventHandler<bool>? WorkFinished;
[ObservableProperty]
private string _title = "Progress";
[ObservableProperty]
private float _total = 100;
[ObservableProperty]
private float _done = 0;
[ObservableProperty]
private string _progressText = "Working...";
public RelayCommand Cmd_Cancel => _cmd_Cancel ??= new(Cancel_Execute, Cancel_CanExecute);
private RelayCommand? _cmd_Cancel;
private void Cancel_Execute()
{
if (!Cancel_CanExecute()) return;
if (!MessagePopupService.OKCancel(AppResource.Str_CancelQuest)) return;
_cts.Cancel();
Cmd_Cancel.NotifyCanExecuteChanged();
}
private bool Cancel_CanExecute() => !_cts.IsCancellationRequested;
#region IDisposable
private bool _disposed = false;
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
_cts.Dispose();
_task.Dispose();
}
_disposed = true;
}
~ProgressDialogViewModel()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
if (_disposed)
{
GC.SuppressFinalize(this);
}
}
#endregion
}
}