예제 #1
0
        public static void Main()
        {
            // this sets the global culture for the app and all new threads
            CultureInfo.DefaultThreadCurrentCulture   = CultureInfo.InvariantCulture;
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;

            // and make sure the app is set correctly
            Thread.CurrentThread.CurrentCulture   = CultureInfo.InvariantCulture;
            Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;

            if (AggContext.OperatingSystem == OSType.Mac)
            {
                _raygunClient = new RaygunClient("qmMBpKy3OSTJj83+tkO7BQ==");                 // this is the Mac key
            }
            else
            {
                _raygunClient = new RaygunClient("hQIlyUUZRGPyXVXbI6l1dA==");                 // this is the PC key
            }

            AggContext.Init(embeddedResourceName: "config.json");

            // Make sure we have the right working directory as we assume everything relative to the executable.
            Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));

            Datastore.Instance.Initialize();

#if !DEBUG
            // Conditionally spin up error reporting if not on the Stable channel
            string channel = UserSettings.Instance.get(UserSettingsKey.UpdateFeedType);
            if (string.IsNullOrEmpty(channel) || channel != "release" || OemSettings.Instance.WindowTitleExtra == "Experimental")
#endif
            {
                System.Windows.Forms.Application.ThreadException += (s, e) =>
                {
                    if (raygunNotificationCount++ < RaygunMaxNotifications)
                    {
                        _raygunClient.Send(e.Exception);
                    }
                };

                AppDomain.CurrentDomain.UnhandledException += (s, e) =>
                {
                    if (raygunNotificationCount++ < RaygunMaxNotifications)
                    {
                        _raygunClient.Send(e.ExceptionObject as Exception);
                    }
                };
            }

            // Get startup bounds from MatterControl and construct system window
            //var systemWindow = new DesktopMainWindow(400, 200)
            var(width, height) = RootSystemWindow.GetStartupBounds();

            var systemWindow = Application.LoadRootWindow(width, height);
            systemWindow.ShowAsSystemWindow();
        }
예제 #2
0
        static void Main(string[] args)
        {
            // this sets the global culture for the app and all new threads
            CultureInfo.DefaultThreadCurrentCulture   = CultureInfo.InvariantCulture;
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;

            // make sure we can bulid a system relevant serial port
            FrostedSerialPortFactory.GetPlatformSerialPort = (serialPortName) =>
            {
                return(new CSharpSerialPortWrapper(serialPortName));
            };

            // and make sure the app is set correctly
            Thread.CurrentThread.CurrentCulture   = CultureInfo.InvariantCulture;
            Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;

            // Set default Agg providers
            AggContext.Config.ProviderTypes.SystemWindowProvider = "MatterHackers.Agg.UI.OpenGLWinformsWindowProvider, agg_platform_win32";
            //AggContext.Config.ProviderTypes.SystemWindowProvider = "MatterHackers.MatterControl.WinformsSingleWindowProvider, MatterControl.Winforms";

            string userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

            // Load optional user configuration
            IConfiguration config = new ConfigurationBuilder()
                                    .AddJsonFile("appsettings.json", optional: true)
                                    .AddJsonFile(Path.Combine(userProfilePath, "MatterControl.json"), optional: true)
                                    .Build();

            // Override defaults via configuration
            config.Bind("Agg:ProviderTypes", AggContext.Config.ProviderTypes);
            config.Bind("Agg:GraphicsMode", AggContext.Config.GraphicsMode);

            Slicer.RunInProcess = config.GetValue <bool>("MatterControl:Slicer:Debug");
            Slicer.RunInProcess = true;

            // Make sure we have the right working directory as we assume everything relative to the executable.
            Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));

            Datastore.Instance.Initialize();

            // Init platformFeaturesProvider before ShowAsSystemWindow
            string platformFeaturesProvider = "MatterHackers.MatterControl.WindowsPlatformsFeatures, MatterControl.Winforms";

            MatterHackers.MatterControl.AppContext.Platform = AggContext.CreateInstanceFrom <INativePlatformFeatures>(platformFeaturesProvider);
            MatterHackers.MatterControl.AppContext.Platform.ProcessCommandline();

            config.Bind("MatterControl", MatterHackers.MatterControl.AppContext.Options);

            // Get startup bounds from MatterControl and construct system window
            //var systemWindow = new DesktopMainWindow(400, 200)
            var(width, height) = RootSystemWindow.GetStartupBounds();

            var systemWindow = Application.LoadRootWindow(width, height);

            systemWindow.ShowAsSystemWindow();
        }
예제 #3
0
        public static void Main(string[] args)
        {
#if false // this is for some early testing of SLA output
            var test = new PhotonFile();
            void Progress(string message)
            {
                Debug.WriteLine(message);
            }

            var sourceFile = @"C:\Users\LarsBrubaker\Downloads\10mm-benchy.photon";
            if (File.Exists(sourceFile))
            {
                test.ReadFile(sourceFile, Progress);
                test.SaveFile(@"C:\Users\LarsBrubaker\Downloads\10mm-bench2.photon");
            }
            else
            {
                sourceFile = @"C:\Users\larsb\Downloads\_rocktopus.ctb";
                test.ReadFile(sourceFile, Progress);
                test.SaveFile(@"C:\Users\larsb\Downloads\_rocktopus.photon");
            }
#endif

#if false // this is for processing print log exports
            var filename    = "C:\\Users\\LarsBrubaker\\Downloads\\210309 B2 print_log.txt";
            var lines       = File.ReadAllLines(filename);
            var newPosition = default(Vector3);
            var ePosition   = 0.0;
            var instruction = 0;
            var layer       = 0;
            using (var writetext = new StreamWriter("C:\\Temp\\printlog.gcode"))
            {
                foreach (var line in lines)
                {
                    if (line.Contains(" G1 "))
                    {
                        GCodeFile.GetFirstNumberAfter("X", line, ref newPosition.X);
                        GCodeFile.GetFirstNumberAfter("Y", line, ref newPosition.Y);
                        GCodeFile.GetFirstNumberAfter("Z", line, ref newPosition.Z);
                        GCodeFile.GetFirstNumberAfter("E", line, ref ePosition);

                        writetext.WriteLine($"G1 X{newPosition.X} Y{newPosition.Y} Z{newPosition.Z} E{ePosition}");
                        instruction++;

                        if (instruction % 500 == 0)
                        {
                            writetext.WriteLine($"; LAYER:{layer++}");
                        }
                    }
                }
            }
#endif

            // Set the global culture for the app, current thread and all new threads
            CultureInfo.DefaultThreadCurrentCulture   = CultureInfo.InvariantCulture;
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;
            Thread.CurrentThread.CurrentCulture       = CultureInfo.InvariantCulture;
            Thread.CurrentThread.CurrentUICulture     = CultureInfo.InvariantCulture;

            // make sure we can build a system relevant serial port
            FrostedSerialPortFactory.GetPlatformSerialPort = (serialPortName) =>
            {
                return(new CSharpSerialPortWrapper(serialPortName));
            };

            // Set default Agg providers
            AggContext.Config.ProviderTypes.SystemWindowProvider = "MatterHackers.GlfwProvider.GlfwWindowProvider, MatterHackers.GlfwProvider";
            // for now we will ship release with the old renderer
#if !DEBUG
            AggContext.Config.ProviderTypes.SystemWindowProvider = "MatterHackers.MatterControl.WinformsSingleWindowProvider, MatterControl.Winforms";
#endif

            string userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

            _raygunClient = new RaygunClient("hQIlyUUZRGPyXVXbI6l1dA==")             // this is the PC key
            {
                ApplicationVersion = VersionInfo.Instance.ReleaseVersion
            };

#if !DEBUG
            if (AggContext.OperatingSystem == OSType.Windows)
            {
                waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, "MatterControl#Startup", out bool created);

                if (!created)
                {
                    // If an instance is already running, create a service proxy and execute ShellOpenFile
                    var proxy = new ServiceProxy();

                    // and at least one argument is an acceptable shell file extension
                    var itemsToAdd = args.Where(f => File.Exists(f) && shellFileExtensions.Contains(Path.GetExtension(f).ToLower()));
                    if (itemsToAdd.Any())
                    {
                        // notify the running instance of the event
                        proxy.ShellOpenFile(itemsToAdd.ToArray());
                    }

                    System.Threading.Thread.Sleep(1000);

                    // Finally, close the process spawned by Explorer.exe
                    return;
                }

                var serviceHost = new ServiceHost(typeof(LocalService), new[] { new Uri(ServiceBaseUri) });
                serviceHost.AddServiceEndpoint(typeof(IMainService), new NetNamedPipeBinding(), mainServiceName);
                serviceHost.Open();

                Console.Write(
                    "Service started: {0};",
                    string.Join(", ", serviceHost.Description.Endpoints.Select(s => s.ListenUri.AbsoluteUri).ToArray()));
            }
#endif

            // If MatterControl isn't running and valid files were shelled, schedule a StartupAction to open the files after load
            var shellFiles = args.Where(f => File.Exists(f) && shellFileExtensions.Contains(Path.GetExtension(f).ToLower()));
            if (shellFiles.Any())
            {
                ApplicationController.StartupActions.Add(new ApplicationController.StartupAction()
                {
                    Title    = "Shell Files",
                    Priority = 0,
                    Action   = () =>
                    {
                        // Open each shelled file
                        foreach (string file in shellFiles)
                        {
                            ApplicationController.Instance.ShellOpenFile(file);
                        }
                    }
                });
            }

            // Load optional user configuration
            IConfiguration config = new ConfigurationBuilder()
                                    .AddJsonFile("appsettings.json", optional: true)
                                    .AddJsonFile(Path.Combine(userProfilePath, "MatterControl.json"), optional: true)
                                    .Build();

            // Override defaults via configuration
            config.Bind("Agg:ProviderTypes", AggContext.Config.ProviderTypes);
            config.Bind("Agg:GraphicsMode", AggContext.Config.GraphicsMode);

            Slicer.RunInProcess               = config.GetValue <bool>("MatterControl:Slicer:Debug");
            Application.EnableF5Collect       = config.GetValue <bool>("MatterControl:Application:EnableF5Collect");
            Application.EnableNetworkTraffic  = config.GetValue <bool>("MatterControl:Application:EnableNetworkTraffic", true);
            Application.MiniTouchScreen.Make  = config.GetValue <string>("MatterControl:MiniTouchScreen:Make", "");
            Application.MiniTouchScreen.Model = config.GetValue <string>("MatterControl:MiniTouchScreen:Model", "");

            // Make sure we have the right working directory as we assume everything relative to the executable.
            Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));

            Datastore.Instance.Initialize(DesktopSqlite.CreateInstance());

            if (UserSettings.Instance.get(UserSettingsKey.ApplicationUseHeigResDisplays) == "true")
            {
                SetProcessDpiAwareness((int)DpiAwareness.PerMonitorAware);
            }

            var isExperimental = OemSettings.Instance.WindowTitleExtra == "Experimental";
#if !DEBUG
            // Conditionally spin up error reporting if not on the Stable channel
            string channel = UserSettings.Instance.get(UserSettingsKey.UpdateFeedType);
            if (string.IsNullOrEmpty(channel) ||
                channel != "release" ||
                isExperimental)
#endif
            {
                System.Windows.Forms.Application.ThreadException += (s, e) =>
                {
                    if (raygunNotificationCount++ < RaygunMaxNotifications)
                    {
                        _raygunClient.Send(e.Exception);
                    }

                    if (System.Windows.Forms.Application.OpenForms.Count > 0 &&
                        !System.Windows.Forms.Application.OpenForms[0].InvokeRequired)
                    {
                        System.Windows.Forms.Application.Exit();
                    }
                };

                AppDomain.CurrentDomain.UnhandledException += (s, e) =>
                {
                    if (raygunNotificationCount++ < RaygunMaxNotifications)
                    {
                        _raygunClient.Send(e.ExceptionObject as Exception);
                    }

                    System.Windows.Forms.Application.Exit();
                };
            }

            // Init platformFeaturesProvider before ShowAsSystemWindow
            string platformFeaturesProvider = "MatterHackers.MatterControl.WindowsPlatformsFeatures, MatterControl.Winforms";

            string textSizeMode = UserSettings.Instance.get(UserSettingsKey.ApplicationTextSize);
            if (!string.IsNullOrEmpty(textSizeMode))
            {
                if (double.TryParse(textSizeMode, out double textSize))
                {
                    GuiWidget.DeviceScale = textSize;
                }
            }

            AppContext.Platform = AggContext.CreateInstanceFrom <INativePlatformFeatures>(platformFeaturesProvider);
            AppContext.Platform.InitPluginFinder();
            AppContext.Platform.ProcessCommandline();

            config.Bind("MatterControl", MatterHackers.MatterControl.AppContext.Options);

            // Get startup bounds from MatterControl and construct system window
            // var systemWindow = new DesktopMainWindow(400, 200)
            var(width, height) = RootSystemWindow.GetStartupBounds();

            var systemWindow = Application.LoadRootWindow(width, height);

            var theme = ApplicationController.Instance.Theme;
            SingleWindowProvider.SetWindowTheme(theme.TextColor,
                                                theme.DefaultFontSize - 1,
                                                theme.InvertIcons,
                                                () => theme.CreateSmallResetButton(),
                                                theme.ToolbarPadding,
                                                theme.TabBarBackground,
                                                new Color(theme.PrimaryAccentColor, 175));

            ApplicationController.Instance.KeepAwake = KeepAwake;

            systemWindow.ShowAsSystemWindow();
        }
예제 #4
0
        public static void Main(string[] args)
        {
            // Set the global culture for the app, current thread and all new threads
            CultureInfo.DefaultThreadCurrentCulture   = CultureInfo.InvariantCulture;
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;
            Thread.CurrentThread.CurrentCulture       = CultureInfo.InvariantCulture;
            Thread.CurrentThread.CurrentUICulture     = CultureInfo.InvariantCulture;

            // make sure we can build a system relevant serial port
            FrostedSerialPortFactory.GetPlatformSerialPort = (serialPortName) =>
            {
                return(new CSharpSerialPortWrapper(serialPortName));
            };

            // Set default Agg providers
            AggContext.Config.ProviderTypes.SystemWindowProvider = "MatterHackers.MatterControl.WinformsSingleWindowProvider, MatterControl.Winforms";

            string userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

            _raygunClient = new RaygunClient("hQIlyUUZRGPyXVXbI6l1dA==")             // this is the PC key
            {
                ApplicationVersion = VersionInfo.Instance.ReleaseVersion
            };

            if (AggContext.OperatingSystem == OSType.Windows)
            {
                waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, "MatterControl#Startup", out bool created);

                if (!created)
                {
                    // If an instance is already running, create a service proxy and execute ShellOpenFile
                    var proxy = new ServiceProxy();

                    // and at least one argument is an acceptable shell file extension
                    var itemsToAdd = args.Where(f => File.Exists(f) && shellFileExtensions.Contains(Path.GetExtension(f).ToLower()));
                    if (itemsToAdd.Any())
                    {
                        // notify the running instance of the event
                        proxy.ShellOpenFile(itemsToAdd.ToArray());
                    }

                    System.Threading.Thread.Sleep(1000);

                    // Finally, close the process spawned by Explorer.exe
                    return;
                }

                // #endif
                var serviceHost = new ServiceHost(
                    typeof(LocalService),
                    new Uri[] { new Uri("net.pipe://localhost/mattercontrol") });

                serviceHost.AddServiceEndpoint(typeof(IMainService), new NetNamedPipeBinding(), mainServiceName);
                serviceHost.Open();

                Console.Write(
                    "Service started: {0};",
                    string.Join(", ", serviceHost.Description.Endpoints.Select(s => s.ListenUri.AbsoluteUri).ToArray()));
            }

            // Load optional user configuration
            IConfiguration config = new ConfigurationBuilder()
                                    .AddJsonFile("appsettings.json", optional: true)
                                    .AddJsonFile(Path.Combine(userProfilePath, "MatterControl.json"), optional: true)
                                    .Build();

            // Override defaults via configuration
            config.Bind("Agg:ProviderTypes", AggContext.Config.ProviderTypes);
            config.Bind("Agg:GraphicsMode", AggContext.Config.GraphicsMode);

            Slicer.RunInProcess              = config.GetValue <bool>("MatterControl:Slicer:Debug");
            Application.EnableF5Collect      = config.GetValue <bool>("MatterControl:Application:EnableF5Collect");
            Application.EnableNetworkTraffic = config.GetValue <bool>("MatterControl:Application:EnableNetworkTraffic", true);

            // Make sure we have the right working directory as we assume everything relative to the executable.
            Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));

            Datastore.Instance.Initialize(DesktopSqlite.CreateInstance());
#if !DEBUG
            // Conditionally spin up error reporting if not on the Stable channel
            string channel = UserSettings.Instance.get(UserSettingsKey.UpdateFeedType);
            if (string.IsNullOrEmpty(channel) || channel != "release" || OemSettings.Instance.WindowTitleExtra == "Experimental")
#endif
            {
                System.Windows.Forms.Application.ThreadException += (s, e) =>
                {
                    if (raygunNotificationCount++ < RaygunMaxNotifications)
                    {
                        _raygunClient.Send(e.Exception);
                    }

                    if (System.Windows.Forms.Application.OpenForms.Count > 0 &&
                        !System.Windows.Forms.Application.OpenForms[0].InvokeRequired)
                    {
                        System.Windows.Forms.Application.Exit();
                    }
                };

                AppDomain.CurrentDomain.UnhandledException += (s, e) =>
                {
                    if (raygunNotificationCount++ < RaygunMaxNotifications)
                    {
                        _raygunClient.Send(e.ExceptionObject as Exception);
                    }

                    System.Windows.Forms.Application.Exit();
                };
            }

            // Init platformFeaturesProvider before ShowAsSystemWindow
            string platformFeaturesProvider = "MatterHackers.MatterControl.WindowsPlatformsFeatures, MatterControl.Winforms";

            AppContext.Platform = AggContext.CreateInstanceFrom <INativePlatformFeatures>(platformFeaturesProvider);
            AppContext.Platform.InitPluginFinder();
            AppContext.Platform.ProcessCommandline();

            config.Bind("MatterControl", MatterHackers.MatterControl.AppContext.Options);

            // Get startup bounds from MatterControl and construct system window
            // var systemWindow = new DesktopMainWindow(400, 200)
            var(width, height) = RootSystemWindow.GetStartupBounds();

            var systemWindow = Application.LoadRootWindow(width, height);
            systemWindow.ShowAsSystemWindow();
        }
예제 #5
0
        public static SystemWindow LoadRootWindow(int width, int height)
        {
            timer = Stopwatch.StartNew();

            if (false)
            {
                // set the default font
                AggContext.DefaultFont           = ApplicationController.GetTypeFace(NamedTypeFace.Nunito_Regular);
                AggContext.DefaultFontBold       = ApplicationController.GetTypeFace(NamedTypeFace.Nunito_Bold);
                AggContext.DefaultFontItalic     = ApplicationController.GetTypeFace(NamedTypeFace.Nunito_Italic);
                AggContext.DefaultFontBoldItalic = ApplicationController.GetTypeFace(NamedTypeFace.Nunito_Bold_Italic);
            }

            var systemWindow = new RootSystemWindow(width, height);

            var overlay = new GuiWidget()
            {
                BackgroundColor = AppContext.Theme.BackgroundColor,
            };

            overlay.AnchorAll();

            systemWindow.AddChild(overlay);

            var mutedAccentColor = AppContext.Theme.SplashAccentColor;

            var spinner = new LogoSpinner(overlay, rotateX: -0.05)
            {
                MeshColor = mutedAccentColor
            };

            progressPanel = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                Position    = new Vector2(0, height * .25),
                HAnchor     = HAnchor.Center | HAnchor.Fit,
                VAnchor     = VAnchor.Fit,
                MinimumSize = new Vector2(400, 100),
                Margin      = new BorderDouble(0, 0, 0, 200)
            };
            overlay.AddChild(progressPanel);

            progressPanel.AddChild(statusText = new TextWidget("", textColor: AppContext.Theme.TextColor)
            {
                MinimumSize            = new Vector2(200, 30),
                HAnchor                = HAnchor.Center,
                AutoExpandBoundsToText = true
            });

            progressPanel.AddChild(progressBar = new ProgressBar()
            {
                FillColor   = mutedAccentColor,
                BorderColor = Color.Gray,                 // theme.BorderColor75,
                Height      = 11,
                Width       = 230,
                HAnchor     = HAnchor.Center,
                VAnchor     = VAnchor.Absolute
            });

            AppContext.RootSystemWindow = systemWindow;

            // hook up a keyboard watcher to rout keys when not handled by children

            systemWindow.KeyPressed += SystemWindow_KeyPressed;

            systemWindow.KeyDown += (s, keyEvent) =>
            {
                var view3D            = systemWindow.Descendants <View3DWidget>().Where((v) => v.ActuallyVisibleOnScreen()).FirstOrDefault();
                var printerTabPage    = systemWindow.Descendants <PrinterTabPage>().Where((v) => v.ActuallyVisibleOnScreen()).FirstOrDefault();
                var offsetDist        = 50;
                var arrowKeyOperation = keyEvent.Shift ? TrackBallTransformType.Translation : TrackBallTransformType.Rotation;

                var gcode2D = systemWindow.Descendants <GCode2DWidget>().Where((v) => v.ActuallyVisibleOnScreen()).FirstOrDefault();

                if (keyEvent.KeyCode == Keys.F1)
                {
                    ApplicationController.Instance.ActivateHelpTab();
                }

                if (EnableF5Collect &&
                    keyEvent.KeyCode == Keys.F5)
                {
                    GC.Collect();
                    systemWindow.Invalidate();
                }

                if (!keyEvent.Handled &&
                    gcode2D != null)
                {
                    switch (keyEvent.KeyCode)
                    {
                    case Keys.Oemplus:
                    case Keys.Add:
                        if (keyEvent.Control)
                        {
                            // Zoom out
                            gcode2D.Zoom(1.2);
                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.OemMinus:
                    case Keys.Subtract:
                        if (keyEvent.Control)
                        {
                            // Zoom in
                            gcode2D.Zoom(.8);
                            keyEvent.Handled = true;
                        }

                        break;
                    }
                }

                if (!keyEvent.Handled &&
                    view3D != null)
                {
                    switch (keyEvent.KeyCode)
                    {
                    case Keys.C:
                        if (keyEvent.Control)
                        {
                            view3D.Scene.Copy();
                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.P:
                        if (keyEvent.Control)
                        {
                            view3D.PushToPrinterAndPrint();
                        }

                        break;

                    case Keys.X:
                        if (keyEvent.Control)
                        {
                            view3D.Scene.Cut();
                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.Y:
                        if (keyEvent.Control)
                        {
                            view3D.Scene.UndoBuffer.Redo();
                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.A:
                        if (keyEvent.Control)
                        {
                            view3D.SelectAll();
                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.S:
                        if (keyEvent.Control)
                        {
                            view3D.Save();
                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.V:
                        if (keyEvent.Control)
                        {
                            view3D.sceneContext.Paste();
                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.Oemplus:
                    case Keys.Add:
                        if (keyEvent.Control)
                        {
                            // Zoom out
                            Offset3DView(view3D, new Vector2(0, offsetDist), TrackBallTransformType.Scale);
                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.OemMinus:
                    case Keys.Subtract:
                        if (keyEvent.Control)
                        {
                            // Zoom in
                            Offset3DView(view3D, new Vector2(0, -offsetDist), TrackBallTransformType.Scale);
                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.Z:
                        if (keyEvent.Control)
                        {
                            if (keyEvent.Shift)
                            {
                                view3D.Scene.Redo();
                            }
                            else
                            {
                                // undo last operation
                                view3D.Scene.Undo();
                            }

                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.Insert:
                        if (keyEvent.Shift)
                        {
                            view3D.sceneContext.Paste();
                            keyEvent.Handled = true;
                        }

                        break;

                    case Keys.Delete:
                    case Keys.Back:
                        view3D.Scene.DeleteSelection();
                        keyEvent.Handled          = true;
                        keyEvent.SuppressKeyPress = true;
                        break;

                    case Keys.Escape:
                        if (view3D.CurrentSelectInfo.DownOnPart)
                        {
                            view3D.CurrentSelectInfo.DownOnPart = false;

                            view3D.Scene.SelectedItem.Matrix = view3D.TransformOnMouseDown;

                            keyEvent.Handled          = true;
                            keyEvent.SuppressKeyPress = true;
                        }

                        foreach (var interactionVolume in view3D.InteractionLayer.InteractionVolumes)
                        {
                            interactionVolume.CancelOperation();
                        }

                        break;

                    case Keys.Left:
                        if (keyEvent.Control &&
                            printerTabPage != null &&
                            !printerTabPage.sceneContext.ViewState.ModelView)
                        {
                            // Decrement slider
                            printerTabPage.LayerFeaturesIndex -= 1;
                        }
                        else
                        {
                            if (view3D.sceneContext.Scene.SelectedItem is IObject3D object3D)
                            {
                                NudgeItem(view3D, object3D, ArrowDirection.Left, keyEvent);
                            }
                            else
                            {
                                // move or rotate view left
                                Offset3DView(view3D, new Vector2(-offsetDist, 0), arrowKeyOperation);
                            }
                        }

                        keyEvent.Handled          = true;
                        keyEvent.SuppressKeyPress = true;
                        break;

                    case Keys.Right:
                        if (keyEvent.Control &&
                            printerTabPage != null &&
                            !printerTabPage.sceneContext.ViewState.ModelView)
                        {
                            // Increment slider
                            printerTabPage.LayerFeaturesIndex += 1;
                        }
                        else
                        {
                            if (view3D.sceneContext.Scene.SelectedItem is IObject3D object3D)
                            {
                                NudgeItem(view3D, object3D, ArrowDirection.Right, keyEvent);
                            }
                            else
                            {
                                // move or rotate view right
                                Offset3DView(view3D, new Vector2(offsetDist, 0), arrowKeyOperation);
                            }
                        }

                        keyEvent.Handled          = true;
                        keyEvent.SuppressKeyPress = true;
                        break;

                    case Keys.Up:
                        if (view3D.Printer != null &&
                            printerTabPage != null &&
                            view3D.Printer.ViewState.ViewMode != PartViewMode.Model)
                        {
                            printerTabPage.LayerScrollbar.Value += 1;
                        }
                        else
                        {
                            if (view3D.sceneContext.Scene.SelectedItem is IObject3D object3D)
                            {
                                NudgeItem(view3D, object3D, ArrowDirection.Up, keyEvent);
                            }
                            else
                            {
                                Offset3DView(view3D, new Vector2(0, offsetDist), arrowKeyOperation);
                            }
                        }

                        keyEvent.Handled          = true;
                        keyEvent.SuppressKeyPress = true;
                        break;

                    case Keys.Down:
                        if (view3D.Printer != null &&
                            printerTabPage != null &&
                            view3D.Printer.ViewState.ViewMode != PartViewMode.Model)
                        {
                            printerTabPage.LayerScrollbar.Value -= 1;
                        }
                        else
                        {
                            if (view3D.sceneContext.Scene.SelectedItem is IObject3D object3D)
                            {
                                NudgeItem(view3D, object3D, ArrowDirection.Down, keyEvent);
                            }
                            else
                            {
                                Offset3DView(view3D, new Vector2(0, -offsetDist), arrowKeyOperation);
                            }
                        }

                        keyEvent.Handled          = true;
                        keyEvent.SuppressKeyPress = true;
                        break;
                    }
                }
            };

            // Hook SystemWindow load and spin up MatterControl once we've hit first draw
            systemWindow.Load += (s, e) =>
            {
                // Show the End User License Agreement if it has not been shown (on windows it is shown in the installer)
                if (AggContext.OperatingSystem != OSType.Windows &&
                    UserSettings.Instance.get(UserSettingsKey.SoftwareLicenseAccepted) != "true")
                {
                    var eula = new LicenseAgreementPage(LoadMC)
                    {
                        Margin = new BorderDouble(5)
                    };

                    systemWindow.AddChild(eula);
                }
                else
                {
                    LoadMC();
                }
            };

            void LoadMC()
            {
                ReportStartupProgress(0.02, "First draw->RunOnIdle");

                // UiThread.RunOnIdle(() =>
                Task.Run(async() =>
                {
                    try
                    {
                        ReportStartupProgress(0.15, "MatterControlApplication.Initialize");

                        ApplicationController.LoadTranslationMap();

                        var mainView = await Initialize(systemWindow, (progress0To1, status) =>
                        {
                            ReportStartupProgress(0.2 + progress0To1 * 0.7, status);
                        });

                        ReportStartupProgress(0.9, "AddChild->MainView");
                        systemWindow.AddChild(mainView, 0);

                        ReportStartupProgress(1, "");
                        systemWindow.BackgroundColor = Color.Transparent;
                        overlay.Close();
                    }
                    catch (Exception ex)
                    {
                        UiThread.RunOnIdle(() =>
                        {
                            statusText.Visible = false;

                            var errorTextColor = Color.White;

                            progressPanel.Margin          = 0;
                            progressPanel.VAnchor         = VAnchor.Center | VAnchor.Fit;
                            progressPanel.BackgroundColor = Color.DarkGray;
                            progressPanel.Padding         = 20;
                            progressPanel.Border          = 1;
                            progressPanel.BorderColor     = Color.Red;

                            var theme = new ThemeConfig();

                            progressPanel.AddChild(
                                new TextWidget("Startup Failure".Localize() + ":", pointSize: theme.DefaultFontSize, textColor: errorTextColor));

                            progressPanel.AddChild(
                                new TextWidget(ex.Message, pointSize: theme.FontSize9, textColor: errorTextColor));

                            var closeButton = new TextButton("Close", theme)
                            {
                                BackgroundColor = theme.SlightShade,
                                HAnchor         = HAnchor.Right,
                                VAnchor         = VAnchor.Absolute
                            };
                            closeButton.Click += (s1, e1) =>
                            {
                                systemWindow.Close();
                            };

                            spinner.SpinLogo    = false;
                            progressBar.Visible = false;

                            progressPanel.AddChild(closeButton);
                        });
                    }

                    AppContext.IsLoading = false;
                });
            }

            ReportStartupProgress(0, "ShowAsSystemWindow");

            return(systemWindow);
        }