From d17c65dd222d831885d0a5f99af5535ab840c524 Mon Sep 17 00:00:00 2001 From: Ben Olden-Cooligan Date: Sat, 20 Aug 2022 20:42:28 -0700 Subject: [PATCH] Get NAPS2 app running on mac Not showing any ui yet --- NAPS2.App.Mac/.gitignore | 31 +++ NAPS2.App.Mac/Icon.icns | Bin 0 -> 20732 bytes NAPS2.App.Mac/Info.plist | 21 ++ NAPS2.App.Mac/NAPS2.App.Mac.csproj | 39 ++++ NAPS2.App.Mac/Program.cs | 15 ++ NAPS2.Images.Mac/MacImage.cs | 23 +- NAPS2.Lib.Mac/EntryPoints/MacEntryPoint.cs | 51 +++++ NAPS2.Lib.Mac/EtoForms/Mac/MacEtoPlatform.cs | 38 ++++ NAPS2.Lib.Mac/EtoForms/Mac/MacListView.cs | 75 +++++++ NAPS2.Lib.Mac/EtoForms/Ui/MacDesktopForm.cs | 43 ++++ NAPS2.Lib.Mac/Modules/MacModule.cs | 209 +++++++++++++++++++ NAPS2.Lib.Mac/NAPS2.Lib.Mac.csproj | 6 +- NAPS2.Lib/EtoForms/Ui/DesktopForm.cs | 17 +- NAPS2.sln | 14 ++ 14 files changed, 564 insertions(+), 18 deletions(-) create mode 100644 NAPS2.App.Mac/.gitignore create mode 100644 NAPS2.App.Mac/Icon.icns create mode 100644 NAPS2.App.Mac/Info.plist create mode 100644 NAPS2.App.Mac/NAPS2.App.Mac.csproj create mode 100644 NAPS2.App.Mac/Program.cs create mode 100644 NAPS2.Lib.Mac/EntryPoints/MacEntryPoint.cs create mode 100644 NAPS2.Lib.Mac/EtoForms/Mac/MacEtoPlatform.cs create mode 100644 NAPS2.Lib.Mac/EtoForms/Mac/MacListView.cs create mode 100644 NAPS2.Lib.Mac/EtoForms/Ui/MacDesktopForm.cs create mode 100644 NAPS2.Lib.Mac/Modules/MacModule.cs diff --git a/NAPS2.App.Mac/.gitignore b/NAPS2.App.Mac/.gitignore new file mode 100644 index 000000000..a8a3b16a8 --- /dev/null +++ b/NAPS2.App.Mac/.gitignore @@ -0,0 +1,31 @@ +Thumbs.db +*.obj +*.exe +*.pdb +*.user +*.aps +*.pch +*.vspscc +*_i.c +*_p.c +*.ncb +*.suo +*.sln.docstates +*.tlb +*.tlh +*.bak +*.cache +*.ilk +*.log +[Bb]in +[Dd]ebug*/ +*.lib +*.sbr +obj/ +[Rr]elease*/ +_ReSharper*/ +[Tt]est[Rr]esult* +*.vssscc +$tf*/ +publish/ +bin/ \ No newline at end of file diff --git a/NAPS2.App.Mac/Icon.icns b/NAPS2.App.Mac/Icon.icns new file mode 100644 index 0000000000000000000000000000000000000000..5e8d6ff8c82940cbb0f54dfcd154c4309b087c48 GIT binary patch literal 20732 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 Q&j0`b07*qoM6N<$g4oP-3;+NC literal 0 HcmV?d00001 diff --git a/NAPS2.App.Mac/Info.plist b/NAPS2.App.Mac/Info.plist new file mode 100644 index 000000000..8ca4a3add --- /dev/null +++ b/NAPS2.App.Mac/Info.plist @@ -0,0 +1,21 @@ + + + + + CFBundleName + NAPS2 + CFBundleIdentifier + com.naps2.desktop + CFBundleShortVersionString + 1.0 + LSMinimumSystemVersion + 10.15 + CFBundleDevelopmentRegion + en + NSHumanReadableCopyright + + + CFBundleIconFile + Icon.icns + + diff --git a/NAPS2.App.Mac/NAPS2.App.Mac.csproj b/NAPS2.App.Mac/NAPS2.App.Mac.csproj new file mode 100644 index 000000000..01aff6fdc --- /dev/null +++ b/NAPS2.App.Mac/NAPS2.App.Mac.csproj @@ -0,0 +1,39 @@ + + + + net6 + Exe + NAPS2 + NAPS2 + 7.0.1 + ../NAPS2.Lib/Icons/favicon.ico + + true + true + true + + + osx-arm64 + + NAPS2 (Not Another PDF Scanner 2) + NAPS2 (Not Another PDF Scanner 2) + Copyright 2009, 2012-2022 NAPS2 Contributors + + + + + + + + + + + + + + Always + appsettings.xml + appsettings.xml + + + \ No newline at end of file diff --git a/NAPS2.App.Mac/Program.cs b/NAPS2.App.Mac/Program.cs new file mode 100644 index 000000000..5ec76fe76 --- /dev/null +++ b/NAPS2.App.Mac/Program.cs @@ -0,0 +1,15 @@ +using NAPS2.EntryPoints; + +namespace NAPS2; + +static class Program +{ + /// + /// The NAPS2.app main method. + /// + static void Main(string[] args) + { + // Use reflection to avoid antivirus false positives (yes, really) + typeof(MacEntryPoint).GetMethod("Run").Invoke(null, new object[] { args }); + } +} \ No newline at end of file diff --git a/NAPS2.Images.Mac/MacImage.cs b/NAPS2.Images.Mac/MacImage.cs index e6b338582..d051da1e5 100644 --- a/NAPS2.Images.Mac/MacImage.cs +++ b/NAPS2.Images.Mac/MacImage.cs @@ -4,19 +4,18 @@ namespace NAPS2.Images.Mac; public class MacImage : IMemoryImage { - private readonly NSImage _image; internal readonly NSBitmapImageRep _imageRep; public MacImage(NSImage image) { - _image = image; + NsImage = image; // TODO: Better error checking lock (MacImageContext.ConstructorLock) { #if MONOMAC - _imageRep = new NSBitmapImageRep(_image.Representations()[0].Handle, false); + _imageRep = new NSBitmapImageRep(Image.Representations()[0].Handle, false); #else - _imageRep = (NSBitmapImageRep) _image.Representations()[0]; + _imageRep = (NSBitmapImageRep) NsImage.Representations()[0]; #endif } // TODO: Also verify color spaces. @@ -45,23 +44,25 @@ public class MacImage : IMemoryImage } } + public NSImage NsImage { get; } + public void Dispose() { - _image.Dispose(); + Image.Dispose(); // TODO: Does this need to dispose the imageRep? } public int Width => (int) _imageRep.PixelsWide; public int Height => (int) _imageRep.PixelsHigh; - public float HorizontalResolution => (float) _image.Size.Width.ToDouble() / Width * 72; - public float VerticalResolution => (float) _image.Size.Height.ToDouble() / Height * 72; + public float HorizontalResolution => (float) Image.Size.Width.ToDouble() / Width * 72; + public float VerticalResolution => (float) Image.Size.Height.ToDouble() / Height * 72; public void SetResolution(float xDpi, float yDpi) { // TODO: Image size or imagerep size? if (xDpi > 0 && yDpi > 0) { - _image.Size = new CGSize(xDpi / 72 * Width, yDpi / 72 * Height); + Image.Size = new CGSize(xDpi / 72 * Width, yDpi / 72 * Height); } } @@ -94,6 +95,8 @@ public class MacImage : IMemoryImage public ImageFileFormat OriginalFileFormat { get; set; } + public NSImage Image => NsImage; + public void Save(string path, ImageFileFormat imageFormat = ImageFileFormat.Unspecified, int quality = -1) { if (imageFormat == ImageFileFormat.Unspecified) @@ -156,9 +159,9 @@ public class MacImage : IMemoryImage } #if MONOMAC - var nsImage = new NSImage(_image.Copy().Handle, true); + var nsImage = new NSImage(Image.Copy().Handle, true); #else - var nsImage = (NSImage) _image.Copy(); + var nsImage = (NSImage) NsImage.Copy(); #endif return new MacImage(nsImage) { diff --git a/NAPS2.Lib.Mac/EntryPoints/MacEntryPoint.cs b/NAPS2.Lib.Mac/EntryPoints/MacEntryPoint.cs new file mode 100644 index 000000000..8df17e689 --- /dev/null +++ b/NAPS2.Lib.Mac/EntryPoints/MacEntryPoint.cs @@ -0,0 +1,51 @@ +using System; +using System.Threading.Tasks; +using Eto; +using Eto.Forms; +using NAPS2.EtoForms.Ui; +using NAPS2.Logging; +using NAPS2.Modules; +using NAPS2.Util; +using NAPS2.WinForms; +using Ninject; +using UnhandledExceptionEventArgs = Eto.UnhandledExceptionEventArgs; + +namespace NAPS2.EntryPoints; + +/// +/// The entry point logic for NAPS2.exe, the NAPS2 GUI. +/// +public static class MacEntryPoint +{ + public static void Run(string[] args) + { + // Initialize Ninject (the DI framework) + var kernel = new StandardKernel(new CommonModule(), new MacModule(), new RecoveryModule(), new ContextModule()); + + Paths.ClearTemp(); + + // Set up basic application configuration + kernel.Get().SetCulturesFromConfig(); + TaskScheduler.UnobservedTaskException += UnhandledTaskException; + + // Show the main form + var application = new Application(Platforms.Mac64); + application.UnhandledException += UnhandledException; + var formFactory = kernel.Get(); + var desktop = formFactory.Create(); + // Invoker.Current = new WinFormsInvoker(desktop.ToNative()); + + application.Run(desktop); + } + + private static void UnhandledTaskException(object? sender, UnobservedTaskExceptionEventArgs e) + { + Log.FatalException("An error occurred that caused the task to terminate.", e.Exception); + e.SetObserved(); + } + + private static void UnhandledException(object? sender, UnhandledExceptionEventArgs e) + { + Log.FatalException("An error occurred that caused the application to close.", e.ExceptionObject as Exception); + } +} \ No newline at end of file diff --git a/NAPS2.Lib.Mac/EtoForms/Mac/MacEtoPlatform.cs b/NAPS2.Lib.Mac/EtoForms/Mac/MacEtoPlatform.cs new file mode 100644 index 000000000..652a597e6 --- /dev/null +++ b/NAPS2.Lib.Mac/EtoForms/Mac/MacEtoPlatform.cs @@ -0,0 +1,38 @@ +using Eto.Drawing; +using Eto.Forms; +using Eto.Mac.Drawing; +using NAPS2.Images; +using NAPS2.Images.Mac; +using sd = System.Drawing; + +namespace NAPS2.EtoForms.Mac; + +public class MacEtoPlatform : EtoPlatform +{ + private const int MIN_BUTTON_WIDTH = 75; + private const int MIN_BUTTON_HEIGHT = 32; + private const int IMAGE_PADDING = 5; + + static MacEtoPlatform() + { + } + + public override IListView CreateListView(ListViewBehavior behavior) => + new MacListView(behavior); + + public override void ConfigureImageButton(Button button) + { + } + + public override Bitmap ToBitmap(IMemoryImage image) + { + var nsImage = ((MacImage) image).NsImage; + return new Bitmap(new BitmapHandler(nsImage)); + } + + public override IMemoryImage DrawHourglass(IMemoryImage image) + { + // TODO + return image; + } +} \ No newline at end of file diff --git a/NAPS2.Lib.Mac/EtoForms/Mac/MacListView.cs b/NAPS2.Lib.Mac/EtoForms/Mac/MacListView.cs new file mode 100644 index 000000000..dd0955f5e --- /dev/null +++ b/NAPS2.Lib.Mac/EtoForms/Mac/MacListView.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using Eto.Forms; +using NAPS2.Images; +using NAPS2.Util; + +namespace NAPS2.EtoForms.Mac; + +public class MacListView : IListView where T : notnull +{ + private readonly ListViewBehavior _behavior; + + private ListSelection _selection = ListSelection.Empty(); + private bool _refreshing; + + public MacListView(ListViewBehavior behavior) + { + _behavior = behavior; + } + + public int ImageSize + { + get => 0; + set { } + } + + // TODO: Properties here vs on behavior? + public bool AllowDrag { get; set; } + + public bool AllowDrop { get; set; } + + private void OnDragEnter(object? sender, DragEventArgs e) + { + if (!AllowDrop) + { + return; + } + e.Effects = _behavior.GetDropEffect(e.Data); + } + + public Control Control { get; set; } + + public event EventHandler? SelectionChanged; + + public event EventHandler? ItemClicked; + + public event EventHandler? Drop; + + public void SetItems(IEnumerable items) + { + } + + // TODO: Do we need this method? Clean up the name/doc at least + public void RegenerateImages() + { + } + + public void ApplyDiffs(ListViewDiffs diffs) + { + } + + public ListSelection Selection + { + get => _selection; + set + { + if (_selection == value) + { + return; + } + _selection = value ?? throw new ArgumentNullException(nameof(value)); + SelectionChanged?.Invoke(this, EventArgs.Empty); + } + } +} \ No newline at end of file diff --git a/NAPS2.Lib.Mac/EtoForms/Ui/MacDesktopForm.cs b/NAPS2.Lib.Mac/EtoForms/Ui/MacDesktopForm.cs new file mode 100644 index 000000000..57afb7aaf --- /dev/null +++ b/NAPS2.Lib.Mac/EtoForms/Ui/MacDesktopForm.cs @@ -0,0 +1,43 @@ +using NAPS2.Config; +using NAPS2.Images; +using NAPS2.ImportExport.Images; +using NAPS2.Util; +using NAPS2.WinForms; + +namespace NAPS2.EtoForms.Ui; + +public class MacDesktopForm : DesktopForm +{ + public MacDesktopForm( + Naps2Config config, + // KeyboardShortcutManager ksm, + INotificationManager notify, + CultureHelper cultureHelper, + IProfileManager profileManager, + UiImageList imageList, + ImageTransfer imageTransfer, + ThumbnailRenderQueue thumbnailRenderQueue, + UiThumbnailProvider thumbnailProvider, + DesktopController desktopController, + IDesktopScanController desktopScanController, + ImageListActions imageListActions, + DesktopFormProvider desktopFormProvider, + IDesktopSubFormController desktopSubFormController) + : base(config, /*ksm,*/ notify, cultureHelper, profileManager, + imageList, imageTransfer, thumbnailRenderQueue, thumbnailProvider, desktopController, desktopScanController, + imageListActions, desktopFormProvider, desktopSubFormController) + { + } + + protected override void CreateToolbarsAndMenus() + { + } + + protected override void ConfigureToolbar() + { + } + + protected override void AfterLayout() + { + } +} \ No newline at end of file diff --git a/NAPS2.Lib.Mac/Modules/MacModule.cs b/NAPS2.Lib.Mac/Modules/MacModule.cs new file mode 100644 index 000000000..12640f970 --- /dev/null +++ b/NAPS2.Lib.Mac/Modules/MacModule.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using NAPS2.EtoForms; +using NAPS2.EtoForms.Mac; +using NAPS2.EtoForms.Ui; +using NAPS2.Images; +using NAPS2.ImportExport; +using NAPS2.ImportExport.Email; +using NAPS2.ImportExport.Pdf; +using NAPS2.Logging; +using NAPS2.Operation; +using NAPS2.Scan; +using NAPS2.Update; +using NAPS2.Util; +using NAPS2.WinForms; +using Ninject; +using Ninject.Modules; + +namespace NAPS2.Modules; + +public class MacModule : NinjectModule +{ + public override void Load() + { + // Bind().To(); + Bind().To(); + Bind().To(); + Bind().To(); + Bind().To().InSingletonScope(); + Bind().To(); + Bind().To().InSingletonScope(); + Bind().ToMethod(ctx => ctx.Kernel.Get()); + Bind().To(); + Bind().To(); + Bind().ToSelf().InSingletonScope(); + Bind().To(); + Bind().To(); + Bind().To(); + Bind().To(); + Bind().ToSelf().InSingletonScope(); + + Bind().To(); + + EtoPlatform.Current = new MacEtoPlatform(); + // Log.EventLogger = new WindowsEventLogger(Kernel!.Get()); + } +} + +public class StubDesktopSubFormController : IDesktopSubFormController +{ + public void ShowCropForm() + { + } + + public void ShowBrightnessContrastForm() + { + } + + public void ShowHueSaturationForm() + { + } + + public void ShowBlackWhiteForm() + { + } + + public void ShowSharpenForm() + { + } + + public void ShowRotateForm() + { + } + + public void ShowProfilesForm() + { + } + + public void ShowOcrForm() + { + } + + public void ShowBatchScanForm() + { + } + + public void ShowViewerForm() + { + } + + public void ShowPdfSettingsForm() + { + } + + public void ShowImageSettingsForm() + { + } + + public void ShowEmailSettingsForm() + { + } + + public void ShowAboutForm() + { + } + + public void ShowSettingsForm() + { + } +} + +public class StubDesktopScanController : IDesktopScanController +{ + public Task ScanWithDevice(string deviceID) + { + return Task.CompletedTask; + } + + public Task ScanDefault() + { + return Task.CompletedTask; + } + + public Task ScanWithNewProfile() + { + return Task.CompletedTask; + } + + public Task ScanWithProfile(ScanProfile profile) + { + return Task.CompletedTask; + } +} + +public class StubExportHelper : IWinFormsExportHelper +{ + public Task SavePDF(IList images, ISaveNotify notify) + { + return Task.FromResult(false); + } + + public Task ExportPDF(string filename, IList images, bool email, EmailMessage emailMessage) + { + return Task.FromResult(false); + } + + public Task SaveImages(IList images, ISaveNotify notify) + { + return Task.FromResult(false); + } + + public Task EmailPDF(IList images) + { + return Task.FromResult(false); + } +} + +public class StubDevicePrompt : IDevicePrompt +{ + public ScanDevice? PromptForDevice(List deviceList, IntPtr dialogParent) + { + return null; + } +} + +public class StubScannedImagePrinter : IScannedImagePrinter +{ + public Task PromptToPrint(IList images, IList selectedImages) + { + return Task.FromResult(false); + } +} + +public class StubNotificationManager : INotificationManager +{ + public void PdfSaved(string path) + { + } + + public void ImagesSaved(int imageCount, string path) + { + } + + public void DonatePrompt() + { + } + + public void OperationProgress(OperationProgress opModalProgress, IOperation op) + { + } + + public void UpdateAvailable(IUpdateChecker updateChecker, UpdateInfo update) + { + } + + public void Rebuild() + { + } +} + +public class StubPdfPasswordProvider : IPdfPasswordProvider +{ + public bool ProvidePassword(string fileName, int attemptCount, out string password) + { + password = null!; + return false; + } +} \ No newline at end of file diff --git a/NAPS2.Lib.Mac/NAPS2.Lib.Mac.csproj b/NAPS2.Lib.Mac/NAPS2.Lib.Mac.csproj index 2b24dd582..18e6dc055 100644 --- a/NAPS2.Lib.Mac/NAPS2.Lib.Mac.csproj +++ b/NAPS2.Lib.Mac/NAPS2.Lib.Mac.csproj @@ -1,7 +1,8 @@ - net6;net6-macos10.15 + + net6 enable true NAPS2 @@ -15,7 +16,8 @@ - + + diff --git a/NAPS2.Lib/EtoForms/Ui/DesktopForm.cs b/NAPS2.Lib/EtoForms/Ui/DesktopForm.cs index b2f5cdb13..585ec353d 100644 --- a/NAPS2.Lib/EtoForms/Ui/DesktopForm.cs +++ b/NAPS2.Lib/EtoForms/Ui/DesktopForm.cs @@ -433,17 +433,22 @@ public abstract class DesktopForm : EtoFormBase { } - protected abstract void ConfigureToolbar(); + protected virtual void ConfigureToolbar() + { + } - protected abstract void CreateToolbarButton(Command command); + protected virtual void CreateToolbarButton(Command command) => throw new InvalidOperationException(); - protected abstract void CreateToolbarButtonWithMenu(Command command, MenuProvider menu); + protected virtual void CreateToolbarButtonWithMenu(Command command, MenuProvider menu) => + throw new InvalidOperationException(); - protected abstract void CreateToolbarMenu(Command command, MenuProvider menu); + protected virtual void CreateToolbarMenu(Command command, MenuProvider menu) => + throw new InvalidOperationException(); - protected abstract void CreateToolbarStackedButtons(Command command1, Command command2); + protected virtual void CreateToolbarStackedButtons(Command command1, Command command2) => + throw new InvalidOperationException(); - protected abstract void CreateToolbarSeparator(); + protected virtual void CreateToolbarSeparator() => throw new InvalidOperationException(); protected virtual void SetContent(Control content) { diff --git a/NAPS2.sln b/NAPS2.sln index aadfa7a1f..614eef03b 100644 --- a/NAPS2.sln +++ b/NAPS2.sln @@ -62,6 +62,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NAPS2.Escl.Client", "NAPS2. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NAPS2.Escl.Tests", "NAPS2.Escl.Tests\NAPS2.Escl.Tests.csproj", "{ECD69481-CD4D-4EEC-A3BA-612DB29F13B3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NAPS2.App.Mac", "NAPS2.App.Mac\NAPS2.App.Mac.csproj", "{A280B315-3670-484D-B7A1-294E3DE56E7E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -338,6 +340,18 @@ Global {ECD69481-CD4D-4EEC-A3BA-612DB29F13B3}.Standalone|Any CPU.Build.0 = Debug|Any CPU {ECD69481-CD4D-4EEC-A3BA-612DB29F13B3}.Tools|Any CPU.ActiveCfg = Debug|Any CPU {ECD69481-CD4D-4EEC-A3BA-612DB29F13B3}.Tools|Any CPU.Build.0 = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.DebugLang|Any CPU.ActiveCfg = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.DebugLang|Any CPU.Build.0 = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.InstallerEXE|Any CPU.ActiveCfg = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.InstallerEXE|Any CPU.Build.0 = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.InstallerMSI|Any CPU.ActiveCfg = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.InstallerMSI|Any CPU.Build.0 = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.Standalone|Any CPU.ActiveCfg = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.Standalone|Any CPU.Build.0 = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.Tools|Any CPU.ActiveCfg = Debug|Any CPU + {A280B315-3670-484D-B7A1-294E3DE56E7E}.Tools|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE