예제 #1
0
        protected void AddRow(ContentRow item)
        {
            if (UseIndex)
            {
                throw new InvalidOperationException("Cannot use AddRow when UseIndex is true, use AddRows instead");
            }

            if (currentHeaderIndex == -1)
            {
                if (CollapseEnabled)
                {
                    AddCollapseRow("", 0);
                }
                else
                {
                    AddHeaderRow("");
                }

                currentHeaderIndex = 0;
            }

            BeforeAddingRow(item);

            if (_items.Count == currentHeaderIndex)
            {
                currentHeaderIndex--;
            }

            var container = _items[currentHeaderIndex];

            container.Item2.Add(item);
        }
        /// <summary>
        /// Returns a list of content rows for use in populating buckets and embeddables
        /// </summary>
        /// <returns>a generic list of ContentRow objects</returns>
        public IList <IContentRow> GetContentRows(Guid contentID)
        {
            var list = new List <IContentRow>();

            using (SqlConnection conn = (SqlConnection)_factory.GetConnection())
            {
                SqlCommand comm = (SqlCommand)_factory.GetCommand("GetCompletedContent");
                comm.CommandType = CommandType.StoredProcedure;
                comm.Parameters.AddWithValue("@contentID", contentID);

                try
                {
                    conn.Open();
                    var reader = comm.ExecuteReader();
                    while (reader.Read())
                    {
                        var cRow = new ContentRow
                        {
                            contentID    = contentID,
                            bucketID     = reader.GetInt32(0),
                            embeddableID = reader.GetInt32(1),
                        };
                        list.Add(cRow);
                    }
                }
                finally
                {
                    conn.Close();
                }
            }
            return(list);
        }
예제 #3
0
        public void HavingAnEmptyNormalRowList_WhenOneNormalRowIsAdded_ThenListContainsTheNormalRow()
        {
            ContentRow contentRow = new ContentRow();

            contentRowList.Add(contentRow);

            Assert.That(contentRowList[0], Is.SameAs(contentRow));
        }
예제 #4
0
        public void HavingAnEmptyNormalRowList_WhenOneNormalRowIsAdded_ThenRowCountIs1()
        {
            ContentRow contentRow = new ContentRow();

            contentRowList.Add(contentRow);

            Assert.That(contentRowList.Count, Is.EqualTo(1));
        }
예제 #5
0
        public void HavingAnEmptyNormalRowList_WhenOneNormalRowIsAdded_ThenDataGridIsSetToNormalRow()
        {
            ContentRow contentRow = new ContentRow();

            contentRowList.Add(contentRow);

            Assert.That(contentRow.ParentDataGrid, Is.SameAs(dataGrid));
        }
예제 #6
0
    public void RemoveRow(ItemRow row)
    {
        itemListData.itemRowDataListContainer.itemRowDataList.Remove(row.itemRowData);
        ContentRow contentRow = row;

        base.RemoveRow(contentRow);
        CalculateTotals();
        SetCheckoutButtonInteraction();
    }
예제 #7
0
        private void BeforeAddingRow(ContentRow item)
        {
            item._controller = this;

            if (!item.Accessory.HasValue)
            {
                item.Accessory = DefaultAccessory;
            }
        }
예제 #8
0
        public void HavingANormalRowListWithOneRow_WhenRemoveTheRow_ThenCountIs0()
        {
            ContentRow contentRow = new ContentRow("value 1");

            contentRowList.Add(contentRow);

            contentRowList.Remove(contentRow);

            Assert.That(contentRowList.Count, Is.EqualTo(0));
        }
예제 #9
0
        public static ContentRow MakeRow(string pageNum, string langData1, string langData2)
        {
            var result = new ContentRow();

            result.AddCell(InternalSpreadsheet.TextGroupLabel);
            result.AddCell(pageNum);
            result.AddCell("1");             // group index placeholder, not exactly right but near enough for this test
            result.AddCell("<p>" + langData1 + "</p>");
            result.AddCell("<p>" + langData2 + "</p>");
            return(result);
        }
예제 #10
0
        public void HavingANormalRowListWithTwoRows_WhenRemoveSecondRow_ThenCountIs1()
        {
            ContentRow contentRow1 = new ContentRow("value 1");
            ContentRow contentRow2 = new ContentRow("value 2");

            contentRowList.Add(contentRow1);
            contentRowList.Add(contentRow2);

            contentRowList.Remove(contentRow2);

            Assert.That(contentRowList.Count, Is.EqualTo(1));
        }
예제 #11
0
        public void HavingANormalRowListWithTwoRows_WhenRemoveSecondRow_ThenFirstRowIsStillInList()
        {
            ContentRow contentRow1 = new ContentRow("value 1");
            ContentRow contentRow2 = new ContentRow("value 2");

            contentRowList.Add(contentRow1);
            contentRowList.Add(contentRow2);

            contentRowList.Remove(contentRow2);

            Assert.That(contentRowList[0], Is.EqualTo(contentRow1));
        }
예제 #12
0
        public void OneTimeSetup()
        {
            _testFolder = new TemporaryFolder("SpreadsheetImporterWithBookTests");
            // We need 2 layers of temp folder because BringBookUpToDate will change the name of the book
            // folder to match an imported title.
            _bookFolder = new TemporaryFolder(_testFolder, "Book");
            var settings = new NewCollectionSettings();

            settings.Language1.Iso639Code = "en";
            settings.Language1.SetName("English", false);
            settings.SettingsFilePath = Path.Combine(_bookFolder.FolderPath, "dummy");

            var fileLocator = new BloomFileLocator(settings, new XMatterPackFinder(new string[] { }), ProjectContext.GetFactoryFileLocations(),
                                                   ProjectContext.GetFoundFileLocations(), ProjectContext.GetAfterXMatterFileLocations());
            var bookFilePath = Path.Combine(_bookFolder.FolderPath, "testBook.htm");

            if (File.Exists(bookFilePath))             // Shouldn't ever happen, but... just being careful.
            {
                RobustFile.Delete(bookFilePath);
            }
            _dom = SetupTestDom();
            // Write out our test book
            File.WriteAllText(bookFilePath, _dom.RawDom.OuterXml.ToString());
            var storage = new BookStorage(_bookFolder.FolderPath, fileLocator, new BookRenamedEvent(), settings);

            var book = new Bloom.Book.Book(new BookInfo(_bookFolder.FolderPath, true), storage, null,
                                           settings, new Bloom.Edit.PageSelection(),
                                           new PageListChangedEvent(), new BookRefreshEvent());

            // Create the regular production importer
            _importer = new SpreadsheetImporter(null, book, _bookFolder.FolderPath);

            // Set up the internal spreadsheet rows directly.
            var ss             = new InternalSpreadsheet();
            var columnForEn    = ss.AddColumnForLang("en", "English");
            var columnForImage = ss.GetColumnForTag(InternalSpreadsheet.ImageSourceColumnLabel);

            var newTitle = "My new book title";
            var titleRow = new ContentRow(ss);

            titleRow.AddCell(InternalSpreadsheet.BookTitleRowLabel);
            titleRow.SetCell(columnForEn, newTitle);

            var coverImageRow = new ContentRow(ss);

            coverImageRow.AddCell(InternalSpreadsheet.CoverImageRowLabel);
            coverImageRow.SetCell(columnForImage, Path.Combine("images", "Othello 199.jpg"));

            _importer.Import(ss);

            _resultElement = ReadResultingBookToXml(newTitle);
        }
예제 #13
0
    private IEnumerator AddRow(ContentRow row, LogLevel lvl, float ttl)
    {
        if (lvl >= logLvl)
        {
            _contentList.Add(row);
            updateTextField();
            yield return(new WaitForSeconds(ttl / 1000.0f));

            _contentList.Remove(row);
            updateTextField();
        }
        yield return(null);
    }
예제 #14
0
 public void ResetOtherRows(ContentRow sourceRow)
 {
     if (contentList != null)
     {
         foreach (ContentRow row in contentList)
         {
             if (row != sourceRow)
             {
                 row.ResetRow();
             }
         }
     }
 }
        public void HavingRowWithPaddingLeft5_WhenCalculatingPaddingLeft_ThenPaddingLeftIs5()
        {
            ContentCell contentCell = new ContentCell();
            ContentRow  contentRow  = new ContentRow
            {
                CellPaddingLeft = 5
            };

            contentRow.AddCell(contentCell);

            int actual = contentCell.CalculatePaddingLeft();

            Assert.That(actual, Is.EqualTo(5));
        }
예제 #16
0
    /// <summary>
    /// Fills the properties of a content row (bucket / embeddable) object.
    /// </summary>
    /// <param name="r">The IContentRevision object.</param>
    /// <param name="rows">The list of content rows.</param>
    private void FillContentRows(IContentRevision r, List <ContentRow> rows)
    {
        var embeddables = (List <string>)ViewState["embeddables"];

        if (embeddables == null)
        {
            return;
        }

        foreach (var entry in embeddables.Select(embeddable => embeddable.Split('|')))
        {
            string[] chunks = entry[0].Split(':');

            ContentRow row = new ContentRow();
            switch (chunks[1])
            {
            case "AddHeaderEmbeddableRow":
                row.bucketID = 1;
                break;

            case "AddPrimaryNavEmbeddableRow":
                row.bucketID = 2;
                break;

            case "AddContentEmbeddableRow":
                row.bucketID = 3;
                break;

            case "AddSubNavEmbeddableRow":
                row.bucketID = 4;
                break;

            case "AddFooterEmbeddableRow":
                row.bucketID = 5;
                break;

            default:
                break;
            }

            row.embeddableID = Convert.ToInt32(entry[1]);
            row.contentID    = r.VersionID;
            rows.Add(row);
        }
    }
        public void HavingDataGridWithPaddingLeft5_WhenCalculatingPaddingLeft_ThenPaddingLeftIs5()
        {
            ContentCell contentCell = new ContentCell();

            ContentRow contentRow = new ContentRow();

            contentRow.AddCell(contentCell);

            DataGrid dataGrid = new DataGrid
            {
                CellPaddingLeft = 5
            };

            dataGrid.Rows.Add(contentRow);

            int actual = contentCell.CalculatePaddingLeft();

            Assert.That(actual, Is.EqualTo(5));
        }
예제 #18
0
        public static RowX CreateFrom(ContentRow contentRow)
        {
            if (contentRow == null)
            {
                throw new ArgumentNullException(nameof(contentRow));
            }

            RowX rowX = new()
            {
                Border = contentRow.ParentDataGrid?.Border?.IsVisible == true
                    ? DataGridBorderX.CreateFrom(contentRow.ParentDataGrid.Border)
                    : null,
                Cells = contentRow
                        .Select(CellX.CreateFrom)
                        .ToList()
            };

            rowX.CalculateLayout();

            return(rowX);
        }
        /// <summary>
        /// Saves a row of content control information.
        /// </summary>
        /// <param name="r">An IContentRevision object.</param>
        /// <param name="row">A ContentRow object.</param>
        public void SaveRow(IContentRevision r, ContentRow row)
        {
            using (SqlConnection conn = (SqlConnection)_factory.GetConnection())
            {
                SqlCommand comm = (SqlCommand)_factory.GetCommand("InsertContentRow");
                comm.CommandType = CommandType.StoredProcedure;
                comm.Parameters.AddWithValue("@versionID", r.VersionID);
                comm.Parameters.AddWithValue("@bucketID", row.bucketID);
                comm.Parameters.AddWithValue("@embeddableID", row.embeddableID);

                try
                {
                    conn.Open();
                    comm.ExecuteNonQuery();
                }
                finally
                {
                    conn.Close();
                }
            }
        }
        public void HavingColumnWithPaddingRight5_WhenCalculatingPaddingRight_ThenPaddingRightIs5()
        {
            ContentCell contentCell = new ContentCell();

            ContentRow contentRow = new ContentRow();

            contentRow.AddCell(contentCell);

            DataGrid dataGrid = new DataGrid();

            dataGrid.Rows.Add(contentRow);

            Column column = new Column
            {
                CellPaddingRight = 5
            };

            dataGrid.Columns.Add(column);

            int actual = contentCell.CalculatePaddingRight();

            Assert.That(actual, Is.EqualTo(5));
        }
예제 #21
0
        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);
        }
예제 #22
0
        private List <ContentRow> GetContentRows(DateTime forwardDate, string category = "home_page_data")
        {
            var result            = new List <ContentRow>();
            var cmsData           = _tabletCms.GetMetaData(category);
            var cmsDataProperties = (IDictionary <string, object>)cmsData;

            if (cmsData != null && cmsDataProperties.ContainsKey("rows"))
            {
                foreach (var row in cmsData.rows)
                {
                    var rowItem = row.Value;

                    var contentRow = new ContentRow();

                    foreach (var slot in rowItem)
                    {
                        var slotItem           = slot.Value;
                        var slotItemProperties = (IDictionary <string, object>)slotItem;

                        var start = DateTime.MinValue;
                        var end   = DateTime.MaxValue;

                        if (slotItemProperties.ContainsKey("start"))
                        {
                            if (!string.IsNullOrEmpty(slotItem.start))
                            {
                                start = DateTime.Parse(slotItem.start);
                            }
                        }
                        if (slotItemProperties.ContainsKey("end"))
                        {
                            if (!string.IsNullOrEmpty(slotItem.end))
                            {
                                end = DateTime.Parse(slotItem.end);
                            }
                        }

                        if (start <= forwardDate && end >= forwardDate)
                        {
                            var contentSlot = new ContentSlot();

                            var type  = "";
                            var width = "";

                            if (slotItemProperties.ContainsKey("type"))
                            {
                                type = slotItem.type;
                            }

                            if (slotItemProperties.ContainsKey("width"))
                            {
                                width = slotItem.width;
                            }

                            switch (type)
                            {
                            case "feature-slider":

                                contentSlot = ParseFeatureSlider(slot);

                                break;

                            case "shoe-finder":

                                //nothing really needs to be parsed for this, just type and width below

                                break;

                            case "feature":

                                if (slotItemProperties.ContainsKey("feature"))
                                {
                                    contentSlot = ParseFeature(slotItem.feature);
                                }

                                break;

                            case "product-slider":

                                contentSlot = ParseProductSlider(slot);

                                break;
                            }

                            contentSlot.Type  = type;
                            contentSlot.Width = width;

                            contentRow.Slots.Add(contentSlot);
                        }
                    }

                    result.Add(contentRow);
                }
            }

            return(result);
        }
 public void AddContentRow(ContentRow row) {
     this.Rows.Add(row);
 }
 public void RemoveContentRow(ContentRow row) {
     this.Rows.Remove(row);
 }
 public ContentRowChangeEvent(ContentRow row, global::System.Data.DataRowAction action) {
     this.eventRow = row;
     this.eventAction = action;
 }
예제 #26
0
 public virtual void AddRow(ContentRow row)
 {
     row.transform.SetParent(contentPanel.transform);
     row.transform.SetAsLastSibling();
     contentList.Add(row);
 }
예제 #27
0
 public virtual void RemoveRow(ContentRow row)
 {
     contentList.Remove(row);
     row.transform.SetParent(null);
     Destroy(row.gameObject);
 }
예제 #28
0
    protected void Bind()
    {
        if (m_checklistRow == null)
        {
            return;
        }

        ContentRow  contentRow  = m_checklistRow as ContentRow;
        CheckboxRow checkboxRow = m_checklistRow as CheckboxRow;

        // Container rows are subclasses of contentrow, so check for contentrow last.
        if (m_checklistRow is ContainerRow containerRow)
        {
            mvItem.SetActiveView(vwRepeater);
            if (!NoHeader)
            {
                lblHeader.Text = HttpUtility.HtmlEncode(m_checklistRow.Content ?? string.Empty);
            }

            List <ChecklistRow> contents   = new List <ChecklistRow>();
            List <ChecklistRow> tabs       = new List <ChecklistRow>();
            List <ChecklistRow> headers    = new List <ChecklistRow>();
            List <ChecklistRow> subheaders = new List <ChecklistRow>();


            foreach (ChecklistRow ckl in containerRow.ContainedItems)
            {
                if (ckl is TabContainer)
                {
                    tabs.Add(ckl);
                }
                else if (ckl is HeaderContainer)
                {
                    headers.Add(ckl);
                }
                else if (ckl is SubHeaderContainer)
                {
                    subheaders.Add(ckl);
                }
                else
                {
                    contents.Add(ckl);
                }
            }

            // OK.  First bind the leaf content nodes - plain text and checkbox items.
            rptRows.DataSource = contents;
            rptRows.DataBind();

            // Now bind subheaders
            if (subheaders.Count != 0)
            {
                rptSubHeaders.DataSource = subheaders;
                rptSubHeaders.DataBind();
            }

            // Now bind the header rows:
            accordionRows.DataSource = headers;
            accordionRows.DataBind();

            // Finally, do any tabs
            for (int i = 0; i < tabs.Count; i++)
            {
                ChecklistRow tabRow            = tabs[i];
                AjaxControlToolkit.TabPanel tp = new AjaxControlToolkit.TabPanel();
                tabRows.Tabs.Add(tp);
                tp.HeaderText = HttpUtility.HtmlEncode(tabRow.Content);
                tp.ID         = String.Format(CultureInfo.InvariantCulture, "cklTabItem{0}", i);
                Controls_ChecklistControls_ChecklistItem ckli = (Controls_ChecklistControls_ChecklistItem)LoadControl("~/Controls/ChecklistControls/ChecklistItem.ascx");
                tp.Controls.Add(ckli);
                ckli.NoHeader = true;
                ckli.DataItem = tabRow;
            }
        }
        else if (checkboxRow != null || contentRow != null)
        {
            rptRows.DataSource = new ChecklistRow[] { m_checklistRow };
            rptRows.DataBind();
        }
    }
예제 #29
0
        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);
        }