Split up some DesktopController functionality into sub-controllers

This commit is contained in:
Ben Olden-Cooligan 2022-06-26 18:42:59 -07:00
parent 607f76cf8d
commit c77f5b30f9
11 changed files with 339 additions and 261 deletions

View File

@ -12,9 +12,9 @@ namespace NAPS2.Update;
public class UpdateOperation : OperationBase
{
private readonly ImageContext _imageContext;
private readonly ErrorOutput _errorOutput;
private readonly DesktopController _desktopController;
private readonly DesktopFormProvider _desktopFormProvider;
private readonly ManualResetEvent _waitHandle = new ManualResetEvent(false);
private WebClient? _client;
@ -35,11 +35,12 @@ public class UpdateOperation : OperationBase
}
}
public UpdateOperation(ImageContext imageContext, ErrorOutput errorOutput, DesktopController desktopController)
public UpdateOperation(ErrorOutput errorOutput, DesktopController desktopController,
DesktopFormProvider desktopFormProvider)
{
_imageContext = imageContext;
_errorOutput = errorOutput;
_desktopController = desktopController;
_desktopFormProvider = desktopFormProvider;
ProgressTitle = MiscResources.UpdateProgress;
AllowBackground = true;
@ -56,7 +57,8 @@ public class UpdateOperation : OperationBase
_update = updateInfo;
_tempFolder = Path.Combine(Paths.Temp, Path.GetRandomFileName());
Directory.CreateDirectory(_tempFolder);
_tempPath = Path.Combine(_tempFolder, updateInfo.DownloadUrl.Substring(updateInfo.DownloadUrl.LastIndexOf('/') + 1));
_tempPath = Path.Combine(_tempFolder,
updateInfo.DownloadUrl.Substring(updateInfo.DownloadUrl.LastIndexOf('/') + 1));
_client = new WebClient();
_client.DownloadProgressChanged += DownloadProgress;
@ -119,12 +121,8 @@ public class UpdateOperation : OperationBase
InvokeFinished();
_waitHandle.Set();
}
var desktop = Application.OpenForms.OfType<FDesktop>().FirstOrDefault();
if (desktop != null)
{
_desktopController.SkipRecoveryCleanup = true;
desktop.Close();
}
_desktopController.SkipRecoveryCleanup = true;
_desktopFormProvider.DesktopForm.Close();
}
private void InstallExe()
@ -181,14 +179,14 @@ public class UpdateOperation : OperationBase
private bool VerifySignature()
{
var cert = new X509Certificate2(ClientCreds.naps2_public);
var csp = (RSACryptoServiceProvider)cert.PublicKey.Key;
var csp = (RSACryptoServiceProvider) cert.PublicKey.Key;
return csp.VerifyHash(_update.Sha1, CryptoConfig.MapNameToOID("SHA1"), _update.Signature);
}
private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
Status.CurrentProgress = (int)e.BytesReceived;
Status.MaxProgress = (int)e.TotalBytesToReceive;
Status.CurrentProgress = (int) e.BytesReceived;
Status.MaxProgress = (int) e.TotalBytesToReceive;
InvokeStatusChanged();
}
}

View File

@ -1,6 +1,5 @@
using System.Threading;
using System.Windows.Forms;
using NAPS2.EtoForms.Ui;
using NAPS2.ImportExport;
using NAPS2.ImportExport.Images;
using NAPS2.Platform.Windows;
@ -8,7 +7,6 @@ using NAPS2.Recovery;
using NAPS2.Remoting;
using NAPS2.Scan;
using NAPS2.Update;
using NAPS2.Wia;
namespace NAPS2.WinForms;
@ -28,24 +26,26 @@ public class DesktopController
private readonly Naps2Config _config;
private readonly IOperationFactory _operationFactory;
private readonly StillImage _stillImage;
private readonly IFormFactory _formFactory;
private readonly IProfileManager _profileManager;
private readonly IScanPerformer _scanPerformer;
private readonly UpdateChecker _updateChecker;
private readonly NotificationManager _notify;
private readonly ImageTransfer _imageTransfer;
private readonly ImageClipboard _imageClipboard;
private readonly ImageListActions _imageListActions;
private readonly WinFormsExportHelper _exportHelper;
private readonly DesktopImagesController _desktopImagesController;
private readonly DesktopScanController _desktopScanController;
private readonly DesktopFormProvider _desktopFormProvider;
private bool _closed;
public DesktopController(ScanningContext scanningContext, UiImageList imageList,
RecoveryStorageManager recoveryStorageManager, ThumbnailRenderQueue thumbnailRenderQueue,
OperationProgress operationProgress, Naps2Config config, IOperationFactory operationFactory,
StillImage stillImage, IFormFactory formFactory, IProfileManager profileManager, IScanPerformer scanPerformer,
StillImage stillImage,
UpdateChecker updateChecker, NotificationManager notify, ImageTransfer imageTransfer,
ImageClipboard imageClipboard, ImageListActions imageListActions, WinFormsExportHelper exportHelper)
ImageClipboard imageClipboard, ImageListActions imageListActions, WinFormsExportHelper exportHelper,
DesktopImagesController desktopImagesController, DesktopScanController desktopScanController,
DesktopFormProvider desktopFormProvider)
{
_scanningContext = scanningContext;
_imageList = imageList;
@ -55,21 +55,17 @@ public class DesktopController
_config = config;
_operationFactory = operationFactory;
_stillImage = stillImage;
_formFactory = formFactory;
_profileManager = profileManager;
_scanPerformer = scanPerformer;
_updateChecker = updateChecker;
_notify = notify;
_imageTransfer = imageTransfer;
_imageClipboard = imageClipboard;
_imageListActions = imageListActions;
_exportHelper = exportHelper;
_desktopImagesController = desktopImagesController;
_desktopScanController = desktopScanController;
_desktopFormProvider = desktopFormProvider;
}
public Form Form { get; set; }
public Action<Action> SafeInvoke { get; set; }
public bool SkipRecoveryCleanup { get; set; }
public async Task Initialize()
@ -124,7 +120,7 @@ public class DesktopController
var update = task.Result;
if (update != null)
{
SafeInvoke(() => _notify.UpdateAvailable(_updateChecker, update));
_notify.UpdateAvailable(_updateChecker, update);
}
}).AssertNoAwait();
}
@ -147,7 +143,7 @@ public class DesktopController
// If NAPS2 was started by the scanner button, do the appropriate actions automatically
if (_stillImage.ShouldScan)
{
await ScanWithDevice(_stillImage.DeviceID!);
await _desktopScanController.ScanWithDevice(_stillImage.DeviceID!);
}
}
@ -216,8 +212,8 @@ public class DesktopController
if (_operationProgress.ActiveOperations.Any())
{
_operationProgress.ActiveOperations.ForEach(op => op.Cancel());
Form.Hide();
Form.ShowInTaskbar = false;
_desktopFormProvider.DesktopForm.Hide();
_desktopFormProvider.DesktopForm.ShowInTaskbar = false;
Task.Run(() =>
{
var timeoutCts = new CancellationTokenSource();
@ -230,7 +226,7 @@ public class DesktopController
{
}
_closed = true;
SafeInvoke(Form.Close);
_desktopFormProvider.DesktopForm.SafeInvoke(_desktopFormProvider.DesktopForm.Close);
});
return false;
}
@ -245,18 +241,19 @@ public class DesktopController
{
if (msg.StartsWith(Pipes.MSG_SCAN_WITH_DEVICE, StringComparison.InvariantCulture))
{
SafeInvoke(async () => await ScanWithDevice(msg.Substring(Pipes.MSG_SCAN_WITH_DEVICE.Length)));
_desktopFormProvider.DesktopForm.SafeInvoke(async () =>
await _desktopScanController.ScanWithDevice(msg.Substring(Pipes.MSG_SCAN_WITH_DEVICE.Length)));
}
if (msg.Equals(Pipes.MSG_ACTIVATE))
{
SafeInvoke(() =>
_desktopFormProvider.DesktopForm.SafeInvoke(() =>
{
var form = Application.OpenForms.Cast<Form>().Last();
if (form.WindowState == FormWindowState.Minimized)
var formOnTop = Application.OpenForms.Cast<Form>().Last();
if (formOnTop.WindowState == FormWindowState.Minimized)
{
Win32.ShowWindow(form.Handle, Win32.ShowWindowCommands.Restore);
Win32.ShowWindow(formOnTop.Handle, Win32.ShowWindowCommands.Restore);
}
form.Activate();
formOnTop.Activate();
});
}
});
@ -277,7 +274,7 @@ public class DesktopController
{
// Allow scanned images to be recovered in case of an unexpected close
var op = _operationFactory.Create<RecoveryOperation>();
if (op.Start(ReceiveScannedImage(),
if (op.Start(_desktopImagesController.ReceiveScannedImage(),
new RecoveryParams { ThumbnailSize = _config.Get(c => c.ThumbnailSize) }))
{
_operationProgress.ShowProgress(op);
@ -290,145 +287,10 @@ public class DesktopController
_thumbnailRenderQueue.StartRendering(_imageList);
}
private ScanParams DefaultScanParams() =>
new ScanParams
{
NoAutoSave = _config.Get(c => c.DisableAutoSave),
DoOcr = _config.Get(c => c.EnableOcr) && _config.Get(c => c.OcrAfterScanning),
ThumbnailSize = _config.Get(c => c.ThumbnailSize)
};
private async Task ScanWithDevice(string deviceID)
{
Form.Activate();
ScanProfile profile;
if (_profileManager.DefaultProfile?.Device?.ID == deviceID)
{
// Try to use the default profile if it has the right device
profile = _profileManager.DefaultProfile;
}
else
{
// Otherwise just pick any old profile with the right device
// Not sure if this is the best way to do it, but it's hard to prioritize profiles
profile = _profileManager.Profiles.FirstOrDefault(x => x.Device != null && x.Device.ID == deviceID);
}
if (profile == null)
{
if (_config.Get(c => c.NoUserProfiles) && _profileManager.Profiles.Any(x => x.IsLocked))
{
return;
}
// No profile for the device we're scanning with, so prompt to create one
var editSettingsForm = _formFactory.Create<FEditProfile>();
editSettingsForm.ScanProfile = _config.Get(c => c.DefaultProfileSettings);
try
{
// Populate the device field automatically (because we can do that!)
using var deviceManager = new WiaDeviceManager();
using var device = deviceManager.FindDevice(deviceID);
editSettingsForm.CurrentDevice = new ScanDevice(deviceID, device.Name());
}
catch (WiaException)
{
}
editSettingsForm.ShowDialog();
if (!editSettingsForm.Result)
{
return;
}
profile = editSettingsForm.ScanProfile;
_profileManager.Mutate(new ListMutation<ScanProfile>.Append(profile),
ListSelection.Empty<ScanProfile>());
_profileManager.DefaultProfile = profile;
}
if (profile != null)
{
// We got a profile, yay, so we can actually do the scan now
var source = await _scanPerformer.PerformScan(profile, DefaultScanParams(), Form.Handle);
await source.ForEach(ReceiveScannedImage());
Form.Activate();
}
}
public async Task ScanDefault()
{
if (_profileManager.DefaultProfile != null)
{
var source =
await _scanPerformer.PerformScan(_profileManager.DefaultProfile, DefaultScanParams(), Form.Handle);
await source.ForEach(ReceiveScannedImage());
Form.Activate();
}
else if (_profileManager.Profiles.Count == 0)
{
await ScanWithNewProfile();
}
else
{
ShowProfilesForm();
}
}
public async Task ScanWithNewProfile()
{
var editSettingsForm = _formFactory.Create<FEditProfile>();
editSettingsForm.ScanProfile = _config.Get(c => c.DefaultProfileSettings);
editSettingsForm.ShowDialog();
if (!editSettingsForm.Result)
{
return;
}
_profileManager.Mutate(new ListMutation<ScanProfile>.Append(editSettingsForm.ScanProfile),
ListSelection.Empty<ScanProfile>());
_profileManager.DefaultProfile = editSettingsForm.ScanProfile;
var source = await _scanPerformer.PerformScan(editSettingsForm.ScanProfile, DefaultScanParams(), Form.Handle);
await source.ForEach(ReceiveScannedImage());
Form.Activate();
}
/// <summary>
/// Constructs a receiver for scanned images.
/// This keeps images from the same source together, even if multiple sources are providing images at the same time.
/// </summary>
/// <returns></returns>
private Action<ProcessedImage> ReceiveScannedImage()
{
UiImage? last = null;
return scannedImage =>
{
SafeInvoke(() =>
{
lock (_imageList)
{
var uiImage = new UiImage(scannedImage);
_imageList.Mutate(new ImageListMutation.InsertAfter(uiImage, last));
last = uiImage;
}
});
};
}
public void ShowProfilesForm()
{
var form = _formFactory.Create<ProfilesForm>();
form.ImageCallback = ReceiveScannedImage();
form.ShowModal();
}
public void ShowBatchScanForm()
{
var form = _formFactory.Create<FBatchScan>();
form.ImageCallback = ReceiveScannedImage();
form.ShowDialog();
}
public void ImportFiles(IEnumerable<string> files)
{
var op = _operationFactory.Create<ImportOperation>();
if (op.Start(OrderFiles(files), ReceiveScannedImage(),
if (op.Start(OrderFiles(files), _desktopImagesController.ReceiveScannedImage(),
new ImportParams { ThumbnailSize = _config.Get(c => c.ThumbnailSize) }))
{
_operationProgress.ShowProgress(op);
@ -446,22 +308,13 @@ public class DesktopController
public void ImportDirect(ImageTransferData data, bool copy)
{
var op = _operationFactory.Create<DirectImportOperation>();
if (op.Start(data, copy, ReceiveScannedImage(),
if (op.Start(data, copy, _desktopImagesController.ReceiveScannedImage(),
new DirectImportParams { ThumbnailSize = _config.Get(c => c.ThumbnailSize) }))
{
_operationProgress.ShowProgress(op);
}
}
public async Task ScanWithProfile(ScanProfile profile)
{
_profileManager.DefaultProfile = profile;
var source = await _scanPerformer.PerformScan(profile, DefaultScanParams(), Form.Handle);
await source.ForEach(ReceiveScannedImage());
Form.Activate();
}
public void Paste()
{
if (_imageTransfer.IsInClipboard())
@ -503,28 +356,6 @@ public class DesktopController
}
}
public void PreviewImage()
{
if (_imageList.Selection.Any())
{
using var viewer = _formFactory.Create<FViewer>();
viewer.ImageList = _imageList;
// TODO: Fix this
// viewer.ImageIndex = SelectedIndices.First();
// viewer.DeleteCallback = UpdateThumbnails;
viewer.SelectCallback = i =>
{
if (_imageList.Selection.Count <= 1)
{
// TODO: Fix this
// SelectedIndices = new[] { i };
//thumbnailList1.Items[i].EnsureVisible();
}
};
viewer.ShowDialog();
}
}
public void ResetImage()
{
if (_imageList.Selection.Any())
@ -538,16 +369,6 @@ public class DesktopController
}
}
public void OpenAbout()
{
_formFactory.Create<AboutForm>().ShowModal();
}
public void OpenSettings()
{
// FormFactory.Create<FSettings>().ShowDialog();
}
public async Task SavePDF(List<UiImage> images)
{
using var imagesToSave = images.Select(x => x.GetClonedImage()).ToDisposableList();
@ -555,10 +376,7 @@ public class DesktopController
{
if (_config.Get(c => c.DeleteAfterSaving))
{
SafeInvoke(() =>
{
_imageList.Mutate(new ImageListMutation.DeleteSelected(), ListSelection.From(images));
});
_imageList.Mutate(new ImageListMutation.DeleteSelected(), ListSelection.From(images));
}
}
}
@ -587,6 +405,7 @@ public class DesktopController
{
Multiselect = true,
CheckFileExists = true,
// TODO: Move filter logic somewhere common
Filter = MiscResources.FileTypeAllFiles + @"|*.*|" +
MiscResources.FileTypePdf + @"|*.pdf|" +
MiscResources.FileTypeImageFiles +

View File

@ -0,0 +1,6 @@
namespace NAPS2.WinForms;
public class DesktopFormProvider
{
public FormBase DesktopForm { get; set; }
}

View File

@ -0,0 +1,31 @@
namespace NAPS2.WinForms;
public class DesktopImagesController
{
private readonly UiImageList _imageList;
public DesktopImagesController(UiImageList imageList)
{
_imageList = imageList;
}
/// <summary>
/// Constructs a receiver for scanned images.
/// This keeps images from the same source together, even if multiple sources are providing images at the same time.
/// </summary>
/// <returns></returns>
public Action<ProcessedImage> ReceiveScannedImage()
{
var lockObj = new object();
UiImage? last = null;
return scannedImage =>
{
lock (lockObj)
{
var uiImage = new UiImage(scannedImage);
_imageList.Mutate(new ImageListMutation.InsertAfter(uiImage, last));
last = uiImage;
}
};
}
}

View File

@ -0,0 +1,134 @@
using NAPS2.Scan;
using NAPS2.Wia;
namespace NAPS2.WinForms;
public class DesktopScanController
{
private readonly Naps2Config _config;
private readonly IProfileManager _profileManager;
private readonly IFormFactory _formFactory;
private readonly IScanPerformer _scanPerformer;
private readonly DesktopImagesController _desktopImagesController;
private readonly DesktopSubFormController _desktopSubFormController;
private readonly DesktopFormProvider _desktopFormProvider;
public DesktopScanController(Naps2Config config, IProfileManager profileManager, IFormFactory formFactory,
IScanPerformer scanPerformer, DesktopImagesController desktopImagesController,
DesktopSubFormController desktopSubFormController, DesktopFormProvider desktopFormProvider)
{
_config = config;
_profileManager = profileManager;
_formFactory = formFactory;
_scanPerformer = scanPerformer;
_desktopImagesController = desktopImagesController;
_desktopSubFormController = desktopSubFormController;
_desktopFormProvider = desktopFormProvider;
}
private ScanParams DefaultScanParams() =>
new()
{
NoAutoSave = _config.Get(c => c.DisableAutoSave),
DoOcr = _config.Get(c => c.EnableOcr) && _config.Get(c => c.OcrAfterScanning),
ThumbnailSize = _config.Get(c => c.ThumbnailSize)
};
public async Task ScanWithDevice(string deviceID)
{
_desktopFormProvider.DesktopForm.Activate();
ScanProfile? profile;
if (_profileManager.DefaultProfile?.Device?.ID == deviceID)
{
// Try to use the default profile if it has the right device
profile = _profileManager.DefaultProfile;
}
else
{
// Otherwise just pick any old profile with the right device
// Not sure if this is the best way to do it, but it's hard to prioritize profiles
profile = _profileManager.Profiles.FirstOrDefault(x => x.Device != null && x.Device.ID == deviceID);
}
if (profile == null)
{
if (_config.Get(c => c.NoUserProfiles) && _profileManager.Profiles.Any(x => x.IsLocked))
{
return;
}
// No profile for the device we're scanning with, so prompt to create one
var editSettingsForm = _formFactory.Create<FEditProfile>();
editSettingsForm.ScanProfile = _config.Get(c => c.DefaultProfileSettings);
try
{
// Populate the device field automatically (because we can do that!)
using var deviceManager = new WiaDeviceManager();
using var device = deviceManager.FindDevice(deviceID);
editSettingsForm.CurrentDevice = new ScanDevice(deviceID, device.Name());
}
catch (WiaException)
{
}
editSettingsForm.ShowDialog();
if (!editSettingsForm.Result)
{
return;
}
profile = editSettingsForm.ScanProfile;
_profileManager.Mutate(new ListMutation<ScanProfile>.Append(profile),
ListSelection.Empty<ScanProfile>());
_profileManager.DefaultProfile = profile;
}
if (profile != null)
{
// We got a profile, yay, so we can actually do the scan now
await DoScan(profile);
}
}
public async Task ScanDefault()
{
if (_profileManager.DefaultProfile != null)
{
await DoScan(_profileManager.DefaultProfile);
}
else if (_profileManager.Profiles.Count == 0)
{
await ScanWithNewProfile();
}
else
{
_desktopSubFormController.ShowProfilesForm();
}
}
public async Task ScanWithNewProfile()
{
var editSettingsForm = _formFactory.Create<FEditProfile>();
editSettingsForm.ScanProfile = _config.Get(c => c.DefaultProfileSettings);
editSettingsForm.ShowDialog();
if (!editSettingsForm.Result)
{
return;
}
_profileManager.Mutate(new ListMutation<ScanProfile>.Append(editSettingsForm.ScanProfile),
ListSelection.Empty<ScanProfile>());
_profileManager.DefaultProfile = editSettingsForm.ScanProfile;
await DoScan(editSettingsForm.ScanProfile);
}
public async Task ScanWithProfile(ScanProfile profile)
{
_profileManager.DefaultProfile = profile;
await DoScan(profile);
}
private async Task DoScan(ScanProfile profile)
{
var source =
await _scanPerformer.PerformScan(profile, DefaultScanParams(), _desktopFormProvider.DesktopForm.Handle);
await source.ForEach(_desktopImagesController.ReceiveScannedImage());
_desktopFormProvider.DesktopForm.Activate();
}
}

View File

@ -0,0 +1,76 @@
using NAPS2.EtoForms.Ui;
namespace NAPS2.WinForms;
public class DesktopSubFormController
{
private readonly IFormFactory _formFactory;
private readonly UiImageList _imageList;
private readonly DesktopImagesController _desktopImagesController;
public DesktopSubFormController(IFormFactory formFactory, UiImageList imageList,
DesktopImagesController desktopImagesController)
{
_formFactory = formFactory;
_imageList = imageList;
_desktopImagesController = desktopImagesController;
}
public void ShowImageForm<T>() where T : ImageForm
{
var selection = _imageList.Selection.ToList();
if (selection.Any())
{
var form = _formFactory.Create<T>();
form.Image = selection.First();
form.SelectedImages = selection.ToList();
form.ShowDialog();
}
}
public void ShowProfilesForm()
{
var form = _formFactory.Create<ProfilesForm>();
form.ImageCallback = _desktopImagesController.ReceiveScannedImage();
form.ShowModal();
}
public void ShowBatchScanForm()
{
var form = _formFactory.Create<FBatchScan>();
form.ImageCallback = _desktopImagesController.ReceiveScannedImage();
form.ShowDialog();
}
public void ShowViewerForm()
{
if (_imageList.Selection.Any())
{
using var viewer = _formFactory.Create<FViewer>();
viewer.ImageList = _imageList;
// TODO: Fix this
// viewer.ImageIndex = SelectedIndices.First();
// viewer.DeleteCallback = UpdateThumbnails;
viewer.SelectCallback = i =>
{
if (_imageList.Selection.Count <= 1)
{
// TODO: Fix this
// SelectedIndices = new[] { i };
//thumbnailList1.Items[i].EnsureVisible();
}
};
viewer.ShowDialog();
}
}
public void ShowAboutForm()
{
_formFactory.Create<AboutForm>().ShowModal();
}
public void ShowSettingsForm()
{
// FormFactory.Create<FSettings>().ShowDialog();
}
}

View File

@ -29,7 +29,10 @@ namespace NAPS2.WinForms
private readonly ThumbnailRenderQueue _thumbnailRenderQueue;
private readonly UiThumbnailProvider _thumbnailProvider;
private readonly DesktopController _desktopController;
private readonly DesktopScanController _desktopScanController;
private readonly ImageListActions _imageListActions;
private readonly DesktopFormProvider _desktopFormProvider;
private readonly DesktopSubFormController _desktopSubFormController;
private WinFormsListView<UiImage> _listView;
private ImageListSyncer? _imageListSyncer;
@ -51,7 +54,9 @@ namespace NAPS2.WinForms
ThumbnailRenderQueue thumbnailRenderQueue,
UiThumbnailProvider thumbnailProvider,
DesktopController desktopController,
ImageListActions imageListActions)
DesktopScanController desktopScanController,
ImageListActions imageListActions,
DesktopFormProvider desktopFormProvider, DesktopSubFormController desktopSubFormController)
{
_toolbarFormatter = toolbarFormatter;
_tesseractLanguageManager = tesseractLanguageManager;
@ -66,7 +71,10 @@ namespace NAPS2.WinForms
_thumbnailRenderQueue = thumbnailRenderQueue;
_thumbnailProvider = thumbnailProvider;
_desktopController = desktopController;
_desktopScanController = desktopScanController;
_imageListActions = imageListActions;
_desktopFormProvider = desktopFormProvider;
_desktopSubFormController = desktopSubFormController;
InitializeComponent();
notify.ParentForm = this;
@ -82,6 +90,7 @@ namespace NAPS2.WinForms
});
};
_profileManager.ProfilesUpdated += (_, _) => UpdateScanButton();
_desktopFormProvider.DesktopForm = this;
}
protected override void OnLoad(object sender, EventArgs args) => PostInitializeComponent();
@ -213,8 +222,6 @@ namespace NAPS2.WinForms
new Eto.Forms.Application(Eto.Platforms.WinForms).Attach();
UpdateToolbar();
_desktopController.Form = this;
_desktopController.SafeInvoke = SafeInvoke;
await _desktopController.Initialize();
}
@ -304,7 +311,7 @@ namespace NAPS2.WinForms
ImageScaling = ToolStripItemImageScaling.None
};
AssignProfileShortcut(i, item);
item.Click += async (_, _) => await _desktopController.ScanWithProfile(profile);
item.Click += async (_, _) => await _desktopScanController.ScanWithProfile(profile);
tsScan.DropDownItems.Insert(tsScan.DropDownItems.Count - staticButtonCount, item);
i++;
@ -353,7 +360,7 @@ namespace NAPS2.WinForms
_ksm.Assign("Ctrl+Down", _imageListActions.MoveDown);
_ksm.Assign("Ctrl+Right", _imageListActions.MoveDown);
_ksm.Assign("Ctrl+Shift+Del", tsClear);
_ksm.Assign("F1", _desktopController.OpenAbout);
_ksm.Assign("F1", _desktopSubFormController.ShowAboutForm);
_ksm.Assign("Ctrl+OemMinus", btnZoomOut);
_ksm.Assign("Ctrl+Oemplus", btnZoomIn);
_ksm.Assign("Del", ctxDelete);
@ -365,7 +372,7 @@ namespace NAPS2.WinForms
var ks = Config.Get(c => c.KeyboardShortcuts);
_ksm.Assign(ks.About, _desktopController.OpenAbout);
_ksm.Assign(ks.About, _desktopSubFormController.ShowAboutForm);
_ksm.Assign(ks.BatchScan, tsBatchScan);
_ksm.Assign(ks.Clear, tsClear);
_ksm.Assign(ks.Delete, tsDelete);
@ -478,13 +485,13 @@ namespace NAPS2.WinForms
#region Event Handlers - Toolbar
private async void tsScan_ButtonClick(object sender, EventArgs e) => await _desktopController.ScanDefault();
private async void tsScan_ButtonClick(object sender, EventArgs e) => await _desktopScanController.ScanDefault();
private async void tsNewProfile_Click(object sender, EventArgs e) => await _desktopController.ScanWithNewProfile();
private async void tsNewProfile_Click(object sender, EventArgs e) =>
await _desktopScanController.ScanWithNewProfile();
private void tsBatchScan_Click(object sender, EventArgs e) => _desktopController.ShowBatchScanForm();
private void tsProfiles_Click(object sender, EventArgs e) => _desktopController.ShowProfilesForm();
private void tsBatchScan_Click(object sender, EventArgs e) => _desktopSubFormController.ShowBatchScanForm();
private void tsProfiles_Click(object sender, EventArgs e) => _desktopSubFormController.ShowProfilesForm();
private void tsOcr_Click(object sender, EventArgs e)
{
@ -580,19 +587,25 @@ namespace NAPS2.WinForms
private void tsClear_Click(object sender, EventArgs e) => _desktopController.Clear();
private void tsAbout_Click(object sender, EventArgs e) => _desktopController.OpenAbout();
private void tsAbout_Click(object sender, EventArgs e) => _desktopSubFormController.ShowAboutForm();
private void tsSettings_Click(object sender, EventArgs e) => _desktopController.OpenSettings();
private void tsSettings_Click(object sender, EventArgs e) => _desktopSubFormController.ShowSettingsForm();
#endregion
#region Event Handlers - Save/Email Menus
private async void tsSavePDFAll_Click(object sender, EventArgs e) => await _desktopController.SavePDF(_imageList.Images);
private async void tsSavePDFSelected_Click(object sender, EventArgs e) => await _desktopController.SavePDF(_imageList.Selection.ToList());
private async void tsPDFSettings_Click(object sender, EventArgs e) => FormFactory.Create<FPdfSettings>().ShowDialog();
private async void tsSavePDFAll_Click(object sender, EventArgs e) =>
await _desktopController.SavePDF(_imageList.Images);
private async void tsSaveImagesAll_Click(object sender, EventArgs e) => await _desktopController.SaveImages(_imageList.Images);
private async void tsSavePDFSelected_Click(object sender, EventArgs e) =>
await _desktopController.SavePDF(_imageList.Selection.ToList());
private async void tsPDFSettings_Click(object sender, EventArgs e) =>
FormFactory.Create<FPdfSettings>().ShowDialog();
private async void tsSaveImagesAll_Click(object sender, EventArgs e) =>
await _desktopController.SaveImages(_imageList.Images);
private async void tsSaveImagesSelected_Click(object sender, EventArgs e) =>
await _desktopController.SaveImages(_imageList.Selection.ToList());
@ -600,8 +613,11 @@ namespace NAPS2.WinForms
private void tsImageSettings_Click(object sender, EventArgs e) =>
FormFactory.Create<FImageSettings>().ShowDialog();
private async void tsEmailPDFAll_Click(object sender, EventArgs e) => await _desktopController.EmailPDF(_imageList.Images);
private async void tsEmailPDFSelected_Click(object sender, EventArgs e) => await _desktopController.EmailPDF(_imageList.Selection.ToList());
private async void tsEmailPDFAll_Click(object sender, EventArgs e) =>
await _desktopController.EmailPDF(_imageList.Images);
private async void tsEmailPDFSelected_Click(object sender, EventArgs e) =>
await _desktopController.EmailPDF(_imageList.Selection.ToList());
private void tsPdfSettings2_Click(object sender, EventArgs e) =>
FormFactory.Create<FPdfSettings>().ShowDialog();
@ -613,25 +629,19 @@ namespace NAPS2.WinForms
#region Event Handlers - Image Menu
private void tsView_Click(object sender, EventArgs e) => _desktopController.PreviewImage();
private void tsView_Click(object sender, EventArgs e) => _desktopSubFormController.ShowViewerForm();
private void tsCrop_Click(object sender, EventArgs e) => _desktopSubFormController.ShowImageForm<FCrop>();
private void ShowImageForm<T>() where T : ImageForm
{
var selection = _imageList.Selection.ToList();
if (selection.Any())
{
var form = FormFactory.Create<T>();
form.Image = selection.First();
form.SelectedImages = selection.ToList();
form.ShowDialog();
}
}
private void tsBrightnessContrast_Click(object sender, EventArgs e) =>
_desktopSubFormController.ShowImageForm<FBrightnessContrast>();
private void tsCrop_Click(object sender, EventArgs e) => ShowImageForm<FCrop>();
private void tsBrightnessContrast_Click(object sender, EventArgs e) => ShowImageForm<FBrightnessContrast>();
private void tsHueSaturation_Click(object sender, EventArgs e) => ShowImageForm<FHueSaturation>();
private void tsBlackWhite_Click(object sender, EventArgs e) => ShowImageForm<FBlackWhite>();
private void tsSharpen_Click(object sender, EventArgs e) => ShowImageForm<FSharpen>();
private void tsHueSaturation_Click(object sender, EventArgs e) =>
_desktopSubFormController.ShowImageForm<FHueSaturation>();
private void tsBlackWhite_Click(object sender, EventArgs e) =>
_desktopSubFormController.ShowImageForm<FBlackWhite>();
private void tsSharpen_Click(object sender, EventArgs e) => _desktopSubFormController.ShowImageForm<FSharpen>();
private void tsReset_Click(object sender, EventArgs e) => _desktopController.ResetImage();
#endregion
@ -642,7 +652,7 @@ namespace NAPS2.WinForms
private async void tsRotateRight_Click(object sender, EventArgs e) => await _imageListActions.RotateRight();
private async void tsFlip_Click(object sender, EventArgs e) => await _imageListActions.Flip();
private void tsDeskew_Click(object sender, EventArgs e) => _imageListActions.Deskew();
private void tsCustomRotation_Click(object sender, EventArgs e) => ShowImageForm<FRotate>();
private void tsCustomRotation_Click(object sender, EventArgs e) => _desktopSubFormController.ShowImageForm<FRotate>();
#endregion
@ -669,7 +679,7 @@ namespace NAPS2.WinForms
}
private void ctxSelectAll_Click(object sender, EventArgs e) => _imageListActions.SelectAll();
private void ctxView_Click(object sender, EventArgs e) => _desktopController.PreviewImage();
private void ctxView_Click(object sender, EventArgs e) => _desktopSubFormController.ShowViewerForm();
private void ctxDelete_Click(object sender, EventArgs e) => _desktopController.Delete();
private async void ctxCopy_Click(object sender, EventArgs e) => await _desktopController.Copy();
@ -735,7 +745,7 @@ namespace NAPS2.WinForms
#region Drag/Drop
private void ListViewItemClicked(object? sender, EventArgs e) => _desktopController.PreviewImage();
private void ListViewItemClicked(object? sender, EventArgs e) => _desktopSubFormController.ShowViewerForm();
private void ListViewSelectionChanged(object? sender, EventArgs e)
{

View File

@ -5,7 +5,7 @@ using Timer = System.Threading.Timer;
namespace NAPS2.WinForms
{
partial class ImageForm : FormBase
public partial class ImageForm : FormBase
{
private readonly ImageContext _imageContext;

View File

@ -17,6 +17,7 @@ public class WinFormsDialogHelper : DialogHelper
{
OverwritePrompt = false,
AddExtension = true,
// TODO: Move filter logic somewhere common
Filter = MiscResources.FileTypePdf + @"|*.pdf|" +
MiscResources.FileTypeBmp + @"|*.bmp|" +
MiscResources.FileTypeEmf + @"|*.emf|" +
@ -62,6 +63,7 @@ public class WinFormsDialogHelper : DialogHelper
{
OverwritePrompt = false,
AddExtension = true,
// TODO: Move filter logic somewhere common
Filter = MiscResources.FileTypeBmp + @"|*.bmp|" +
MiscResources.FileTypeEmf + @"|*.emf|" +
MiscResources.FileTypeExif + @"|*.exif|" +

View File

@ -6,6 +6,7 @@ using NAPS2.ImportExport.Pdf;
namespace NAPS2.WinForms;
// TODO: Rename this ImageExportController or something
public class WinFormsExportHelper
{
private readonly DialogHelper _dialogHelper;

View File

@ -1,5 +1,6 @@
namespace NAPS2.Threading;
// TODO: Can we get rid of this static context?
/// <summary>
/// Synchronized access to the UI thread.
/// </summary>