private void Printer_SettingChanged(object s, EventArgs e)
        {
            string settingsName = (e as StringEventArgs)?.Data;

            if (settingsName != null && settingsName == SettingsKey.printer_name)
            {
                // Allow enough time for ProfileManager to respond and refresh its data
                UiThread.RunOnIdle(() =>
                {
                    HardwareTreeView.CreatePrinterProfilesTree(printersNode, theme);
                }, .2);

                this.Invalidate();
            }
        }
        public HardwareTreeView(ThemeConfig theme)
            : base(theme)
        {
            rootColumn = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit
            };
            this.AddChild(rootColumn);

            // Printers
            printersNode = new TreeNode(theme)
            {
                Text             = "Printers".Localize(),
                HAnchor          = HAnchor.Stretch,
                AlwaysExpandable = true,
                Image            = AggContext.StaticData.LoadIcon("printer.png", 16, 16, theme.InvertIcons)
            };
            printersNode.TreeView = this;

            var forcedHeight = 20;
            var mainRow      = printersNode.Children.FirstOrDefault();

            mainRow.HAnchor = HAnchor.Stretch;
            mainRow.AddChild(new HorizontalSpacer());

            // add in the create printer button
            var createPrinter = new IconButton(AggContext.StaticData.LoadIcon("md-add-circle_18.png", 18, 18, theme.InvertIcons), theme)
            {
                Name        = "Create Printer",
                VAnchor     = VAnchor.Center,
                Margin      = theme.ButtonSpacing.Clone(left: theme.ButtonSpacing.Right),
                ToolTipText = "Create Printer".Localize(),
                Height      = forcedHeight,
                Width       = forcedHeight
            };

            createPrinter.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                if (ApplicationController.Instance.AnyPrintTaskRunning)
                {
                    StyledMessageBox.ShowMessageBox("Please wait until the print has finished and try again.".Localize(), "Can't add printers while printing".Localize());
                }
                else
                {
                    DialogWindow.Show(PrinterSetup.GetBestStartPage(PrinterSetup.StartPageOptions.ShowMakeModel));
                }
            });
            mainRow.AddChild(createPrinter);

            // add in the import printer button
            var importPrinter = new IconButton(AggContext.StaticData.LoadIcon("md-import_18.png", 18, 18, theme.InvertIcons), theme)
            {
                VAnchor     = VAnchor.Center,
                Margin      = theme.ButtonSpacing,
                ToolTipText = "Import Printer".Localize(),
                Height      = forcedHeight,
                Width       = forcedHeight
            };

            importPrinter.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                AggContext.FileDialogs.OpenFileDialog(
                    new OpenFileDialogParams(
                        "settings files|*.ini;*.printer;*.slice"),
                    (result) =>
                {
                    if (!string.IsNullOrEmpty(result.FileName) &&
                        File.Exists(result.FileName))
                    {
                        //simpleTabs.RemoveTab(simpleTabs.ActiveTab);
                        if (ProfileManager.ImportFromExisting(result.FileName))
                        {
                            string importPrinterSuccessMessage = "You have successfully imported a new printer profile. You can find '{0}' in your list of available printers.".Localize();
                            DialogWindow.Show(
                                new ImportSucceeded(
                                    importPrinterSuccessMessage.FormatWith(Path.GetFileNameWithoutExtension(result.FileName))));
                        }
                        else
                        {
                            StyledMessageBox.ShowMessageBox("Oops! Settings file '{0}' did not contain any settings we could import.".Localize().FormatWith(Path.GetFileName(result.FileName)), "Unable to Import".Localize());
                        }
                    }
                });
            });
            mainRow.AddChild(importPrinter);

            rootColumn.AddChild(printersNode);

            HardwareTreeView.CreatePrinterProfilesTree(printersNode, theme);
            this.Invalidate();

            // Filament
            var materialsNode = new TreeNode(theme)
            {
                Text             = "Materials".Localize(),
                AlwaysExpandable = true,
                Image            = AggContext.StaticData.LoadIcon("filament.png", 16, 16, theme.InvertIcons)
            };

            materialsNode.TreeView = this;

            rootColumn.AddChild(materialsNode);

            // Register listeners
            PrinterSettings.AnyPrinterSettingChanged += Printer_SettingChanged;

            // Rebuild the treeview anytime the Profiles list changes
            ProfileManager.ProfilesListChanged.RegisterEvent((s, e) =>
            {
                HardwareTreeView.CreatePrinterProfilesTree(printersNode, theme);
                this.Invalidate();
            }, ref unregisterEvents);
        }
        public HardwareTreeView(ThemeConfig theme)
            : base(theme)
        {
            rootColumn = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit
            };
            this.AddChild(rootColumn);

            // Printers
            printersNode = new TreeNode(theme)
            {
                Text             = "Printers".Localize(),
                HAnchor          = HAnchor.Stretch,
                AlwaysExpandable = true,
                Image            = StaticData.Instance.LoadIcon("printer.png", 16, 16, theme.InvertIcons)
            };
            printersNode.TreeView = this;

            var forcedHeight = 20 * GuiWidget.DeviceScale;
            var mainRow      = printersNode.Children.FirstOrDefault();

            mainRow.HAnchor = HAnchor.Stretch;
            mainRow.AddChild(new HorizontalSpacer());

            // add in the create printer button
            var createPrinter = new IconButton(StaticData.Instance.LoadIcon("md-add-circle_18.png", 18, 18, theme.InvertIcons), theme)
            {
                Name        = "Create Printer",
                VAnchor     = VAnchor.Center,
                Margin      = theme.ButtonSpacing.Clone(left: theme.ButtonSpacing.Right),
                ToolTipText = "Create Printer".Localize(),
                Height      = forcedHeight,
                Width       = forcedHeight
            };

            createPrinter.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                DialogWindow.Show(PrinterSetup.GetBestStartPage(PrinterSetup.StartPageOptions.ShowMakeModel));
            });
            mainRow.AddChild(createPrinter);

            // add in the import printer button
            var importPrinter = new IconButton(StaticData.Instance.LoadIcon("md-import_18.png", 18, 18, theme.InvertIcons), theme)
            {
                VAnchor     = VAnchor.Center,
                Margin      = theme.ButtonSpacing,
                ToolTipText = "Import Printer".Localize(),
                Height      = forcedHeight,
                Width       = forcedHeight,
                Name        = "Import Printer Button"
            };

            importPrinter.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                DialogWindow.Show(new CloneSettingsPage());
            });
            mainRow.AddChild(importPrinter);

            rootColumn.AddChild(printersNode);

            HardwareTreeView.CreatePrinterProfilesTree(printersNode, theme);
            this.Invalidate();

            // Filament
            var materialsNode = new TreeNode(theme)
            {
                Text             = "Materials".Localize(),
                AlwaysExpandable = true,
                Image            = StaticData.Instance.LoadIcon("filament.png", 16, 16, theme.InvertIcons)
            };

            materialsNode.TreeView = this;

            rootColumn.AddChild(materialsNode);

            // Register listeners
            PrinterSettings.AnyPrinterSettingChanged += Printer_SettingChanged;

            // Rebuild the treeview anytime the Profiles list changes
            ProfileManager.ProfilesListChanged.RegisterEvent((s, e) =>
            {
                HardwareTreeView.CreatePrinterProfilesTree(printersNode, theme);
                this.Invalidate();
            }, ref unregisterEvents);
        }
        public HardwareTabPage(ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.theme   = theme;
            this.Padding = 0;
            this.HAnchor = HAnchor.Stretch;
            this.VAnchor = VAnchor.Stretch;

            var toolbar = new Toolbar(theme.TabbarPadding, theme.CreateSmallResetButton())
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit,
                Padding = theme.ToolbarPadding
            };

            theme.ApplyBottomBorder(toolbar);

            toolbar.AddChild(new TextButton("Inventory".Localize(), theme)
            {
                Padding     = new BorderDouble(6, 0),
                MinimumSize = new Vector2(0, theme.ButtonHeight),
                Selectable  = false
            });

            this.AddChild(toolbar);

            var horizontalSplitter = new Splitter()
            {
                SplitterDistance   = UserSettings.Instance.LibraryViewWidth,
                SplitterSize       = theme.SplitterWidth,
                SplitterBackground = theme.SplitterBackground,
                HAnchor            = HAnchor.Stretch,
                VAnchor            = VAnchor.Stretch,
            };

            horizontalSplitter.DistanceChanged += (s, e) =>
            {
                UserSettings.Instance.LibraryViewWidth = horizontalSplitter.SplitterDistance;
            };

            this.AddChild(horizontalSplitter);

            var treeView = new HardwareTreeView(theme)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Stretch,
                Width   = 300,
                Margin  = 5
            };

            treeView.NodeMouseDoubleClick += (s, e) =>
            {
                if (e is MouseEventArgs mouseEvent &&
                    s is GuiWidget clickedWidget &&
                    mouseEvent.Button == MouseButtons.Left &&
                    mouseEvent.Clicks == 2)
                {
                    if (treeView?.SelectedNode.Tag is PrinterInfo printerInfo)
                    {
                        ApplicationController.Instance.OpenPrinter(printerInfo);
                    }
                }
            };

            treeView.NodeMouseClick += (s, e) =>
            {
                if (e is MouseEventArgs mouseEvent &&
                    s is GuiWidget clickedWidget &&
                    mouseEvent.Button == MouseButtons.Right)
                {
                    UiThread.RunOnIdle(() =>
                    {
                        var popupMenu = new PopupMenu(ApplicationController.Instance.MenuTheme);

                        var openMenuItem    = popupMenu.CreateMenuItem("Open".Localize());
                        openMenuItem.Click += (s2, e2) =>
                        {
                            if (treeView?.SelectedNode.Tag is PrinterInfo printerInfo)
                            {
                                ApplicationController.Instance.OpenPrinter(printerInfo);
                            }
                        };

                        popupMenu.CreateSeparator();

                        var deleteMenuItem    = popupMenu.CreateMenuItem("Delete".Localize());
                        deleteMenuItem.Click += (s2, e2) =>
                        {
                            if (treeView.SelectedNode.Tag is PrinterInfo printerInfo)
                            {
                                // Delete printer
                                StyledMessageBox.ShowMessageBox(
                                    (deletePrinter) =>
                                {
                                    if (deletePrinter)
                                    {
                                        ProfileManager.Instance.DeletePrinter(printerInfo.ID);
                                    }
                                },
                                    "Are you sure you want to delete printer '{0}'?".Localize().FormatWith(printerInfo.Name),
                                    "Delete Printer?".Localize(),
                                    StyledMessageBox.MessageType.YES_NO,
                                    "Delete Printer".Localize());
                            }
                        };

                        popupMenu.ShowMenu(clickedWidget, mouseEvent);
                    });
                }
            };

            treeView.ScrollArea.HAnchor = HAnchor.Stretch;

            treeView.AfterSelect += (s, e) =>
            {
                if (treeView.SelectedNode.Tag is PrinterInfo printerInfo)
                {
                    horizontalSplitter.Panel2.CloseChildren();
                    horizontalSplitter.Panel2.AddChild(new PrinterDetails(printerInfo, theme, true)
                    {
                        HAnchor = HAnchor.MaxFitOrStretch,
                        VAnchor = VAnchor.Stretch,
                        Padding = theme.DefaultContainerPadding
                    });
                }
            };
            horizontalSplitter.Panel1.AddChild(treeView);

            horizontalSplitter.Panel2.AddChild(new GuiWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Stretch,
            });
        }
        public HardwareTabPage(ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.theme   = theme;
            this.Padding = 0;
            this.HAnchor = HAnchor.Stretch;
            this.VAnchor = VAnchor.Stretch;

            var toolbar = new Toolbar(theme)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit,
                Padding = theme.ToolbarPadding
            };

            theme.ApplyBottomBorder(toolbar);

            toolbar.AddChild(new TextButton("Inventory".Localize(), theme)
            {
                Padding     = new BorderDouble(6, 0),
                MinimumSize = new Vector2(0, theme.ButtonHeight),
                Selectable  = false
            });

            this.AddChild(toolbar);

            var horizontalSplitter = new Splitter()
            {
                SplitterDistance   = UserSettings.Instance.LibraryViewWidth,
                SplitterSize       = theme.SplitterWidth,
                SplitterBackground = theme.SplitterBackground,
                HAnchor            = HAnchor.Stretch,
                VAnchor            = VAnchor.Stretch,
            };

            horizontalSplitter.DistanceChanged += (s, e) =>
            {
                UserSettings.Instance.LibraryViewWidth = horizontalSplitter.SplitterDistance;
            };

            this.AddChild(horizontalSplitter);

            var treeView = new HardwareTreeView(theme)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Stretch,
                Width   = 300,
                Margin  = 5
            };

            treeView.NodeMouseDoubleClick += (s, e) =>
            {
                if (e is MouseEventArgs mouseEvent &&
                    s is GuiWidget clickedWidget &&
                    mouseEvent.Button == MouseButtons.Left &&
                    mouseEvent.Clicks == 2)
                {
                    if (treeView?.SelectedNode.Tag is PrinterInfo printerInfo)
                    {
                        if (ApplicationController.Instance.ActivePrinters.FirstOrDefault(p => p.Settings.ID == printerInfo.ID) is PrinterConfig printer &&
                            ApplicationController.Instance.MainView.TabControl.AllTabs.FirstOrDefault(t => t.TabContent is PrinterTabPage printerTabPage && printerTabPage.printer == printer) is ITab tab)
                        {
                            // Switch to existing printer tab
                            ApplicationController.Instance.MainView.TabControl.ActiveTab = tab;
                        }
                        else
                        {
                            // Open new printer tab
                            ApplicationController.Instance.OpenPrinter(printerInfo.ID).ConfigureAwait(false);
                        }
                    }
                }
            };

            treeView.NodeMouseClick += (s, e) =>
            {
                if (e is MouseEventArgs mouseEvent &&
                    s is GuiWidget clickedWidget &&
                    mouseEvent.Button == MouseButtons.Right)
                {
                    UiThread.RunOnIdle(() =>
                    {
                        var menu = new PopupMenu(ApplicationController.Instance.MenuTheme);

                        var openMenuItem    = menu.CreateMenuItem("Open".Localize());
                        openMenuItem.Click += (s2, e2) =>
                        {
                            if (treeView?.SelectedNode.Tag is PrinterInfo printerInfo)
                            {
                                // Open printer
                                ApplicationController.Instance.OpenPrinter(printerInfo.ID).ConfigureAwait(false);
                            }
                        };

                        menu.CreateSeparator();

                        var deleteMenuItem    = menu.CreateMenuItem("Delete".Localize());
                        deleteMenuItem.Click += (s2, e2) =>
                        {
                            // Delete printer
                            StyledMessageBox.ShowMessageBox(
                                (deletePrinter) =>
                            {
                                if (deletePrinter)
                                {
                                    if (treeView.SelectedNode.Tag is PrinterInfo printerInfo)
                                    {
                                        ProfileManager.Instance.DeletePrinter(printerInfo.ID);
                                    }
                                }
                            },
                                "Are you sure you want to delete your currently selected printer?".Localize(),
                                "Delete Printer?".Localize(),
                                StyledMessageBox.MessageType.YES_NO,
                                "Delete Printer".Localize());
                        };


                        var systemWindow = this.Parents <SystemWindow>().FirstOrDefault();
                        systemWindow.ShowPopup(
                            new MatePoint(clickedWidget)
                        {
                            Mate    = new MateOptions(MateEdge.Left, MateEdge.Top),
                            AltMate = new MateOptions(MateEdge.Left, MateEdge.Top)
                        },
                            new MatePoint(menu)
                        {
                            Mate    = new MateOptions(MateEdge.Left, MateEdge.Top),
                            AltMate = new MateOptions(MateEdge.Right, MateEdge.Top)
                        },
                            altBounds: new RectangleDouble(mouseEvent.X + 1, mouseEvent.Y + 1, mouseEvent.X + 1, mouseEvent.Y + 1));
                    });
                }
            };

            treeView.ScrollArea.HAnchor = HAnchor.Stretch;

            treeView.AfterSelect += async(s, e) =>
            {
                if (treeView.SelectedNode.Tag is PrinterInfo printerInfo)
                {
                    horizontalSplitter.Panel2.CloseAllChildren();
                    horizontalSplitter.Panel2.AddChild(new PrinterDetails(printerInfo, theme)
                    {
                        HAnchor = HAnchor.MaxFitOrStretch,
                        VAnchor = VAnchor.Stretch,
                        Padding = theme.DefaultContainerPadding
                    });
                }
            };
            horizontalSplitter.Panel1.AddChild(treeView);

            horizontalSplitter.Panel2.AddChild(new GuiWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Stretch,
            });
        }