Move eto forms and most other eto code to Lib.Common

This commit is contained in:
Ben Olden-Cooligan 2022-08-20 17:42:35 -07:00
parent fdd1ff839e
commit 3159ede121
51 changed files with 264 additions and 205 deletions

View File

@ -1,4 +1,4 @@
using System.Windows.Forms;
using Eto.Forms;
namespace NAPS2.EtoForms;

View File

@ -31,6 +31,27 @@ public static class EtoExtensions
public static Bitmap ToEtoImage(this byte[] bytes) => new(bytes);
public static Bitmap ToEtoImage(this IMemoryImage image) => EtoPlatform.Current.ToBitmap(image);
public static MessageBoxType ToEto(this MessageBoxIcon icon)
{
return icon switch
{
MessageBoxIcon.Information => MessageBoxType.Information,
MessageBoxIcon.Warning => MessageBoxType.Warning,
_ => MessageBoxType.Information // TODO: Default type with no icon?
};
}
public static DockPosition ToEto(this DockStyle dock)
{
return dock switch
{
DockStyle.Bottom => DockPosition.Bottom,
DockStyle.Left => DockPosition.Left,
DockStyle.Right => DockPosition.Right,
_ => DockPosition.Top
};
}
public static ControlWithLayoutAttributes Width(this Control control, int width) =>
new ControlWithLayoutAttributes(control, width: width);
public static ControlWithLayoutAttributes Height(this Control control, int height) =>

View File

@ -16,4 +16,5 @@ public abstract class EtoPlatform
public abstract IListView<T> CreateListView<T>(ListViewBehavior<T> behavior) where T : notnull;
public abstract void ConfigureImageButton(Button button);
public abstract Bitmap ToBitmap(IMemoryImage image);
public abstract IMemoryImage DrawHourglass(IMemoryImage thumb);
}

View File

@ -1,6 +1,5 @@
using Eto.Drawing;
using Eto.Forms;
using Eto.WinForms;
using NAPS2.ImportExport.Images;
namespace NAPS2.EtoForms;
@ -22,7 +21,7 @@ public class ImageListViewBehavior : ListViewBehavior<UiImage>
public override Image GetImage(UiImage item, int imageSize)
{
return _thumbnailProvider.GetThumbnail(item, imageSize).ToEto();
return _thumbnailProvider.GetThumbnail(item, imageSize).ToEtoImage();
}
public override void SetDragData(ListSelection<UiImage> selection, IDataObject dataObject)

View File

@ -1,6 +1,5 @@
using Eto.Drawing;
using Eto.Forms;
using Eto.WinForms;
using NAPS2.ImportExport.Profiles;
using NAPS2.Scan;

View File

@ -1,5 +1,5 @@
using Eto.Drawing;
using Eto.Forms;
using Eto.WinForms;
using NAPS2.Update;
namespace NAPS2.EtoForms.Ui;
@ -25,7 +25,7 @@ public class AboutForm : EtoDialogBase
_updateChecker = updateChecker;
Title = UiStrings.AboutFormTitle;
Icon = Icons.information_small.ToEtoIcon();
Icon = new Icon(1f, Icons.information_small.ToEtoImage());
Resizable = false;
FormStateController.RestoreFormState = false;

View File

@ -1,6 +1,5 @@
using System.Collections.Immutable;
using Eto.Forms;
using Eto.WinForms;
using NAPS2.ImportExport.Images;
using NAPS2.WinForms;
@ -8,7 +7,7 @@ namespace NAPS2.EtoForms.Ui;
public abstract class DesktopForm : EtoFormBase
{
private readonly KeyboardShortcutManager _ksm;
// private readonly KeyboardShortcutManager _ksm;
private readonly INotificationManager _notify;
private readonly CultureHelper _cultureHelper;
private readonly IProfileManager _profileManager;
@ -20,7 +19,7 @@ public abstract class DesktopForm : EtoFormBase
private readonly IDesktopScanController _desktopScanController;
private readonly ImageListActions _imageListActions;
private readonly DesktopFormProvider _desktopFormProvider;
private readonly DesktopSubFormController _desktopSubFormController;
private readonly IDesktopSubFormController _desktopSubFormController;
private readonly Command _scanCommand;
private readonly Command _newProfileCommand;
@ -79,7 +78,7 @@ public abstract class DesktopForm : EtoFormBase
public DesktopForm(
Naps2Config config,
KeyboardShortcutManager ksm,
// KeyboardShortcutManager ksm,
INotificationManager notify,
CultureHelper cultureHelper,
IProfileManager profileManager,
@ -91,9 +90,9 @@ public abstract class DesktopForm : EtoFormBase
IDesktopScanController desktopScanController,
ImageListActions imageListActions,
DesktopFormProvider desktopFormProvider,
DesktopSubFormController desktopSubFormController) : base(config)
IDesktopSubFormController desktopSubFormController) : base(config)
{
_ksm = ksm;
// _ksm = ksm;
_notify = notify;
_cultureHelper = cultureHelper;
_profileManager = profileManager;
@ -132,7 +131,7 @@ public abstract class DesktopForm : EtoFormBase
ToolBarText = UiStrings.Ocr,
Image = Icons.text.ToEtoImage()
};
_importCommand = new ActionCommand(_desktopController.Import)
_importCommand = new ActionCommand(() => _desktopController.Import(this))
{
ToolBarText = UiStrings.Import,
Image = Icons.folder_picture.ToEtoImage()
@ -185,27 +184,27 @@ public abstract class DesktopForm : EtoFormBase
{
MenuText = UiStrings.View
};
_cropCommand = new ActionCommand(_desktopSubFormController.ShowImageForm<FCrop>)
_cropCommand = new ActionCommand(_desktopSubFormController.ShowCropForm)
{
MenuText = UiStrings.Crop,
Image = Icons.transform_crop.ToEtoImage()
};
_brightContCommand = new ActionCommand(_desktopSubFormController.ShowImageForm<FBrightnessContrast>)
_brightContCommand = new ActionCommand(_desktopSubFormController.ShowBrightnessContrastForm)
{
MenuText = UiStrings.BrightnessContrast,
Image = Icons.contrast_with_sun.ToEtoImage()
};
_hueSatCommand = new ActionCommand(_desktopSubFormController.ShowImageForm<FHueSaturation>)
_hueSatCommand = new ActionCommand(_desktopSubFormController.ShowHueSaturationForm)
{
MenuText = UiStrings.HueSaturation,
Image = Icons.color_management.ToEtoImage()
};
_blackWhiteCommand = new ActionCommand(_desktopSubFormController.ShowImageForm<FBlackWhite>)
_blackWhiteCommand = new ActionCommand(_desktopSubFormController.ShowBlackWhiteForm)
{
MenuText = UiStrings.BlackAndWhite,
Image = Icons.contrast_high.ToEtoImage()
};
_sharpenCommand = new ActionCommand(_desktopSubFormController.ShowImageForm<FSharpen>)
_sharpenCommand = new ActionCommand(_desktopSubFormController.ShowSharpenForm)
{
MenuText = UiStrings.Sharpen,
Image = Icons.sharpen.ToEtoImage()
@ -238,7 +237,7 @@ public abstract class DesktopForm : EtoFormBase
{
MenuText = UiStrings.Deskew
};
_customRotateCommand = new ActionCommand(_desktopSubFormController.ShowImageForm<FRotate>)
_customRotateCommand = new ActionCommand(_desktopSubFormController.ShowRotateForm)
{
MenuText = UiStrings.CustomRotation
};
@ -872,9 +871,9 @@ public abstract class DesktopForm : EtoFormBase
private void ListViewDrop(object? sender, DropEventArgs args)
{
if (_imageTransfer.IsIn(args.Data.ToEto()))
if (_imageTransfer.IsIn(args.Data))
{
var data = _imageTransfer.GetFrom(args.Data.ToEto());
var data = _imageTransfer.GetFrom(args.Data);
if (data.ProcessId == Process.GetCurrentProcess().Id)
{
DragMoveImages(args.Position);
@ -884,10 +883,10 @@ public abstract class DesktopForm : EtoFormBase
_desktopController.ImportDirect(data, false);
}
}
else if (args.Data.GetDataPresent("FileDrop"))
else if (args.Data.Contains("FileDrop"))
{
// TODO: Is this xplat-compatible?
var data = (string[]) args.Data.GetData("FileDrop");
var data = args.Data.GetObject<string[]>("FileDrop");
_desktopController.ImportFiles(data);
}
}

View File

@ -1,11 +1,8 @@
using Eto.Drawing;
using Eto.Forms;
using Eto.WinForms;
using Eto.WinForms.Forms;
using NAPS2.ImportExport.Profiles;
using NAPS2.Scan;
using NAPS2.Serialization;
using NAPS2.WinForms;
namespace NAPS2.EtoForms.Ui;
@ -35,17 +32,18 @@ public class ProfilesForm : EtoDialogBase
_profileTransfer = profileTransfer;
Title = UiStrings.ProfilesFormTitle;
Icon = Icons.blueprints_small.ToEtoIcon();
Icon = new Icon(1f, Icons.blueprints_small.ToEtoImage());
Size = new Size(700, 200);
MinimumSize = new Size(600, 180);
Resizable = true;
switch (Handler)
{
case IWindowsControl windowsControl:
windowsControl.UseShellDropManager = false;
break;
}
// TODO: Do this only in WinForms (?)
// switch (Handler)
// {
// case IWindowsControl windowsControl:
// windowsControl.UseShellDropManager = false;
// break;
// }
_listView = EtoPlatform.Current.CreateListView(profileListViewBehavior);
_scanCommand = new ActionCommand(DoScan)
@ -188,9 +186,9 @@ public class ProfilesForm : EtoDialogBase
private void Drop(object? sender, DropEventArgs e)
{
// Receive drop data
if (_profileTransfer.IsIn(e.Data.ToEto()))
if (_profileTransfer.IsIn(e.Data))
{
var data = _profileTransfer.GetFrom(e.Data.ToEto());
var data = _profileTransfer.GetFrom(e.Data);
if (data.ProcessId == Process.GetCurrentProcess().Id)
{
if (data.Locked)
@ -233,63 +231,64 @@ public class ProfilesForm : EtoDialogBase
private async void DoScan()
{
if (ImageCallback == null)
{
throw new InvalidOperationException("Image callback not specified");
}
if (_profileManager.Profiles.Count == 0)
{
var editSettingsForm = FormFactory.Create<FEditProfile>();
editSettingsForm.ScanProfile = new ScanProfile
{
Version = ScanProfile.CURRENT_VERSION
};
editSettingsForm.ShowDialog();
if (!editSettingsForm.Result)
{
return;
}
_profileManager.Mutate(new ListMutation<ScanProfile>.Append(editSettingsForm.ScanProfile), ListSelection.Empty<ScanProfile>());
_profileManager.DefaultProfile = editSettingsForm.ScanProfile;
}
if (SelectedProfile == null)
{
MessageBox.Show(MiscResources.SelectProfileBeforeScan, MiscResources.ChooseProfile, MessageBoxButtons.OK, MessageBoxType.Warning);
return;
}
if (_profileManager.DefaultProfile == null)
{
_profileManager.DefaultProfile = SelectedProfile;
}
var source = await _scanPerformer.PerformScan(SelectedProfile, DefaultScanParams(), this.ToNative().Handle);
await source.ForEach(ImageCallback);
this.ToNative().Activate();
// TODO: Migrate FEditProfile to eto
// if (ImageCallback == null)
// {
// throw new InvalidOperationException("Image callback not specified");
// }
// if (_profileManager.Profiles.Count == 0)
// {
// var editSettingsForm = FormFactory.Create<FEditProfile>();
// editSettingsForm.ScanProfile = new ScanProfile
// {
// Version = ScanProfile.CURRENT_VERSION
// };
// editSettingsForm.ShowDialog();
// if (!editSettingsForm.Result)
// {
// return;
// }
// _profileManager.Mutate(new ListMutation<ScanProfile>.Append(editSettingsForm.ScanProfile), ListSelection.Empty<ScanProfile>());
// _profileManager.DefaultProfile = editSettingsForm.ScanProfile;
// }
// if (SelectedProfile == null)
// {
// MessageBox.Show(MiscResources.SelectProfileBeforeScan, MiscResources.ChooseProfile, MessageBoxButtons.OK, MessageBoxType.Warning);
// return;
// }
// if (_profileManager.DefaultProfile == null)
// {
// _profileManager.DefaultProfile = SelectedProfile;
// }
// var source = await _scanPerformer.PerformScan(SelectedProfile, DefaultScanParams(), this.ToNative().Handle);
// await source.ForEach(ImageCallback);
// this.ToNative().Activate();
}
private void DoAdd()
{
var fedit = FormFactory.Create<FEditProfile>();
fedit.ScanProfile = Config.DefaultProfileSettings();
fedit.ShowDialog();
if (fedit.Result)
{
_profileManager.Mutate(new ListMutation<ScanProfile>.Append(fedit.ScanProfile), _listView);
}
// var fedit = FormFactory.Create<FEditProfile>();
// fedit.ScanProfile = Config.DefaultProfileSettings();
// fedit.ShowDialog();
// if (fedit.Result)
// {
// _profileManager.Mutate(new ListMutation<ScanProfile>.Append(fedit.ScanProfile), _listView);
// }
}
private void DoEdit()
{
var originalProfile = SelectedProfile;
if (originalProfile != null)
{
var fedit = FormFactory.Create<FEditProfile>();
fedit.ScanProfile = originalProfile;
fedit.ShowDialog();
if (fedit.Result)
{
_profileManager.Mutate(new ListMutation<ScanProfile>.ReplaceWith(fedit.ScanProfile), _listView);
}
}
// var originalProfile = SelectedProfile;
// if (originalProfile != null)
// {
// var fedit = FormFactory.Create<FEditProfile>();
// fedit.ScanProfile = originalProfile;
// fedit.ShowDialog();
// if (fedit.Result)
// {
// _profileManager.Mutate(new ListMutation<ScanProfile>.ReplaceWith(fedit.ScanProfile), _listView);
// }
// }
}
private void DoDelete()

View File

@ -1,5 +1,6 @@
using System.Drawing;
using System.Drawing.Imaging;
using NAPS2.EtoForms;
using NAPS2.Images.Gdi;
namespace NAPS2.Images;
@ -10,61 +11,43 @@ namespace NAPS2.Images;
/// </summary>
public class UiThumbnailProvider
{
private Bitmap? _placeholder;
private readonly ImageContext _imageContext;
private IMemoryImage? _placeholder;
public Bitmap GetThumbnail(UiImage img, int thumbnailSize)
public UiThumbnailProvider(ImageContext imageContext)
{
_imageContext = imageContext;
}
public IMemoryImage GetThumbnail(UiImage img, int thumbnailSize)
{
lock (img)
{
var thumb = ((GdiImage?) img.GetThumbnailClone())?.Bitmap;
var thumb = img.GetThumbnailClone();
if (thumb == null)
{
return RenderPlaceholder(thumbnailSize);
}
if (img.IsThumbnailDirty)
{
thumb = DrawHourglass(thumb);
thumb = EtoPlatform.Current.DrawHourglass(thumb);
}
return thumb;
}
}
private Bitmap RenderPlaceholder(int thumbnailSize)
private IMemoryImage RenderPlaceholder(int thumbnailSize)
{
lock (this)
{
if (_placeholder?.Size.Width == thumbnailSize)
if (_placeholder?.Width == thumbnailSize)
{
return _placeholder;
}
_placeholder?.Dispose();
_placeholder = new Bitmap(thumbnailSize, thumbnailSize);
_placeholder = DrawHourglass(_placeholder);
_placeholder = _imageContext.Create(thumbnailSize, thumbnailSize, ImagePixelFormat.RGB24);
_placeholder = EtoPlatform.Current.DrawHourglass(_placeholder);
return _placeholder;
}
}
private Bitmap DrawHourglass(Image image)
{
var bitmap = new Bitmap(image.Width, image.Height);
using (var g = Graphics.FromImage(bitmap))
{
var attrs = new ImageAttributes();
attrs.SetColorMatrix(new ColorMatrix
{
Matrix33 = 0.3f
});
g.DrawImage(image,
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
0,
0,
image.Width,
image.Height,
GraphicsUnit.Pixel,
attrs);
g.DrawImage(new Bitmap(new MemoryStream(Icons.hourglass_grey)), new Rectangle((bitmap.Width - 32) / 2, (bitmap.Height - 32) / 2, 32, 32));
}
image.Dispose();
return bitmap;
}
}

View File

@ -0,0 +1,12 @@
namespace NAPS2.ImportExport;
public interface IScannedImagePrinter
{
/// <summary>
/// Prints the provided images, prompting the user for the printer settings.
/// </summary>
/// <param name="images">The full list of images to print.</param>
/// <param name="selectedImages">The list of selected images. If non-empty, the user will be presented an option to print selected.</param>
/// <returns>True if the print completed, false if there was nothing to print or the user cancelled.</returns>
Task<bool> PromptToPrint(IList<ProcessedImage> images, IList<ProcessedImage> selectedImages);
}

View File

@ -20,6 +20,7 @@
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="Ninject" Version="3.3.6" />
<PackageReference Include="NLog" Version="4.5.8" />
<PackageReference Include="Eto.Forms" Version="2.7.0" />
</ItemGroup>
<ItemGroup>

View File

@ -1,7 +1,6 @@
using System.ComponentModel;
using System.IO.Compression;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Threading;

View File

@ -1,5 +1,6 @@
using System.Threading;
using System.Windows.Forms;
using Eto.Forms;
using NAPS2.EtoForms;
using NAPS2.ImportExport;
using NAPS2.ImportExport.Images;
using NAPS2.Platform.Windows;
@ -7,7 +8,6 @@ using NAPS2.Recovery;
using NAPS2.Remoting;
using NAPS2.Scan;
using NAPS2.Update;
using MessageBoxIcon = System.Windows.Forms.MessageBoxIcon;
namespace NAPS2.WinForms;
@ -181,9 +181,10 @@ public class DesktopController
{
if (_operationProgress.ActiveOperations.Any(x => !x.SkipExitPrompt))
{
var result = MessageBox.Show(MiscResources.ExitWithActiveOperations,
var result = MessageBox.Show(_desktopFormProvider.DesktopForm,
MiscResources.ExitWithActiveOperations,
MiscResources.ActiveOperations,
MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
MessageBoxButtons.YesNo, MessageBoxType.Warning, MessageBoxDefaultButton.No);
if (result != DialogResult.Yes)
{
return false;
@ -199,8 +200,9 @@ public class DesktopController
{
if (userClosing && !SkipRecoveryCleanup)
{
var result = MessageBox.Show(MiscResources.ExitWithUnsavedChanges, MiscResources.UnsavedChanges,
MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
var result = MessageBox.Show(_desktopFormProvider.DesktopForm, MiscResources.ExitWithUnsavedChanges,
MiscResources.UnsavedChanges,
MessageBoxButtons.YesNo, MessageBoxType.Warning, MessageBoxDefaultButton.No);
if (result != DialogResult.Yes)
{
return false;
@ -252,12 +254,13 @@ public class DesktopController
{
Invoker.Current.SafeInvoke(() =>
{
var formOnTop = Application.OpenForms.Cast<Form>().Last();
if (formOnTop.WindowState == FormWindowState.Minimized)
// TODO: xplat
var formOnTop = Application.Instance.Windows.Last();
if (formOnTop.WindowState == WindowState.Minimized)
{
Win32.ShowWindow(formOnTop.Handle, Win32.ShowWindowCommands.Restore);
Win32.ShowWindow(formOnTop.NativeHandle, Win32.ShowWindowCommands.Restore);
}
formOnTop.Activate();
formOnTop.BringToFront();
});
}
});
@ -270,19 +273,20 @@ public class DesktopController
{
MessageBox.Show(_config.Get(c => c.StartupMessageText), _config.Get(c => c.StartupMessageTitle),
MessageBoxButtons.OK,
_config.Get(c => c.StartupMessageIcon).ToWinForms());
_config.Get(c => c.StartupMessageIcon).ToEto());
}
}
private void ShowRecoveryPrompt()
{
// Allow scanned images to be recovered in case of an unexpected close
var op = _operationFactory.Create<RecoveryOperation>();
if (op.Start(_desktopImagesController.ReceiveScannedImage(),
new RecoveryParams { ThumbnailSize = _config.ThumbnailSize() }))
{
_operationProgress.ShowProgress(op);
}
// TODO: Eto implementation
// var op = _operationFactory.Create<RecoveryOperation>();
// if (op.Start(_desktopImagesController.ReceiveScannedImage(),
// new RecoveryParams { ThumbnailSize = _config.ThumbnailSize() }))
// {
// _operationProgress.ShowProgress(op);
// }
}
private void InitThumbnailRendering()
@ -338,9 +342,10 @@ public class DesktopController
{
if (_imageList.Images.Count > 0)
{
if (MessageBox.Show(string.Format(MiscResources.ConfirmClearItems, _imageList.Images.Count),
if (MessageBox.Show(_desktopFormProvider.DesktopForm,
string.Format(MiscResources.ConfirmClearItems, _imageList.Images.Count),
MiscResources.Clear, MessageBoxButtons.OKCancel,
MessageBoxIcon.Question) == DialogResult.OK)
MessageBoxType.Question) == DialogResult.Ok)
{
_imageListActions.DeleteAll();
}
@ -351,9 +356,10 @@ public class DesktopController
{
if (_imageList.Selection.Any())
{
if (MessageBox.Show(string.Format(MiscResources.ConfirmDeleteItems, _imageList.Selection.Count),
if (MessageBox.Show(_desktopFormProvider.DesktopForm,
string.Format(MiscResources.ConfirmDeleteItems, _imageList.Selection.Count),
MiscResources.Delete, MessageBoxButtons.OKCancel,
MessageBoxIcon.Question) == DialogResult.OK)
MessageBoxType.Question) == DialogResult.Ok)
{
_imageListActions.DeleteSelected();
}
@ -364,9 +370,10 @@ public class DesktopController
{
if (_imageList.Selection.Any())
{
if (MessageBox.Show(string.Format(MiscResources.ConfirmResetImages, _imageList.Selection.Count),
if (MessageBox.Show(_desktopFormProvider.DesktopForm,
string.Format(MiscResources.ConfirmResetImages, _imageList.Selection.Count),
MiscResources.ResetImage,
MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
MessageBoxButtons.OKCancel, MessageBoxType.Question) == DialogResult.Ok)
{
_imageListActions.ResetTransforms();
}
@ -402,7 +409,7 @@ public class DesktopController
using var imagesToEmail = images.Select(x => x.GetClonedImage()).ToDisposableList();
await _exportHelper.EmailPDF(imagesToEmail.InnerList);
}
public async Task Print()
{
var state = _imageList.CurrentState;
@ -414,34 +421,37 @@ public class DesktopController
}
}
public void Import()
public void Import(Control parentForm)
{
// TODO: Merge this into exporthelper/dialoghelper?
var ofd = new OpenFileDialog
{
Multiselect = true,
MultiSelect = true,
CheckFileExists = true,
// TODO: Move filter logic somewhere common
Filter = MiscResources.FileTypeAllFiles + @"|*.*|" +
MiscResources.FileTypePdf + @"|*.pdf|" +
MiscResources.FileTypeImageFiles +
@"|*.bmp;*.emf;*.exif;*.gif;*.jpg;*.jpeg;*.png;*.tiff;*.tif|" +
MiscResources.FileTypeBmp + @"|*.bmp|" +
MiscResources.FileTypeEmf + @"|*.emf|" +
MiscResources.FileTypeExif + @"|*.exif|" +
MiscResources.FileTypeGif + @"|*.gif|" +
MiscResources.FileTypeJpeg + @"|*.jpg;*.jpeg|" +
MiscResources.FileTypePng + @"|*.png|" +
MiscResources.FileTypeTiff + @"|*.tiff;*.tif"
Filters =
{
// TODO: Move filter logic somewhere common
new FileFilter(MiscResources.FileTypeAllFiles, ".*"),
new FileFilter(MiscResources.FileTypePdf, ".pdf"),
new FileFilter(MiscResources.FileTypeImageFiles,
".bmp", ".emf", ".exif", ".gif", "jpg", ".jpeg", ".png", ".tiff", ".tif"),
new FileFilter(MiscResources.FileTypeBmp, ".bmp"),
new FileFilter(MiscResources.FileTypeEmf, ".emf"),
new FileFilter(MiscResources.FileTypeExif, ".exif"),
new FileFilter(MiscResources.FileTypeGif, ".gif"),
new FileFilter(MiscResources.FileTypeJpeg, ".jpg", ".jpeg"),
new FileFilter(MiscResources.FileTypePng, ".png"),
new FileFilter(MiscResources.FileTypeTiff, ".tiff", ".tif"),
}
};
if (Paths.IsTestAppDataPath)
{
// For UI test automation we choose the appdata folder to find the prepared files to import
ofd.InitialDirectory = Paths.AppData;
ofd.Directory = new Uri(Path.GetFullPath(Paths.AppData));
}
if (ofd.ShowDialog() == DialogResult.OK)
if (ofd.ShowDialog(parentForm) == DialogResult.Ok)
{
ImportFiles(ofd.FileNames);
ImportFiles(ofd.Filenames);
}
}
}

View File

@ -0,0 +1,20 @@
namespace NAPS2.WinForms;
public interface IDesktopSubFormController
{
void ShowCropForm();
void ShowBrightnessContrastForm();
void ShowHueSaturationForm();
void ShowBlackWhiteForm();
void ShowSharpenForm();
void ShowRotateForm();
void ShowProfilesForm();
void ShowOcrForm();
void ShowBatchScanForm();
void ShowViewerForm();
void ShowPdfSettingsForm();
void ShowImageSettingsForm();
void ShowEmailSettingsForm();
void ShowAboutForm();
void ShowSettingsForm();
}

View File

@ -18,7 +18,7 @@ public class WinFormsDesktopForm : DesktopForm
public WinFormsDesktopForm(
Naps2Config config,
KeyboardShortcutManager ksm,
// KeyboardShortcutManager ksm,
INotificationManager notify,
CultureHelper cultureHelper,
IProfileManager profileManager,
@ -31,7 +31,7 @@ public class WinFormsDesktopForm : DesktopForm
ImageListActions imageListActions,
DesktopFormProvider desktopFormProvider,
DesktopSubFormController desktopSubFormController)
: base(config, ksm, notify, cultureHelper, profileManager,
: base(config, /*ksm,*/ notify, cultureHelper, profileManager,
imageList, imageTransfer, thumbnailRenderQueue, thumbnailProvider, desktopController, desktopScanController,
imageListActions, desktopFormProvider, desktopSubFormController)
{

View File

@ -1,10 +1,11 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using Eto.Drawing;
using Eto.Forms;
using Eto.WinForms;
using Eto.WinForms.Forms.Controls;
using NAPS2.Images.Gdi;
using Bitmap = Eto.Drawing.Bitmap;
using sd = System.Drawing;
namespace NAPS2.EtoForms.WinForms;
@ -13,7 +14,7 @@ public class WinFormsEtoPlatform : EtoPlatform
private const int MIN_BUTTON_WIDTH = 75;
private const int MIN_BUTTON_HEIGHT = 32;
private const int IMAGE_PADDING = 5;
static WinFormsEtoPlatform()
{
ButtonHandler.DefaultMinimumSize = new Eto.Drawing.Size(MIN_BUTTON_WIDTH, MIN_BUTTON_HEIGHT);
@ -28,15 +29,15 @@ public class WinFormsEtoPlatform : EtoPlatform
{
var native = (System.Windows.Forms.Button) button.ToNative();
native.TextImageRelation = TextImageRelation.Overlay;
native.ImageAlign = ContentAlignment.MiddleLeft;
native.TextAlign = ContentAlignment.MiddleRight;
native.ImageAlign = sd.ContentAlignment.MiddleLeft;
native.TextAlign = sd.ContentAlignment.MiddleRight;
var imageWidth = native.Image.Width;
using var g = native.CreateGraphics();
var textWidth = (int) g.MeasureString(native.Text, native.Font).Width;
native.AutoSize = false;
var widthWithoutRightPadding = imageWidth + textWidth + IMAGE_PADDING + 15;
var widthWithoutRightPadding = imageWidth + textWidth + IMAGE_PADDING + 15;
native.Width = Math.Max(widthWithoutRightPadding + IMAGE_PADDING, ButtonHandler.DefaultMinimumSize.Width);
var rightPadding = IMAGE_PADDING + (native.Width - widthWithoutRightPadding - IMAGE_PADDING) / 2;
native.Padding = native.Padding with { Left = IMAGE_PADDING, Right = rightPadding };
@ -47,4 +48,29 @@ public class WinFormsEtoPlatform : EtoPlatform
{
return ((GdiImage) image).Bitmap.ToEto();
}
public override IMemoryImage DrawHourglass(IMemoryImage image)
{
var bitmap = new System.Drawing.Bitmap(image.Width, image.Height);
using (var g = sd.Graphics.FromImage(bitmap))
{
var attrs = new ImageAttributes();
attrs.SetColorMatrix(new ColorMatrix
{
Matrix33 = 0.3f
});
g.DrawImage(image.AsBitmap(),
new sd.Rectangle(0, 0, bitmap.Width, bitmap.Height),
0,
0,
image.Width,
image.Height,
sd.GraphicsUnit.Pixel,
attrs);
using var hourglass = new sd.Bitmap(new MemoryStream(Icons.hourglass_grey));
g.DrawImage(hourglass, new sd.Rectangle((bitmap.Width - 32) / 2, (bitmap.Height - 32) / 2, 32, 32));
}
image.Dispose();
return new GdiImage(bitmap);
}
}

View File

@ -263,7 +263,7 @@ public class WinFormsListView<T> : IListView<T> where T : notnull
var index = GetDragIndex(e);
if (index != -1)
{
Drop?.Invoke(this, new DropEventArgs(index, e.Data));
Drop?.Invoke(this, new DropEventArgs(index, e.Data.ToEto()));
}
_view.InsertionMark.Index = -1;
}

View File

@ -1,23 +0,0 @@
using System.Drawing.Printing;
namespace NAPS2.ImportExport;
public interface IScannedImagePrinter
{
/// <summary>
/// Prints the provided images, prompting the user for the printer settings.
/// </summary>
/// <param name="images">The full list of images to print.</param>
/// <param name="selectedImages">The list of selected images. If non-empty, the user will be presented an option to print selected.</param>
/// <returns>True if the print completed, false if there was nothing to print or the user cancelled.</returns>
Task<bool> PromptToPrint(IList<ProcessedImage> images, IList<ProcessedImage> selectedImages);
/// <summary>
/// Prints the provided images with the specified printer settings.
/// </summary>
/// <param name="printerSettings">The printer settings.</param>
/// <param name="images">The full list of images to print.</param>
/// <param name="selectedImages">The list of selected images, to be used if the printer settings specify to print selected.</param>
/// <returns>True if the print completed, false if there was nothing to print.</returns>
Task<bool> Print(PrinterSettings printerSettings, IList<ProcessedImage> images, IList<ProcessedImage> selectedImages);
}

View File

@ -30,6 +30,7 @@ public class WinFormsModule : NinjectModule
Bind<IUpdateChecker>().To<UpdateChecker>();
Bind<IWinFormsExportHelper>().To<WinFormsExportHelper>();
Bind<IDesktopScanController>().To<DesktopScanController>();
Bind<IDesktopSubFormController>().To<DesktopSubFormController>();
Bind<DesktopFormProvider>().ToSelf().InSingletonScope();
Bind<DesktopForm>().To<WinFormsDesktopForm>();

View File

@ -362,6 +362,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="ImportExport\Images" />
<Folder Include="Scan\Internal" />
</ItemGroup>

View File

@ -10,12 +10,12 @@ public class DesktopScanController : IDesktopScanController
private readonly IFormFactory _formFactory;
private readonly IScanPerformer _scanPerformer;
private readonly DesktopImagesController _desktopImagesController;
private readonly DesktopSubFormController _desktopSubFormController;
private readonly IDesktopSubFormController _desktopSubFormController;
private readonly DesktopFormProvider _desktopFormProvider;
public DesktopScanController(Naps2Config config, IProfileManager profileManager, IFormFactory formFactory,
IScanPerformer scanPerformer, DesktopImagesController desktopImagesController,
DesktopSubFormController desktopSubFormController, DesktopFormProvider desktopFormProvider)
IDesktopSubFormController desktopSubFormController, DesktopFormProvider desktopFormProvider)
{
_config = config;
_profileManager = profileManager;

View File

@ -3,7 +3,7 @@ using NAPS2.Ocr;
namespace NAPS2.WinForms;
public class DesktopSubFormController
public class DesktopSubFormController : IDesktopSubFormController
{
private readonly IFormFactory _formFactory;
private readonly UiImageList _imageList;
@ -19,7 +19,14 @@ public class DesktopSubFormController
_tesseractLanguageManager = tesseractLanguageManager;
}
public void ShowImageForm<T>() where T : ImageForm
public void ShowCropForm() => ShowImageForm<FCrop>();
public void ShowBrightnessContrastForm() => ShowImageForm<FBrightnessContrast>();
public void ShowHueSaturationForm() => ShowImageForm<FHueSaturation>();
public void ShowBlackWhiteForm() => ShowImageForm<FBlackWhite>();
public void ShowSharpenForm() => ShowImageForm<FSharpen>();
public void ShowRotateForm() => ShowImageForm<FRotate>();
private void ShowImageForm<T>() where T : ImageForm
{
var selection = _imageList.Selection.ToList();
if (selection.Any())

View File

@ -7,7 +7,11 @@ using NAPS2.EtoForms.WinForms;
using NAPS2.ImportExport;
using NAPS2.Ocr;
using NAPS2.ImportExport.Images;
using DataFormats = System.Windows.Forms.DataFormats;
using DockStyle = System.Windows.Forms.DockStyle;
using KeyEventArgs = System.Windows.Forms.KeyEventArgs;
using Keys = System.Windows.Forms.Keys;
using MouseEventArgs = System.Windows.Forms.MouseEventArgs;
namespace NAPS2.WinForms;
@ -504,7 +508,7 @@ public partial class FDesktop : FormBase
}
}
private void tsImport_Click(object sender, EventArgs e) => _desktopController.Import();
private void tsImport_Click(object sender, EventArgs e) => _desktopController.Import(Eto.Forms.WinFormsHelpers.ToEto(this));
private async void tsdSavePDF_ButtonClick(object sender, EventArgs e)
{
@ -625,18 +629,18 @@ public partial class FDesktop : FormBase
#region Event Handlers - Image Menu
private void tsView_Click(object sender, EventArgs e) => _desktopSubFormController.ShowViewerForm();
private void tsCrop_Click(object sender, EventArgs e) => _desktopSubFormController.ShowImageForm<FCrop>();
private void tsCrop_Click(object sender, EventArgs e) => _desktopSubFormController.ShowCropForm();
private void tsBrightnessContrast_Click(object sender, EventArgs e) =>
_desktopSubFormController.ShowImageForm<FBrightnessContrast>();
_desktopSubFormController.ShowBrightnessContrastForm();
private void tsHueSaturation_Click(object sender, EventArgs e) =>
_desktopSubFormController.ShowImageForm<FHueSaturation>();
_desktopSubFormController.ShowHueSaturationForm();
private void tsBlackWhite_Click(object sender, EventArgs e) =>
_desktopSubFormController.ShowImageForm<FBlackWhite>();
_desktopSubFormController.ShowBlackWhiteForm();
private void tsSharpen_Click(object sender, EventArgs e) => _desktopSubFormController.ShowImageForm<FSharpen>();
private void tsSharpen_Click(object sender, EventArgs e) => _desktopSubFormController.ShowSharpenForm();
private void tsReset_Click(object sender, EventArgs e) => _desktopController.ResetImage();
#endregion
@ -647,7 +651,7 @@ public partial class FDesktop : FormBase
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) => _desktopSubFormController.ShowImageForm<FRotate>();
private void tsCustomRotation_Click(object sender, EventArgs e) => _desktopSubFormController.ShowRotateForm();
#endregion
@ -750,9 +754,9 @@ public partial class FDesktop : FormBase
private void ListViewDrop(object? sender, DropEventArgs args)
{
if (_imageTransfer.IsIn(args.Data.ToEto()))
if (_imageTransfer.IsIn(args.Data))
{
var data = _imageTransfer.GetFrom(args.Data.ToEto());
var data = _imageTransfer.GetFrom(args.Data);
if (data.ProcessId == Process.GetCurrentProcess().Id)
{
DragMoveImages(args.Position);
@ -762,9 +766,9 @@ public partial class FDesktop : FormBase
_desktopController.ImportDirect(data, false);
}
}
else if (args.Data.GetDataPresent(DataFormats.FileDrop))
else if (args.Data.Contains(DataFormats.FileDrop))
{
var data = (string[]) args.Data.GetData(DataFormats.FileDrop);
var data = args.Data.GetObject<string[]>(DataFormats.FileDrop);
_desktopController.ImportFiles(data);
}
}