public void FindAndInstantiatePlugins(SystemWindow systemWindow) { foreach (MatterControlPlugin plugin in PluginFinder.CreateInstancesOf <MatterControlPlugin>()) { plugin.Initialize(systemWindow); } }
public static FrostedSerialPortFactory GetAppropriateFactory(string driverType) { lock (availableFactories) { try { if (availableFactories.Count == 0) { // always add a serial port this is a raw port availableFactories.Add("Raw", new FrostedSerialPortFactory()); // add in any plugins that we find with other factories. var portFactories = PluginFinder.CreateInstancesOf <FrostedSerialPortFactory>(); foreach (FrostedSerialPortFactory plugin in portFactories) { availableFactories.Add(plugin.GetDriverType(), plugin); } // If we did not find a RepRap driver add the default. if (!availableFactories.ContainsKey("RepRap")) { availableFactories.Add("RepRap", new FrostedSerialPortFactory()); } } if (!string.IsNullOrEmpty(driverType) && availableFactories.ContainsKey(driverType)) { return(availableFactories[driverType]); } return(availableFactories["RepRap"]); } catch { return(new FrostedSerialPortFactory()); } } }
public void FindAndInstantiatePlugins(SystemWindow systemWindow) { string oemName = ApplicationSettings.Instance.GetOEMName(); foreach (MatterControlPlugin plugin in PluginFinder.CreateInstancesOf <MatterControlPlugin>()) { string pluginInfo = plugin.GetPluginInfoJSon(); Dictionary <string, string> nameValuePairs = Newtonsoft.Json.JsonConvert.DeserializeObject <Dictionary <string, string> >(pluginInfo); if (nameValuePairs != null && nameValuePairs.ContainsKey("OEM")) { if (nameValuePairs["OEM"] == oemName) { plugin.Initialize(systemWindow); } } else { plugin.Initialize(systemWindow); } } }
public ExportPrintItemPage(IEnumerable <ILibraryItem> libraryItems, bool centerOnBed, PrinterConfig printer) { this.WindowTitle = "Export File".Localize(); this.HeaderText = "Export selection to".Localize() + ":"; this.Name = "Export Item Window"; var commonMargin = new BorderDouble(4, 2); bool isFirstItem = true; // Must be constructed before plugins are initialized var exportButton = theme.CreateDialogButton("Export".Localize()); validationPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) { HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Fit }; // GCode export exportPluginButtons = new Dictionary <RadioButton, IExportPlugin>(); foreach (IExportPlugin plugin in PluginFinder.CreateInstancesOf <IExportPlugin>().OrderBy(p => p.ButtonText)) { plugin.Initialize(printer); // Skip plugins which are invalid for the current printer if (!plugin.Enabled) { if (!string.IsNullOrEmpty(plugin.DisabledReason)) { // add a message to let us know why not enabled var disabledPluginButton = new RadioButton(new RadioImageWidget(plugin.ButtonText, theme.TextColor, plugin.Icon)) { HAnchor = HAnchor.Left, Margin = commonMargin, Cursor = Cursors.Hand, Name = plugin.ButtonText + " Button", Enabled = false }; contentRow.AddChild(disabledPluginButton); contentRow.AddChild(new TextWidget("Disabled: {0}".Localize().FormatWith(plugin.DisabledReason), textColor: theme.PrimaryAccentColor) { Margin = new BorderDouble(left: 80), HAnchor = HAnchor.Left }); } continue; } // Create export button for each plugin var pluginButton = new RadioButton(new RadioImageWidget(plugin.ButtonText, theme.TextColor, plugin.Icon)) { HAnchor = HAnchor.Left, Margin = commonMargin, Cursor = Cursors.Hand, Name = plugin.ButtonText + " Button" }; contentRow.AddChild(pluginButton); if (plugin is GCodeExport) { var gcodeExportButton = pluginButton; gcodeExportButton.CheckedStateChanged += (s, e) => { validationPanel.CloseAllChildren(); if (gcodeExportButton.Checked) { var errors = printer.ValidateSettings(validatePrintBed: false); exportButton.Enabled = !errors.Any(item => item.ErrorLevel == ValidationErrorLevel.Error); validationPanel.AddChild( new ValidationErrorsPanel( errors, AppContext.Theme) { HAnchor = HAnchor.Stretch }); } else { exportButton.Enabled = true; } }; } if (isFirstItem) { pluginButton.Checked = true; isFirstItem = false; } if (plugin is IExportWithOptions pluginWithOptions) { var optionPanel = pluginWithOptions.GetOptionsPanel(); if (optionPanel != null) { optionPanel.HAnchor = HAnchor.Stretch; optionPanel.VAnchor = VAnchor.Fit; contentRow.AddChild(optionPanel); } } exportPluginButtons.Add(pluginButton, plugin); } ContentRow.AddChild(new VerticalSpacer()); contentRow.AddChild(validationPanel); // TODO: make this work on the mac and then delete this if if (AggContext.OperatingSystem == OSType.Windows || AggContext.OperatingSystem == OSType.X11) { showInFolderAfterSave = new CheckBox("Show file in folder after save".Localize(), theme.TextColor, 10) { HAnchor = HAnchor.Left, Cursor = Cursors.Hand }; contentRow.AddChild(showInFolderAfterSave); } exportButton.Name = "Export Button"; exportButton.Click += (s, e) => { IExportPlugin activePlugin = null; // Loop over all plugin buttons, break on the first checked item found foreach (var button in this.exportPluginButtons.Keys) { if (button.Checked) { activePlugin = exportPluginButtons[button]; break; } } // Early exit if no plugin radio button is selected if (activePlugin == null) { return; } DoExport(libraryItems, printer, activePlugin, centerOnBed, showInFolderAfterSave.Checked); this.Parent.CloseOnIdle(); }; this.AddPageAction(exportButton); }
public ExportPrintItemPage(IEnumerable <ILibraryItem> libraryItems, bool centerOnBed, PrinterConfig printer) { this.centerOnBed = centerOnBed; this.WindowTitle = "Export File".Localize(); this.HeaderText = "Export selection to".Localize() + ":"; this.libraryItems = libraryItems; this.Name = "Export Item Window"; var commonMargin = new BorderDouble(4, 2); bool isFirstItem = true; // GCode export exportPluginButtons = new Dictionary <RadioButton, IExportPlugin>(); foreach (IExportPlugin plugin in PluginFinder.CreateInstancesOf <IExportPlugin>().OrderBy(p => p.ButtonText)) { plugin.Initialize(printer); // Skip plugins which are invalid for the current printer if (!plugin.Enabled) { continue; } // Create export button for each plugin var pluginButton = new RadioButton(new RadioImageWidget(plugin.ButtonText, theme.TextColor, plugin.Icon)) { HAnchor = HAnchor.Left, Margin = commonMargin, Cursor = Cursors.Hand, Name = plugin.ButtonText + " Button" }; contentRow.AddChild(pluginButton); if (isFirstItem) { pluginButton.Checked = true; isFirstItem = false; } if (plugin is IExportWithOptions pluginWithOptions) { var optionPanel = pluginWithOptions.GetOptionsPanel(); if (optionPanel != null) { optionPanel.HAnchor = HAnchor.Stretch; optionPanel.VAnchor = VAnchor.Fit; contentRow.AddChild(optionPanel); } } exportPluginButtons.Add(pluginButton, plugin); } contentRow.AddChild(new VerticalSpacer()); // TODO: make this work on the mac and then delete this if if (AggContext.OperatingSystem == OSType.Windows || AggContext.OperatingSystem == OSType.X11) { showInFolderAfterSave = new CheckBox("Show file in folder after save".Localize(), theme.TextColor, 10) { HAnchor = HAnchor.Left, Cursor = Cursors.Hand }; contentRow.AddChild(showInFolderAfterSave); } var exportButton = theme.CreateDialogButton("Export".Localize()); exportButton.Name = "Export Button"; exportButton.Click += (s, e) => { string fileTypeFilter = ""; string targetExtension = ""; IExportPlugin activePlugin = null; // Loop over all plugin buttons, break on the first checked item found foreach (var button in this.exportPluginButtons.Keys) { if (button.Checked) { activePlugin = exportPluginButtons[button]; break; } } // Early exit if no plugin radio button is selected if (activePlugin == null) { return; } fileTypeFilter = activePlugin.ExtensionFilter; targetExtension = activePlugin.FileExtension; this.Parent.CloseOnIdle(); if (activePlugin is FolderExport) { UiThread.RunOnIdle(() => { AggContext.FileDialogs.SelectFolderDialog( new SelectFolderDialogParams("Select Location To Export Files") { ActionButtonLabel = "Export".Localize(), Title = ApplicationController.Instance.ProductName + " - " + "Select A Folder".Localize() }, (openParams) => { ApplicationController.Instance.Tasks.Execute( "Saving".Localize() + "...", async(reporter, cancellationToken) => { string path = openParams.FolderPath; if (!string.IsNullOrEmpty(path)) { await activePlugin.Generate(libraryItems, path, reporter, cancellationToken); } }); }); }); return; } UiThread.RunOnIdle(() => { string title = ApplicationController.Instance.ProductName + " - " + "Export File".Localize(); string workspaceName = "Workspace " + DateTime.Now.ToString("yyyy-MM-dd HH_mm_ss"); AggContext.FileDialogs.SaveFileDialog( new SaveFileDialogParams(fileTypeFilter) { Title = title, ActionButtonLabel = "Export".Localize(), FileName = Path.GetFileNameWithoutExtension(libraryItems.FirstOrDefault()?.Name ?? workspaceName) }, (saveParams) => { string savePath = saveParams.FileName; if (!string.IsNullOrEmpty(savePath)) { ApplicationController.Instance.Tasks.Execute( "Exporting".Localize() + "...", async(reporter, cancellationToken) => { string extension = Path.GetExtension(savePath); if (extension != targetExtension) { savePath += targetExtension; } bool succeeded = false; if (activePlugin != null) { if (activePlugin is GCodeExport gCodeExport) { gCodeExport.CenterOnBed = centerOnBed; } succeeded = await activePlugin.Generate(libraryItems, savePath, reporter, cancellationToken); } if (succeeded) { ShowFileIfRequested(savePath); } else { UiThread.RunOnIdle(() => { StyledMessageBox.ShowMessageBox("Export failed".Localize(), title); }); } }); } }); }); }; this.AddPageAction(exportButton); }
public PrintPopupMenu(PrinterConfig printer, ThemeConfig theme) : base(theme) { this.printer = printer; this.DrawArrow = true; this.BackgroundColor = theme.ToolbarButtonBackground; this.HoverColor = theme.ToolbarButtonHover; this.MouseDownColor = theme.ToolbarButtonDown; this.Name = "PrintPopupMenu"; this.HAnchor = HAnchor.Fit; this.VAnchor = VAnchor.Fit; settingsContext = new SettingsContext(printer, null, NamedSettingsLayers.All); this.PopupHAnchor = HAnchor.Fit; this.PopupVAnchor = VAnchor.Fit; this.MakeScrollable = false; this.DynamicPopupContent = () => { var menuTheme = ApplicationController.Instance.MenuTheme; int tabIndex = 0; allUiFields.Clear(); var printPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) { Padding = theme.DefaultContainerPadding, BackgroundColor = menuTheme.BackgroundColor }; printPanel.AddChild(new TextWidget("Options".Localize(), textColor: menuTheme.TextColor, pointSize: theme.DefaultFontSize) { HAnchor = HAnchor.Left }); var optionsPanel = new IgnoredFlowLayout() { Name = "PrintPopupMenu Panel", HAnchor = HAnchor.Fit | HAnchor.Left, VAnchor = VAnchor.Fit, Padding = 5, MinimumSize = new Vector2(400, 65), }; printPanel.AddChild(optionsPanel); foreach (var key in new[] { SettingsKey.layer_height, SettingsKey.fill_density, SettingsKey.create_raft }) { var settingsData = PrinterSettings.SettingsData[key]; var row = SliceSettingsTabView.CreateItemRow(settingsData, settingsContext, printer, menuTheme, ref tabIndex, allUiFields); if (row is SliceSettingsRow settingsRow) { settingsRow.ArrowDirection = ArrowDirection.Left; } optionsPanel.AddChild(row); } var subPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) { Margin = new BorderDouble(2, 0) }; bool anySettingOverridden = false; anySettingOverridden |= printer.Settings.GetValue <bool>(SettingsKey.spiral_vase); anySettingOverridden |= !string.IsNullOrWhiteSpace(printer.Settings.GetValue(SettingsKey.layer_to_pause)); var sectionWidget = new SectionWidget("Advanced".Localize(), subPanel, menuTheme, expanded: anySettingOverridden) { Name = "Advanced Section", HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Fit, Margin = 0 }; printPanel.AddChild(sectionWidget); foreach (var key in new[] { SettingsKey.spiral_vase, SettingsKey.layer_to_pause }) { var advancedRow = SliceSettingsTabView.CreateItemRow( PrinterSettings.SettingsData[key], settingsContext, printer, menuTheme, ref tabIndex, allUiFields); if (advancedRow is SliceSettingsRow settingsRow) { settingsRow.ArrowDirection = ArrowDirection.Left; } subPanel.AddChild(advancedRow); } menuTheme.ApplyBoxStyle(sectionWidget); sectionWidget.Margin = new BorderDouble(0, 10); sectionWidget.ContentPanel.Children <SettingsRow>().First().Border = new BorderDouble(0, 1); sectionWidget.ContentPanel.Children <SettingsRow>().Last().Border = 0; var printerReadyToTakeCommands = printer.Connection.CommunicationState == PrinterCommunication.CommunicationStates.FinishedPrint || printer.Connection.CommunicationState == PrinterCommunication.CommunicationStates.Connected; // add the start print button var setupRow = new FlowLayoutWidget() { HAnchor = HAnchor.Stretch }; // Perform validation before popup var errors = printer.Validate(); // Enable print option when no validation Errors exists var printEnabled = !errors.Any(err => err.ErrorLevel == ValidationErrorLevel.Error); var startPrintButton = new TextButton("Start Print".Localize(), menuTheme) { Name = "Start Print Button", Enabled = printEnabled }; startPrintButton.Click += (s, e) => { // Exit if the bed is not GCode and the bed has no printable items if (!printer.Bed.EditContext.IsGGCodeSource && !printer.PrintableItems(printer.Bed.Scene).Any()) { return; } UiThread.RunOnIdle(async() => { // Save any pending changes before starting print operation await ApplicationController.Instance.Tasks.Execute("Saving Changes".Localize(), printer, printer.Bed.SaveChanges); await ApplicationController.Instance.PrintPart( printer.Bed.EditContext, printer, null, CancellationToken.None); }); this.CloseMenu(); }; var hasErrors = errors.Any(e => e.ErrorLevel == ValidationErrorLevel.Error); var hasWarnings = errors.Any(e => e.ErrorLevel == ValidationErrorLevel.Warning && UserSettings.Instance.get($"Ignore_{e.ID}") != "true"); var hasErrorsOrWarnings = hasErrors || hasWarnings; if (hasErrorsOrWarnings) { string label = hasErrors ? "Action Required".Localize() : "Action Recommended".Localize(); setupRow.AddChild(new TextWidget(label, textColor: hasErrors ? Color.Red : theme.PrimaryAccentColor, pointSize: theme.DefaultFontSize) { VAnchor = VAnchor.Bottom, AutoExpandBoundsToText = true, }); } setupRow.AddChild(new HorizontalSpacer()); // Export button {{ bool isSailfish = printer.Settings.GetValue <bool>("enable_sailfish_communication"); var exportPlugins = PluginFinder.CreateInstancesOf <IExportPlugin>(); var targetPluginType = isSailfish ? typeof(X3GExport) : typeof(GCodeExport); // Find the first export plugin with the target type if (exportPlugins.FirstOrDefault(p => p.GetType() == targetPluginType) is IExportPlugin exportPlugin) { string exportType = isSailfish ? "Export X3G".Localize() : "Export G-Code".Localize(); exportPlugin.Initialize(printer); var exportGCodeButton = menuTheme.CreateDialogButton("Export".Localize()); exportGCodeButton.Name = "Export Gcode Button"; exportGCodeButton.Enabled = exportPlugin.Enabled; exportGCodeButton.ToolTipText = exportPlugin.Enabled ? exportType : exportPlugin.DisabledReason; exportGCodeButton.Click += (s, e) => { ExportPrintItemPage.DoExport( new[] { new InMemoryLibraryItem(printer.Bed.Scene) }, printer, exportPlugin); }; setupRow.AddChild(exportGCodeButton); } // Export button }} setupRow.AddChild(startPrintButton); printPanel.AddChild(setupRow); if (printEnabled) { theme.ApplyPrimaryActionStyle(startPrintButton); } else { startPrintButton.BackgroundColor = theme.MinimalShade; } if (hasErrorsOrWarnings) { var errorsPanel = new ValidationErrorsPanel(errors, menuTheme); // Conditional layout for right or bottom errors panel alignment var layoutStyle = FlowDirection.TopToBottom; if (layoutStyle == FlowDirection.LeftToRight) { errorsPanel.HAnchor = HAnchor.Absolute; errorsPanel.VAnchor = VAnchor.Fit | VAnchor.Top; errorsPanel.BackgroundColor = theme.ResolveColor(menuTheme.BackgroundColor, theme.PrimaryAccentColor.WithAlpha(30)); errorsPanel.Width = 350; errorsPanel.Load += (s, e) => { errorsPanel.Parent.BackgroundColor = Color.Transparent; }; } else { errorsPanel.HAnchor = HAnchor.Stretch; errorsPanel.VAnchor = VAnchor.Fit; errorsPanel.Margin = 3; } // Instead of the typical case where the print panel is returned, wrap and append validation errors panel var errorsContainer = new FlowLayoutWidget(layoutStyle) { HAnchor = HAnchor.Fit, VAnchor = VAnchor.Fit, BackgroundColor = layoutStyle == FlowDirection.TopToBottom ? printPanel.BackgroundColor : Color.Transparent }; // Clear bottom padding printPanel.Padding = printPanel.Padding.Clone(bottom: 2); errorsContainer.AddChild(printPanel); errorsContainer.AddChild(errorsPanel); return(errorsContainer); } return(printPanel); }; this.AddChild(new TextButton("Print".Localize(), theme) { Selectable = false, Padding = theme.TextButtonPadding.Clone(right: 5) }); // Register listeners printer.Settings.SettingChanged += Printer_SettingChanged; }
public ExportSlaPopupMenu(PrinterConfig printer, ThemeConfig theme) : base(theme) { this.printer = printer; this.DrawArrow = true; this.BackgroundColor = theme.ToolbarButtonBackground; this.HoverColor = theme.ToolbarButtonHover; this.MouseDownColor = theme.ToolbarButtonDown; this.Name = "ExportSlaPopupMenu"; this.HAnchor = HAnchor.Fit; this.VAnchor = VAnchor.Fit; settingsContext = new SettingsContext(printer, null, NamedSettingsLayers.All); this.PopupHAnchor = HAnchor.Fit; this.PopupVAnchor = VAnchor.Fit; this.MakeScrollable = false; this.DynamicPopupContent = () => { var menuTheme = ApplicationController.Instance.MenuTheme; int tabIndex = 0; allUiFields.Clear(); var exportPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) { Padding = theme.DefaultContainerPadding, BackgroundColor = menuTheme.BackgroundColor }; exportPanel.AddChild(new TextWidget("Options".Localize(), textColor: menuTheme.TextColor, pointSize: theme.DefaultFontSize) { HAnchor = HAnchor.Left }); var optionsPanel = new IgnoredFlowLayout() { Name = "ExportSlaPopupMenu Panel", HAnchor = HAnchor.Fit | HAnchor.Left, VAnchor = VAnchor.Fit, Padding = 5, MinimumSize = new Vector2(400 * GuiWidget.DeviceScale, 65 * GuiWidget.DeviceScale), }; exportPanel.AddChild(optionsPanel); var settingsToAdd = new[] { SettingsKey.sla_layer_height, SettingsKey.sla_create_raft, SettingsKey.sla_auto_support }; foreach (var key in settingsToAdd) { var settingsData = PrinterSettings.SettingsData[key]; var row = SliceSettingsTabView.CreateItemRow(settingsData, settingsContext, printer, menuTheme, ref tabIndex, allUiFields); if (row is SliceSettingsRow settingsRow) { settingsRow.ArrowDirection = ArrowDirection.Left; } optionsPanel.AddChild(row); } // add the export print button var setupRow = new FlowLayoutWidget() { HAnchor = HAnchor.Stretch }; // Perform validation before popup var errors = printer.Validate(); var hasErrors = errors.Any(e => e.ErrorLevel == ValidationErrorLevel.Error); var hasWarnings = errors.Any(e => e.ErrorLevel == ValidationErrorLevel.Warning && UserSettings.Instance.get($"Ignore_{e.ID}") != "true"); var hasErrorsOrWarnings = hasErrors || hasWarnings; if (hasErrorsOrWarnings) { string label = hasErrors ? "Action Required".Localize() : "Action Recommended".Localize(); setupRow.AddChild(new TextWidget(label, textColor: hasErrors ? Color.Red : theme.PrimaryAccentColor, pointSize: theme.DefaultFontSize) { VAnchor = VAnchor.Bottom, AutoExpandBoundsToText = true, }); } setupRow.AddChild(new HorizontalSpacer()); // Export button {{ var exportPlugins = PluginFinder.CreateInstancesOf <IExportPlugin>(); // set target as SLA export var targetPluginType = typeof(GCodeExport); // Find the first export plugin with the target type if (exportPlugins.FirstOrDefault(p => p.GetType() == targetPluginType) is IExportPlugin exportPlugin) { string exportType = "Export Photon File".Localize(); exportPlugin.Initialize(printer); var exportButton = menuTheme.CreateDialogButton("Export".Localize()); theme.ApplyPrimaryActionStyle(exportButton); exportButton.Name = "Export SLA Button"; exportButton.Enabled = exportPlugin.Enabled; exportButton.ToolTipText = exportPlugin.Enabled ? exportType : exportPlugin.DisabledReason; exportButton.Click += (s, e) => { this.CloseMenu(); ExportPrintItemPage.DoExport( new[] { new InMemoryLibraryItem(printer.Bed.Scene) }, printer, exportPlugin); }; setupRow.AddChild(exportButton); } // Export button exportPanel.AddChild(setupRow); if (hasErrorsOrWarnings) { var errorsPanel = new ValidationErrorsPanel(errors, menuTheme); // Conditional layout for right or bottom errors panel alignment var layoutStyle = FlowDirection.TopToBottom; if (layoutStyle == FlowDirection.LeftToRight) { errorsPanel.HAnchor = HAnchor.Absolute; errorsPanel.VAnchor = VAnchor.Fit | VAnchor.Top; errorsPanel.BackgroundColor = theme.ResolveColor(menuTheme.BackgroundColor, theme.PrimaryAccentColor.WithAlpha(30)); errorsPanel.Width = 350; errorsPanel.Load += (s, e) => { errorsPanel.Parent.BackgroundColor = Color.Transparent; }; } else { errorsPanel.HAnchor = HAnchor.Stretch; errorsPanel.VAnchor = VAnchor.Fit; errorsPanel.Margin = 3; } // Instead of the typical case where the print panel is returned, wrap and append validation errors panel var errorsContainer = new FlowLayoutWidget(layoutStyle) { HAnchor = HAnchor.Fit, VAnchor = VAnchor.Fit, BackgroundColor = layoutStyle == FlowDirection.TopToBottom ? exportPanel.BackgroundColor : Color.Transparent }; // Clear bottom padding exportPanel.Padding = exportPanel.Padding.Clone(bottom: 2); errorsContainer.AddChild(exportPanel); errorsContainer.AddChild(errorsPanel); return(errorsContainer); } return(exportPanel); }; this.AddChild(new TextButton("Export".Localize(), theme) { Selectable = false, Padding = theme.TextButtonPadding.Clone(right: 5) }); }
public ExportPrintItemPage(IEnumerable <ILibraryItem> libraryItems, bool centerOnBed, PrinterConfig printer) { this.centerOnBed = centerOnBed; this.WindowTitle = "Export File".Localize(); this.HeaderText = "Export selection to".Localize() + ":"; this.libraryItems = libraryItems; this.Name = "Export Item Window"; var commonMargin = new BorderDouble(4, 2); bool isFirstItem = true; // Must be constructed before plugins are initialized var exportButton = theme.CreateDialogButton("Export".Localize()); validationPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) { HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Fit }; // GCode export exportPluginButtons = new Dictionary <RadioButton, IExportPlugin>(); foreach (IExportPlugin plugin in PluginFinder.CreateInstancesOf <IExportPlugin>().OrderBy(p => p.ButtonText)) { plugin.Initialize(printer); // Skip plugins which are invalid for the current printer if (!plugin.Enabled) { if (!string.IsNullOrEmpty(plugin.DisabledReason)) { // add a message to let us know why not enabled var disabledPluginButton = new RadioButton(new RadioImageWidget(plugin.ButtonText, theme.TextColor, plugin.Icon)) { HAnchor = HAnchor.Left, Margin = commonMargin, Cursor = Cursors.Hand, Name = plugin.ButtonText + " Button", Enabled = false }; contentRow.AddChild(disabledPluginButton); contentRow.AddChild(new TextWidget("Disabled: {0}".Localize().FormatWith(plugin.DisabledReason), textColor: theme.PrimaryAccentColor) { Margin = new BorderDouble(left: 80), HAnchor = HAnchor.Left }); } continue; } // Create export button for each plugin var pluginButton = new RadioButton(new RadioImageWidget(plugin.ButtonText, theme.TextColor, plugin.Icon)) { HAnchor = HAnchor.Left, Margin = commonMargin, Cursor = Cursors.Hand, Name = plugin.ButtonText + " Button" }; contentRow.AddChild(pluginButton); if (plugin is GCodeExport) { var gcodeExportButton = pluginButton; gcodeExportButton.CheckedStateChanged += (s, e) => { validationPanel.CloseAllChildren(); if (gcodeExportButton.Checked) { var errors = printer.ValidateSettings(); exportButton.Enabled = !errors.Any(item => item.ErrorLevel == ValidationErrorLevel.Error); validationPanel.AddChild( new ValidationErrorsPanel( errors, AppContext.Theme) { HAnchor = HAnchor.Stretch }); } else { exportButton.Enabled = true; } }; } if (isFirstItem) { pluginButton.Checked = true; isFirstItem = false; } if (plugin is IExportWithOptions pluginWithOptions) { var optionPanel = pluginWithOptions.GetOptionsPanel(); if (optionPanel != null) { optionPanel.HAnchor = HAnchor.Stretch; optionPanel.VAnchor = VAnchor.Fit; contentRow.AddChild(optionPanel); } } exportPluginButtons.Add(pluginButton, plugin); } ContentRow.AddChild(new VerticalSpacer()); contentRow.AddChild(validationPanel); // TODO: make this work on the mac and then delete this if if (AggContext.OperatingSystem == OSType.Windows || AggContext.OperatingSystem == OSType.X11) { showInFolderAfterSave = new CheckBox("Show file in folder after save".Localize(), theme.TextColor, 10) { HAnchor = HAnchor.Left, Cursor = Cursors.Hand }; contentRow.AddChild(showInFolderAfterSave); } exportButton.Name = "Export Button"; exportButton.Click += (s, e) => { string fileTypeFilter = ""; string targetExtension = ""; IExportPlugin activePlugin = null; // Loop over all plugin buttons, break on the first checked item found foreach (var button in this.exportPluginButtons.Keys) { if (button.Checked) { activePlugin = exportPluginButtons[button]; break; } } // Early exit if no plugin radio button is selected if (activePlugin == null) { return; } fileTypeFilter = activePlugin.ExtensionFilter; targetExtension = activePlugin.FileExtension; this.Parent.CloseOnIdle(); if (activePlugin is FolderExport) { UiThread.RunOnIdle(() => { AggContext.FileDialogs.SelectFolderDialog( new SelectFolderDialogParams("Select Location To Export Files") { ActionButtonLabel = "Export".Localize(), Title = ApplicationController.Instance.ProductName + " - " + "Select A Folder".Localize() }, (openParams) => { ApplicationController.Instance.Tasks.Execute( "Saving".Localize() + "...", printer, async(reporter, cancellationToken) => { string path = openParams.FolderPath; if (!string.IsNullOrEmpty(path)) { await activePlugin.Generate(libraryItems, path, reporter, cancellationToken); } }); }); }); return; } UiThread.RunOnIdle(() => { string title = ApplicationController.Instance.ProductName + " - " + "Export File".Localize(); string workspaceName = "Workspace " + DateTime.Now.ToString("yyyy-MM-dd HH_mm_ss"); AggContext.FileDialogs.SaveFileDialog( new SaveFileDialogParams(fileTypeFilter) { Title = title, ActionButtonLabel = "Export".Localize(), FileName = Path.GetFileNameWithoutExtension(libraryItems.FirstOrDefault()?.Name ?? workspaceName) }, (saveParams) => { string savePath = saveParams.FileName; if (!string.IsNullOrEmpty(savePath)) { ApplicationController.Instance.Tasks.Execute( "Exporting".Localize() + "...", printer, async(reporter, cancellationToken) => { string extension = Path.GetExtension(savePath); if (extension != targetExtension) { savePath += targetExtension; } List <ValidationError> exportErrors = null; if (activePlugin != null) { if (activePlugin is GCodeExport gCodeExport) { gCodeExport.CenterOnBed = centerOnBed; } exportErrors = await activePlugin.Generate(libraryItems, savePath, reporter, cancellationToken); } if (exportErrors == null || exportErrors.Count == 0) { ShowFileIfRequested(savePath); } else { bool showGenerateErrors = !(activePlugin is GCodeExport); // Only show errors in Generate if not GCodeExport - GCodeExport shows validation errors before Generate call if (showGenerateErrors) { ApplicationController.Instance.ShowValidationErrors("Export Error".Localize(), exportErrors); } } }); } }); }); }; this.AddPageAction(exportButton); }