From df6c187a003b1dbca7d01d1f6b1397194a793cf5 Mon Sep 17 00:00:00 2001 From: Elias Fierke Date: Thu, 23 Apr 2026 12:30:35 +0200 Subject: [PATCH] [chore:] combining export margin options gui with settings and PdfBuilder.cs --- DataStore/Settings.cs | 22 ++++++++++- MainWindow.axaml | 8 ++-- MainWindow.axaml.cs | 90 ++++++++++++++++++++++++++++++++++++++++++- Tasks/PdfBuilder.cs | 87 +++++++++++++++++------------------------ 4 files changed, 149 insertions(+), 58 deletions(-) diff --git a/DataStore/Settings.cs b/DataStore/Settings.cs index 5443e03..95bdb8b 100644 --- a/DataStore/Settings.cs +++ b/DataStore/Settings.cs @@ -10,6 +10,7 @@ public class Settings public static Settings _instance = new(); public AddressSets addressSets = new(); public Customers customers = new(); + public PdfExportSettings pdfExport { get; set; } = new(); public string settingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "logofclient", "config.json"); @@ -52,6 +53,25 @@ public class Settings } } +public class PdfExportSettings +{ + public double cellPaddingTopMm { get; set; } = 5; + public double cellPaddingBottomMm { get; set; } = 5; + public double cellPaddingLeftMm { get; set; } = 5; + public double cellPaddingRightMm { get; set; } = 5; + + public double pageMarginTopMm { get; set; } = 0; + public double pageMarginBottomMm { get; set; } = 0; + public double pageMarginLeftMm { get; set; } = 0; + public double pageMarginRightMm { get; set; } = 0; + + public int rowsPerPage { get; set; } = 7; + public int columnsPerPage { get; set; } = 3; + + public double fontSize { get; set; } = 9; + public double smallFontSize { get; set; } = 6; +} + public class Global { public static Global _instance; @@ -191,4 +211,4 @@ public class Country return null; } -} \ No newline at end of file +} diff --git a/MainWindow.axaml b/MainWindow.axaml index 7dae503..5185187 100644 --- a/MainWindow.axaml +++ b/MainWindow.axaml @@ -270,11 +270,11 @@ - + - + @@ -287,7 +287,7 @@ - + @@ -612,4 +612,4 @@ - \ No newline at end of file + diff --git a/MainWindow.axaml.cs b/MainWindow.axaml.cs index 71315d0..b01d20f 100644 --- a/MainWindow.axaml.cs +++ b/MainWindow.axaml.cs @@ -5,6 +5,7 @@ using System.IO; using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Interactivity; +using Avalonia.Controls.Primitives; using Avalonia.Platform.Storage; using Logof_Client.Wiki; @@ -33,6 +34,8 @@ public partial class MainWindow : Window WindowState = WindowState.Maximized; Global.Load(); Settings.Load(); + LoadPdfExportOptions(); + HookPdfExportOptionEvents(); RefreshCountryView(); @@ -735,11 +738,13 @@ public partial class MainWindow : Window GrdCalcMan.IsVisible = false; GrdCombineTypes.IsVisible = false; GrdExportMarginOptions.IsVisible = true; - + LoadPdfExportOptions(); } private async void BtnStartGenerateLabels_OnClick(object? sender, RoutedEventArgs e) { + SavePdfExportOptions(); + var saveDialog = new SaveFileDialog { DefaultExtension = "pdf", @@ -749,7 +754,7 @@ public partial class MainWindow : Window if (!string.IsNullOrEmpty(filePath)) { - var builder = new PdfBuilder(); + var builder = new PdfBuilder(Settings._instance.pdfExport); builder.CreateAddressLabelPdfFromAddressSetWithPlaceholder( Convert.ToInt32(LstCustomerAdressSets.SelectedItems[0].ToString().Split(" - ")[0]), @@ -760,6 +765,87 @@ public partial class MainWindow : Window } } + private void HookPdfExportOptionEvents() + { + var controls = GetPdfExportControls(); + foreach (var control in controls) control.ValueChanged += PdfExportOption_OnValueChanged; + } + + private void LoadPdfExportOptions() + { + var options = Settings._instance.pdfExport ?? new PdfExportSettings(); + + NudExpMargCellPaddingTop.Value = (decimal)options.cellPaddingTopMm; + NudExpMargCellPaddingBot.Value = (decimal)options.cellPaddingBottomMm; + NudExpMargCellPaddingLeft.Value = (decimal)options.cellPaddingLeftMm; + NudExpMargCellPaddingRight.Value = (decimal)options.cellPaddingRightMm; + + TbExpMargMarginTop.Value = (decimal)options.pageMarginTopMm; + TbExpMargMarginBottom.Value = (decimal)options.pageMarginBottomMm; + TbExpMargMarginLeft.Value = (decimal)options.pageMarginLeftMm; + TbExpMargMarginRight.Value = (decimal)options.pageMarginRightMm; + + TbExpMargRowsPerPage.Value = options.rowsPerPage; + NudExpMargColumnsPerPage.Value = options.columnsPerPage; + NudExpMargFontSize.Value = (decimal)options.fontSize; + NudExpMargSmallFontSize.Value = (decimal)options.smallFontSize; + } + + private void SavePdfExportOptions() + { + Settings._instance.pdfExport = new PdfExportSettings + { + cellPaddingTopMm = ReadDouble(NudExpMargCellPaddingTop), + cellPaddingBottomMm = ReadDouble(NudExpMargCellPaddingBot), + cellPaddingLeftMm = ReadDouble(NudExpMargCellPaddingLeft), + cellPaddingRightMm = ReadDouble(NudExpMargCellPaddingRight), + pageMarginTopMm = ReadDouble(TbExpMargMarginTop), + pageMarginBottomMm = ReadDouble(TbExpMargMarginBottom), + pageMarginLeftMm = ReadDouble(TbExpMargMarginLeft), + pageMarginRightMm = ReadDouble(TbExpMargMarginRight), + rowsPerPage = ReadInt(TbExpMargRowsPerPage, 7), + columnsPerPage = ReadInt(NudExpMargColumnsPerPage, 3), + fontSize = ReadDouble(NudExpMargFontSize), + smallFontSize = ReadDouble(NudExpMargSmallFontSize) + }; + + Settings.Save(); + } + + private void PdfExportOption_OnValueChanged(object? sender, NumericUpDownValueChangedEventArgs e) + { + SavePdfExportOptions(); + } + + private double ReadDouble(NumericUpDown control) + { + return (double)(control.Value ?? 0); + } + + private int ReadInt(NumericUpDown control, int fallback) + { + return (int)Math.Round(control.Value ?? fallback); + } + + private NumericUpDown[] GetPdfExportControls() + { + return + [ + NudExpMargCellPaddingTop, + NudExpMargCellPaddingBot, + NudExpMargCellPaddingLeft, + NudExpMargCellPaddingRight, + TbExpMargMarginTop, + TbExpMargMarginBottom, + TbExpMargMarginLeft, + TbExpMargMarginRight, + TbExpMargRowsPerPage, + NudExpMargColumnsPerPage, + NudExpMargFontSize, + NudExpMargSmallFontSize + ]; + } + private void TbSettingsCustomerSenderAddress_OnTextChanged(object? sender, TextChangedEventArgs e) { if (LstSettingsCustomers.SelectedIndex == null || LstSettingsCustomers.SelectedIndex == -1) return; diff --git a/Tasks/PdfBuilder.cs b/Tasks/PdfBuilder.cs index 43924cf..d33a587 100644 --- a/Tasks/PdfBuilder.cs +++ b/Tasks/PdfBuilder.cs @@ -11,36 +11,15 @@ namespace Logof_Client; public class PdfBuilder { - // Table layout - private const int CellsPerRow = 3; - private const int CellsPerPage = 21; // 3 columns × 7 rows + private readonly PdfExportSettings _settings; private readonly XFont _boldFont; - private readonly double _cellHeight = 42.43; // mm - private readonly double _cellPaddingBottom = 5; // mm - - // Padding inside cells - private readonly double _cellPaddingLeft = 5; // mm - private readonly double _cellPaddingTop = 5; // mm - - // Cell dimensions (in mm) - private readonly double _cellWidth = 70; // mm - - // Font settings - private readonly double _fontSize = 9; - private readonly double _smallFontSize = 6; - - private readonly double _marginBottom = 1; // mm - - // Paper and layout settings - private readonly double _marginLeft = 0; // mm - private readonly double _marginRight = 0; // mm - private readonly double _marginTop = 0; // mm private readonly XFont _regularFont; private readonly XFont _smallFont; - public PdfBuilder() + public PdfBuilder(PdfExportSettings? settings = null) { EnsureFontResolverRegistered(); + _settings = settings ?? new PdfExportSettings(); // Select first font from build output fonts folder (AppContext.BaseDirectory/fonts) var chosenFamily = "Arial"; @@ -58,9 +37,9 @@ public class PdfBuilder chosenFamily = "Arial"; } - _boldFont = new XFont(chosenFamily, _fontSize, XFontStyleEx.Bold); - _regularFont = new XFont(chosenFamily, _fontSize, XFontStyleEx.Regular); - _smallFont = new XFont(chosenFamily, _smallFontSize, XFontStyleEx.Regular); + _boldFont = new XFont(chosenFamily, _settings.fontSize, XFontStyleEx.Bold); + _regularFont = new XFont(chosenFamily, _settings.fontSize, XFontStyleEx.Regular); + _smallFont = new XFont(chosenFamily, _settings.smallFontSize, XFontStyleEx.Regular); } private static void EnsureFontResolverRegistered() @@ -160,20 +139,17 @@ public class PdfBuilder private void DrawPage(XGraphics gfx, List addresses, ref int addressIndex) { - var cellCount = 0; - - for (var row = 0; row < 7; row++) + for (var row = 0; row < _settings.rowsPerPage; row++) { - for (var col = 0; col < 3; col++) + for (var col = 0; col < _settings.columnsPerPage; col++) { if (addressIndex >= addresses.Count) break; - var x = MmToPoints(_marginLeft + col * _cellWidth); - var y = MmToPoints(_marginTop + row * _cellHeight); + var x = MmToPoints(_settings.pageMarginLeftMm + col * GetCellWidthMm()); + var y = MmToPoints(_settings.pageMarginTopMm + row * GetCellHeightMm()); DrawCell(gfx, x, y, addresses[addressIndex]); addressIndex++; - cellCount++; } if (addressIndex >= addresses.Count) break; @@ -183,13 +159,11 @@ public class PdfBuilder private void DrawPageWithPlaceholder(XGraphics gfx, List addresses, ref int addressIndex, ref bool isFirstCell, string placeholderText) { - var cellCount = 0; - - for (var row = 0; row < 7; row++) - for (var col = 0; col < 3; col++) + for (var row = 0; row < _settings.rowsPerPage; row++) + for (var col = 0; col < _settings.columnsPerPage; col++) { - var x = MmToPoints(_marginLeft + col * _cellWidth); - var y = MmToPoints(_marginTop + row * _cellHeight); + var x = MmToPoints(_settings.pageMarginLeftMm + col * GetCellWidthMm()); + var y = MmToPoints(_settings.pageMarginTopMm + row * GetCellHeightMm()); // First cell: placeholder if (isFirstCell) @@ -206,15 +180,13 @@ public class PdfBuilder { DrawEmptyCell(gfx, x, y); } - - cellCount++; } } private void DrawCell(XGraphics gfx, double x, double y, string? address) { - var cellWidthPoints = MmToPoints(_cellWidth); - var cellHeightPoints = MmToPoints(_cellHeight); + var cellWidthPoints = MmToPoints(GetCellWidthMm()); + var cellHeightPoints = MmToPoints(GetCellHeightMm()); // Draw cell border var rect = new XRect(x, y, cellWidthPoints, cellHeightPoints); @@ -226,8 +198,8 @@ public class PdfBuilder private void DrawEmptyCell(XGraphics gfx, double x, double y) { - var cellWidthPoints = MmToPoints(_cellWidth); - var cellHeightPoints = MmToPoints(_cellHeight); + var cellWidthPoints = MmToPoints(GetCellWidthMm()); + var cellHeightPoints = MmToPoints(GetCellHeightMm()); var rect = new XRect(x, y, cellWidthPoints, cellHeightPoints); gfx.DrawRectangle(XPens.Black, rect); @@ -235,11 +207,12 @@ public class PdfBuilder private void DrawMarkdownText(XGraphics gfx, string text, double x, double y, double cellWidth, double cellHeight) { - var paddingLeftPoints = MmToPoints(_cellPaddingLeft); - var paddingTopPoints = MmToPoints(_cellPaddingTop); - var paddingBottomPoints = MmToPoints(_cellPaddingBottom); + var paddingLeftPoints = MmToPoints(_settings.cellPaddingLeftMm); + var paddingRightPoints = MmToPoints(_settings.cellPaddingRightMm); + var paddingTopPoints = MmToPoints(_settings.cellPaddingTopMm); + var paddingBottomPoints = MmToPoints(_settings.cellPaddingBottomMm); - var maxWidth = cellWidth - paddingLeftPoints * 2; + var maxWidth = Math.Max(0, cellWidth - paddingLeftPoints - paddingRightPoints); // Split text by newlines and remove empty trailing lines var rawLines = text.Split(new[] { "\n" }, StringSplitOptions.None); @@ -383,6 +356,18 @@ public class PdfBuilder return mm * 2.834645669; } + private double GetCellWidthMm() + { + var availableWidthMm = 210d - _settings.pageMarginLeftMm - _settings.pageMarginRightMm; + return availableWidthMm / _settings.columnsPerPage; + } + + private double GetCellHeightMm() + { + var availableHeightMm = 297d - _settings.pageMarginTopMm - _settings.pageMarginBottomMm; + return availableHeightMm / _settings.rowsPerPage; + } + // Configuration methods to allow customization /// @@ -402,4 +387,4 @@ public class PdfBuilder if (left < 0 || top < 0 || right < 0 || bottom < 0) throw new ArgumentException("Margins cannot be negative"); } -} \ No newline at end of file +}