mirror of
https://github.com/cyanfish/naps2.git
synced 2024-09-11 15:26:55 +03:00
Refactor common entrypoint code into GuiEntryPoint
This commit is contained in:
parent
068cbaf24b
commit
5d2ac21185
@ -1,15 +1,9 @@
|
||||
using Autofac;
|
||||
using NAPS2.EtoForms;
|
||||
using NAPS2.EtoForms.Ui;
|
||||
using NAPS2.Modules;
|
||||
using NAPS2.Remoting.Worker;
|
||||
using NAPS2.Scan;
|
||||
using UnhandledExceptionEventArgs = Eto.UnhandledExceptionEventArgs;
|
||||
using NAPS2.Modules;
|
||||
|
||||
namespace NAPS2.EntryPoints;
|
||||
|
||||
/// <summary>
|
||||
/// The entry point logic for NAPS2.exe, the NAPS2 GUI.
|
||||
/// The entry point logic for the Gtk NAPS2 executable.
|
||||
/// </summary>
|
||||
public static class GtkEntryPoint
|
||||
{
|
||||
@ -24,50 +18,6 @@ public static class GtkEntryPoint
|
||||
return WorkerEntryPoint.Run(args.Skip(1).ToArray(), new GtkImagesModule());
|
||||
}
|
||||
|
||||
// Initialize Autofac (the DI framework)
|
||||
var container = AutoFacHelper.FromModules(
|
||||
new CommonModule(), new GtkImagesModule(), new GtkModule(), new RecoveryModule(), new ContextModule());
|
||||
|
||||
Paths.ClearTemp();
|
||||
|
||||
// Set up basic application configuration
|
||||
container.Resolve<CultureHelper>().SetCulturesFromConfig();
|
||||
TaskScheduler.UnobservedTaskException += UnhandledTaskException;
|
||||
GLib.ExceptionManager.UnhandledException += UnhandledGtkException;
|
||||
Trace.Listeners.Add(new ConsoleTraceListener());
|
||||
|
||||
// Start a pending worker process
|
||||
container.Resolve<IWorkerFactory>().Init(container.Resolve<ScanningContext>());
|
||||
|
||||
// Show the main form
|
||||
var application = EtoPlatform.Current.CreateApplication();
|
||||
application.UnhandledException += UnhandledException;
|
||||
var formFactory = container.Resolve<IFormFactory>();
|
||||
var desktop = formFactory.Create<DesktopForm>();
|
||||
application.Run(desktop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void UnhandledGtkException(GLib.UnhandledExceptionArgs e)
|
||||
{
|
||||
if (e.IsTerminating)
|
||||
{
|
||||
Log.FatalException("An error occurred that caused the task to terminate.", e.ExceptionObject as Exception ?? new Exception());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.ErrorException("An unhandled error occurred.", e.ExceptionObject as Exception ?? new Exception());
|
||||
}
|
||||
}
|
||||
|
||||
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 ?? new Exception());
|
||||
return GuiEntryPoint.Run(args, new GtkImagesModule(), new GtkModule());
|
||||
}
|
||||
}
|
@ -18,6 +18,23 @@ public class GtkEtoPlatform : EtoPlatform
|
||||
|
||||
public override bool IsGtk => true;
|
||||
|
||||
public override void InitializePlatform()
|
||||
{
|
||||
GLib.ExceptionManager.UnhandledException += UnhandledGtkException;
|
||||
}
|
||||
|
||||
private static void UnhandledGtkException(GLib.UnhandledExceptionArgs e)
|
||||
{
|
||||
if (e.IsTerminating)
|
||||
{
|
||||
Log.FatalException("An error occurred that caused the task to terminate.", e.ExceptionObject as Exception ?? new Exception());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.ErrorException("An unhandled error occurred.", e.ExceptionObject as Exception ?? new Exception());
|
||||
}
|
||||
}
|
||||
|
||||
public override Application CreateApplication()
|
||||
{
|
||||
var application = new Application(Platforms.Gtk);
|
||||
|
@ -1,15 +1,9 @@
|
||||
using Autofac;
|
||||
using NAPS2.EtoForms;
|
||||
using NAPS2.EtoForms.Ui;
|
||||
using NAPS2.Modules;
|
||||
using NAPS2.Remoting.Worker;
|
||||
using NAPS2.Scan;
|
||||
using UnhandledExceptionEventArgs = Eto.UnhandledExceptionEventArgs;
|
||||
using NAPS2.Modules;
|
||||
|
||||
namespace NAPS2.EntryPoints;
|
||||
|
||||
/// <summary>
|
||||
/// The entry point logic for NAPS2.exe, the NAPS2 GUI.
|
||||
/// The entry point logic for the Mac NAPS2 executable.
|
||||
/// </summary>
|
||||
public static class MacEntryPoint
|
||||
{
|
||||
@ -24,55 +18,6 @@ public static class MacEntryPoint
|
||||
return MacWorkerEntryPoint.Run(args.Skip(1).ToArray());
|
||||
}
|
||||
|
||||
// We start the process as a background process (by setting LSBackgroundOnly in Info.plist) and only turn it
|
||||
// into a foreground process once we know we're not in worker or console mode. This ensures workers don't have
|
||||
// a chance to show in the dock.
|
||||
MacProcessHelper.TransformThisProcessToForeground();
|
||||
|
||||
// Initialize Autofac (the DI framework)
|
||||
var container = AutoFacHelper.FromModules(
|
||||
new CommonModule(), new MacImagesModule(), new MacModule(), new RecoveryModule(), new ContextModule());
|
||||
|
||||
Paths.ClearTemp();
|
||||
|
||||
// Set up basic application configuration
|
||||
container.Resolve<CultureHelper>().SetCulturesFromConfig();
|
||||
TaskScheduler.UnobservedTaskException += UnhandledTaskException;
|
||||
Trace.Listeners.Add(new ConsoleTraceListener());
|
||||
|
||||
Runtime.MarshalManagedException += (_, eventArgs) =>
|
||||
{
|
||||
Log.ErrorException("Marshalling managed exception", eventArgs.Exception);
|
||||
eventArgs.ExceptionMode = MarshalManagedExceptionMode.ThrowObjectiveCException;
|
||||
};
|
||||
Runtime.MarshalObjectiveCException += (_, eventArgs) =>
|
||||
{
|
||||
Log.Error($"Marshalling ObjC exception: {eventArgs.Exception.Description}");
|
||||
};
|
||||
|
||||
// Start a pending worker process
|
||||
container.Resolve<IWorkerFactory>().Init(container.Resolve<ScanningContext>());
|
||||
|
||||
// Show the main form
|
||||
var application = EtoPlatform.Current.CreateApplication();
|
||||
application.UnhandledException += UnhandledException;
|
||||
var formFactory = container.Resolve<IFormFactory>();
|
||||
var desktop = formFactory.Create<DesktopForm>();
|
||||
// Invoker.Current = new WinFormsInvoker(desktop.ToNative());
|
||||
|
||||
application.Run(desktop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 ?? new Exception());
|
||||
return GuiEntryPoint.Run(args, new MacImagesModule(), new MacModule());
|
||||
}
|
||||
}
|
@ -13,6 +13,24 @@ public class MacEtoPlatform : EtoPlatform
|
||||
{
|
||||
public override bool IsMac => true;
|
||||
|
||||
public override void InitializePlatform()
|
||||
{
|
||||
// We start the process as a background process (by setting LSBackgroundOnly in Info.plist) and only turn it
|
||||
// into a foreground process once we know we're not in worker or console mode. This ensures workers don't have
|
||||
// a chance to show in the dock.
|
||||
MacProcessHelper.TransformThisProcessToForeground();
|
||||
|
||||
Runtime.MarshalManagedException += (_, eventArgs) =>
|
||||
{
|
||||
Log.ErrorException("Marshalling managed exception", eventArgs.Exception);
|
||||
eventArgs.ExceptionMode = MarshalManagedExceptionMode.ThrowObjectiveCException;
|
||||
};
|
||||
Runtime.MarshalObjectiveCException += (_, eventArgs) =>
|
||||
{
|
||||
Log.Error($"Marshalling ObjC exception: {eventArgs.Exception.Description}");
|
||||
};
|
||||
}
|
||||
|
||||
public override Application CreateApplication()
|
||||
{
|
||||
return new Application(Platforms.macOS);
|
||||
|
@ -1,16 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Autofac;
|
||||
using Eto.Forms;
|
||||
using Eto.WinForms.Forms;
|
||||
using NAPS2.EtoForms;
|
||||
using NAPS2.EtoForms.Ui;
|
||||
using NAPS2.EtoForms.WinForms;
|
||||
using NAPS2.Modules;
|
||||
using NAPS2.Platform.Windows;
|
||||
using NAPS2.Remoting.Worker;
|
||||
using NAPS2.Scan;
|
||||
using wf = System.Windows.Forms;
|
||||
using NAPS2.Modules;
|
||||
|
||||
namespace NAPS2.EntryPoints;
|
||||
|
||||
@ -26,53 +14,6 @@ public static class WinFormsEntryPoint
|
||||
return WindowsWorkerEntryPoint.Run(args.Skip(1).ToArray());
|
||||
}
|
||||
|
||||
// Initialize Autofac (the DI framework)
|
||||
var container = AutoFacHelper.FromModules(
|
||||
new CommonModule(), new GdiModule(), new WinFormsModule(), new RecoveryModule(), new ContextModule());
|
||||
|
||||
Paths.ClearTemp();
|
||||
|
||||
// Parse the command-line arguments and see if we're doing something other than displaying the main form
|
||||
var lifecycle = container.Resolve<WindowsApplicationLifecycle>();
|
||||
lifecycle.ParseArgs(args);
|
||||
lifecycle.ExitIfRedundant();
|
||||
|
||||
// Start a pending worker process
|
||||
container.Resolve<IWorkerFactory>().Init(container.Resolve<ScanningContext>());
|
||||
|
||||
// Set up basic application configuration
|
||||
container.Resolve<CultureHelper>().SetCulturesFromConfig();
|
||||
// TODO: Unify unhandled exception handling across platforms
|
||||
wf.Application.ThreadException += UnhandledException;
|
||||
TaskScheduler.UnobservedTaskException += UnhandledTaskException;
|
||||
|
||||
// Show the main form
|
||||
var application = EtoPlatform.Current.CreateApplication();
|
||||
var formFactory = container.Resolve<IFormFactory>();
|
||||
var desktop = formFactory.Create<DesktopForm>();
|
||||
|
||||
// We manually run an application rather than using eto as that lets us change the main form
|
||||
// TODO: PR for eto to handle mainform changes correctly
|
||||
application.MainForm = desktop;
|
||||
desktop.Show();
|
||||
var appContext = new wf.ApplicationContext(desktop.ToNative());
|
||||
Invoker.Current = new WinFormsInvoker(() => appContext.MainForm!);
|
||||
WinFormsDesktopForm.ApplicationContext = appContext;
|
||||
var setOptionsMethod =
|
||||
typeof(ApplicationHandler).GetMethod("SetOptions", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
setOptionsMethod!.Invoke(application.Handler, Array.Empty<object>());
|
||||
wf.Application.Run(appContext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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, ThreadExceptionEventArgs e)
|
||||
{
|
||||
Log.FatalException("An error occurred that caused the application to close.", e.Exception);
|
||||
return GuiEntryPoint.Run(args, new GdiModule(), new WinFormsModule());
|
||||
}
|
||||
}
|
@ -1,8 +1,4 @@
|
||||
using Autofac;
|
||||
using CommandLine;
|
||||
using NAPS2.Automation;
|
||||
using NAPS2.Modules;
|
||||
using NAPS2.Remoting.Worker;
|
||||
using NAPS2.Modules;
|
||||
|
||||
namespace NAPS2.EntryPoints;
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using Eto.Drawing;
|
||||
using Eto.Forms;
|
||||
using Eto.WinForms;
|
||||
using Eto.WinForms.Forms;
|
||||
using Eto.WinForms.Forms.Controls;
|
||||
using NAPS2.EtoForms.Layout;
|
||||
using NAPS2.EtoForms.Ui;
|
||||
using NAPS2.EtoForms.Widgets;
|
||||
using NAPS2.Images.Gdi;
|
||||
using sd = System.Drawing;
|
||||
@ -27,6 +30,21 @@ public class WinFormsEtoPlatform : EtoPlatform
|
||||
return new Application(Eto.Platforms.WinForms);
|
||||
}
|
||||
|
||||
public override void RunApplication(Application application, Form mainForm)
|
||||
{
|
||||
// We manually run an application rather than using eto as that lets us change the main form
|
||||
// TODO: PR for eto to handle mainform changes correctly
|
||||
application.MainForm = mainForm;
|
||||
mainForm.Show();
|
||||
var appContext = new wf.ApplicationContext(mainForm.ToNative());
|
||||
Invoker.Current = new WinFormsInvoker(() => appContext.MainForm!);
|
||||
WinFormsDesktopForm.ApplicationContext = appContext;
|
||||
var setOptionsMethod =
|
||||
typeof(ApplicationHandler).GetMethod("SetOptions", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
setOptionsMethod!.Invoke(application.Handler, Array.Empty<object>());
|
||||
wf.Application.Run(appContext);
|
||||
}
|
||||
|
||||
public override IListView<T> CreateListView<T>(ListViewBehavior<T> behavior) =>
|
||||
new WinFormsListView<T>(behavior);
|
||||
|
||||
|
@ -3,7 +3,7 @@ using NAPS2.EtoForms;
|
||||
using NAPS2.EtoForms.Ui;
|
||||
using NAPS2.EtoForms.WinForms;
|
||||
using NAPS2.ImportExport;
|
||||
using NAPS2.WinForms;
|
||||
using NAPS2.Platform.Windows;
|
||||
|
||||
namespace NAPS2.Modules;
|
||||
|
||||
@ -13,6 +13,7 @@ public class WinFormsModule : GuiModule
|
||||
{
|
||||
base.Load(builder);
|
||||
|
||||
builder.RegisterType<WindowsApplicationLifecycle>().As<ApplicationLifecycle>();
|
||||
builder.RegisterType<PrintDocumentPrinter>().As<IScannedImagePrinter>();
|
||||
builder.RegisterType<WinFormsDarkModeProvider>().As<IDarkModeProvider>().SingleInstance();
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace NAPS2.Platform.Windows;
|
||||
/// <summary>
|
||||
/// A class to help manage the lifecycle of the NAPS2 GUI.
|
||||
/// </summary>
|
||||
public class WindowsApplicationLifecycle
|
||||
public class WindowsApplicationLifecycle : ApplicationLifecycle
|
||||
{
|
||||
private readonly StillImage _sti;
|
||||
private readonly WindowsEventLogger _windowsEventLogger;
|
||||
@ -28,7 +28,7 @@ public class WindowsApplicationLifecycle
|
||||
/// Parses the NAPS2 GUI command-line arguments.
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
public void ParseArgs(string[] args)
|
||||
public override void ParseArgs(string[] args)
|
||||
{
|
||||
bool silent = args.Any(x => x.Equals("/Silent", StringComparison.InvariantCultureIgnoreCase));
|
||||
bool noElevation = args.Any(x => x.Equals("/NoElevation", StringComparison.InvariantCultureIgnoreCase));
|
||||
@ -150,7 +150,7 @@ public class WindowsApplicationLifecycle
|
||||
/// <summary>
|
||||
/// May terminate the NAPS2 GUI based on the command-line arguments and running processes, sending messages to other processes if appropriate.
|
||||
/// </summary>
|
||||
public void ExitIfRedundant()
|
||||
public override void ExitIfRedundant()
|
||||
{
|
||||
if (_sti.ShouldRegister || _sti.ShouldUnregister || _shouldCreateEventSource)
|
||||
{
|
||||
|
59
NAPS2.Lib/EntryPoints/GuiEntryPoint.cs
Normal file
59
NAPS2.Lib/EntryPoints/GuiEntryPoint.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using Autofac;
|
||||
using NAPS2.EtoForms;
|
||||
using NAPS2.EtoForms.Ui;
|
||||
using NAPS2.Modules;
|
||||
using NAPS2.Remoting.Worker;
|
||||
using NAPS2.Scan;
|
||||
|
||||
namespace NAPS2.EntryPoints;
|
||||
|
||||
/// <summary>
|
||||
/// The entry point for the main NAPS2 executable.
|
||||
/// </summary>
|
||||
public static class GuiEntryPoint
|
||||
{
|
||||
public static int Run(string[] args, Module imageModule, Module guiModule)
|
||||
{
|
||||
// Initialize Autofac (the DI framework)
|
||||
var container = AutoFacHelper.FromModules(
|
||||
new CommonModule(), imageModule, guiModule, new RecoveryModule(), new ContextModule());
|
||||
|
||||
Paths.ClearTemp();
|
||||
|
||||
// Parse the command-line arguments and see if we're doing something other than displaying the main form
|
||||
var lifecycle = container.Resolve<ApplicationLifecycle>();
|
||||
lifecycle.ParseArgs(args);
|
||||
lifecycle.ExitIfRedundant();
|
||||
|
||||
EtoPlatform.Current.InitializePlatform();
|
||||
|
||||
// Set up basic application configuration
|
||||
container.Resolve<CultureHelper>().SetCulturesFromConfig();
|
||||
TaskScheduler.UnobservedTaskException += UnhandledTaskException;
|
||||
Trace.Listeners.Add(new ConsoleTraceListener());
|
||||
|
||||
// Start a pending worker process
|
||||
container.Resolve<IWorkerFactory>().Init(container.Resolve<ScanningContext>());
|
||||
|
||||
// Show the main form
|
||||
var application = EtoPlatform.Current.CreateApplication();
|
||||
application.UnhandledException += UnhandledException;
|
||||
var formFactory = container.Resolve<IFormFactory>();
|
||||
var desktop = formFactory.Create<DesktopForm>();
|
||||
|
||||
EtoPlatform.Current.RunApplication(application, desktop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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, Eto.UnhandledExceptionEventArgs e)
|
||||
{
|
||||
Log.FatalException("An error occurred that caused the application to close.",
|
||||
e.ExceptionObject as Exception ?? new Exception());
|
||||
}
|
||||
}
|
@ -32,6 +32,15 @@ public abstract class EtoPlatform
|
||||
public abstract Control AccessibleImageButton(Image image, string text, Action onClick,
|
||||
int xOffset = 0, int yOffset = 0);
|
||||
|
||||
public virtual void InitializePlatform()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void RunApplication(Application application, Form mainForm)
|
||||
{
|
||||
application.Run(mainForm);
|
||||
}
|
||||
|
||||
public virtual void SetContainerSize(Window window, Control container, Size size, int padding)
|
||||
{
|
||||
}
|
||||
|
12
NAPS2.Lib/Platform/ApplicationLifecycle.cs
Normal file
12
NAPS2.Lib/Platform/ApplicationLifecycle.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace NAPS2.Platform;
|
||||
|
||||
public class ApplicationLifecycle
|
||||
{
|
||||
public virtual void ParseArgs(string[] args)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void ExitIfRedundant()
|
||||
{
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user