export-margin-options implementation #33

Merged
fierke merged 4 commits from export-margin-options into main 2026-04-23 14:22:58 +00:00
4 changed files with 149 additions and 58 deletions
Showing only changes of commit df6c187a00 - Show all commits
+21 -1
View File
@@ -10,6 +10,7 @@ public class Settings
public static Settings _instance = new(); public static Settings _instance = new();
public AddressSets addressSets = new(); public AddressSets addressSets = new();
public Customers customers = new(); public Customers customers = new();
public PdfExportSettings pdfExport { get; set; } = new();
public string settingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), public string settingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"logofclient", "config.json"); "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 class Global
{ {
public static Global _instance; public static Global _instance;
@@ -191,4 +211,4 @@ public class Country
return null; return null;
} }
} }
+4 -4
View File
@@ -270,11 +270,11 @@
<StackPanel Grid.Column="2" Orientation="Vertical" Spacing="10"> <StackPanel Grid.Column="2" Orientation="Vertical" Spacing="10">
<Grid ColumnDefinitions="*,*"> <Grid ColumnDefinitions="*,*">
<Label Content="Zeilen pro Seite"></Label> <Label Content="Zeilen pro Seite"></Label>
<NumericUpDown Grid.Column="1" x:Name="TbExpMargRowsPerPage" Minimum="1" Maximum="10" Value="3"></NumericUpDown> <NumericUpDown Grid.Column="1" x:Name="TbExpMargRowsPerPage" Minimum="1" Maximum="10" Value="7"></NumericUpDown>
</Grid> </Grid>
<Grid ColumnDefinitions="*,*"> <Grid ColumnDefinitions="*,*">
<Label Grid.Column="0" Content="Spalten pro Seite"></Label> <Label Grid.Column="0" Content="Spalten pro Seite"></Label>
<NumericUpDown Grid.Column="1" x:Name="NudExpMargColumnsPerPage" Minimum="1" Maximum="8" Value="7"></NumericUpDown> <NumericUpDown Grid.Column="1" x:Name="NudExpMargColumnsPerPage" Minimum="1" Maximum="8" Value="3"></NumericUpDown>
</Grid> </Grid>
<Grid ColumnDefinitions="*,*"> <Grid ColumnDefinitions="*,*">
<Label Grid.Column="0" Content="Schriftgröße (groß)"></Label> <Label Grid.Column="0" Content="Schriftgröße (groß)"></Label>
@@ -287,7 +287,7 @@
</StackPanel> </StackPanel>
</Grid> </Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="Start" IsEnabled="False"></Button> <Button Content="Start" Click="BtnStartGenerateLabels_OnClick"></Button>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</Grid> </Grid>
@@ -612,4 +612,4 @@
</Grid> </Grid>
</Border> </Border>
</Window> </Window>
+88 -2
View File
@@ -5,6 +5,7 @@ using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Controls.Primitives;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Logof_Client.Wiki; using Logof_Client.Wiki;
@@ -33,6 +34,8 @@ public partial class MainWindow : Window
WindowState = WindowState.Maximized; WindowState = WindowState.Maximized;
Global.Load(); Global.Load();
Settings.Load(); Settings.Load();
LoadPdfExportOptions();
HookPdfExportOptionEvents();
RefreshCountryView(); RefreshCountryView();
@@ -735,11 +738,13 @@ public partial class MainWindow : Window
GrdCalcMan.IsVisible = false; GrdCalcMan.IsVisible = false;
GrdCombineTypes.IsVisible = false; GrdCombineTypes.IsVisible = false;
GrdExportMarginOptions.IsVisible = true; GrdExportMarginOptions.IsVisible = true;
LoadPdfExportOptions();
} }
private async void BtnStartGenerateLabels_OnClick(object? sender, RoutedEventArgs e) private async void BtnStartGenerateLabels_OnClick(object? sender, RoutedEventArgs e)
{ {
SavePdfExportOptions();
var saveDialog = new SaveFileDialog var saveDialog = new SaveFileDialog
{ {
DefaultExtension = "pdf", DefaultExtension = "pdf",
@@ -749,7 +754,7 @@ public partial class MainWindow : Window
if (!string.IsNullOrEmpty(filePath)) if (!string.IsNullOrEmpty(filePath))
{ {
var builder = new PdfBuilder(); var builder = new PdfBuilder(Settings._instance.pdfExport);
builder.CreateAddressLabelPdfFromAddressSetWithPlaceholder( builder.CreateAddressLabelPdfFromAddressSetWithPlaceholder(
Convert.ToInt32(LstCustomerAdressSets.SelectedItems[0].ToString().Split(" - ")[0]), 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) private void TbSettingsCustomerSenderAddress_OnTextChanged(object? sender, TextChangedEventArgs e)
{ {
if (LstSettingsCustomers.SelectedIndex == null || LstSettingsCustomers.SelectedIndex == -1) return; if (LstSettingsCustomers.SelectedIndex == null || LstSettingsCustomers.SelectedIndex == -1) return;
+36 -51
View File
@@ -11,36 +11,15 @@ namespace Logof_Client;
public class PdfBuilder public class PdfBuilder
{ {
// Table layout private readonly PdfExportSettings _settings;
private const int CellsPerRow = 3;
private const int CellsPerPage = 21; // 3 columns × 7 rows
private readonly XFont _boldFont; 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 _regularFont;
private readonly XFont _smallFont; private readonly XFont _smallFont;
public PdfBuilder() public PdfBuilder(PdfExportSettings? settings = null)
{ {
EnsureFontResolverRegistered(); EnsureFontResolverRegistered();
_settings = settings ?? new PdfExportSettings();
// Select first font from build output fonts folder (AppContext.BaseDirectory/fonts) // Select first font from build output fonts folder (AppContext.BaseDirectory/fonts)
var chosenFamily = "Arial"; var chosenFamily = "Arial";
@@ -58,9 +37,9 @@ public class PdfBuilder
chosenFamily = "Arial"; chosenFamily = "Arial";
} }
_boldFont = new XFont(chosenFamily, _fontSize, XFontStyleEx.Bold); _boldFont = new XFont(chosenFamily, _settings.fontSize, XFontStyleEx.Bold);
_regularFont = new XFont(chosenFamily, _fontSize, XFontStyleEx.Regular); _regularFont = new XFont(chosenFamily, _settings.fontSize, XFontStyleEx.Regular);
_smallFont = new XFont(chosenFamily, _smallFontSize, XFontStyleEx.Regular); _smallFont = new XFont(chosenFamily, _settings.smallFontSize, XFontStyleEx.Regular);
} }
private static void EnsureFontResolverRegistered() private static void EnsureFontResolverRegistered()
@@ -160,20 +139,17 @@ public class PdfBuilder
private void DrawPage(XGraphics gfx, List<string> addresses, ref int addressIndex) private void DrawPage(XGraphics gfx, List<string> addresses, ref int addressIndex)
{ {
var cellCount = 0; for (var row = 0; row < _settings.rowsPerPage; row++)
for (var row = 0; row < 7; row++)
{ {
for (var col = 0; col < 3; col++) for (var col = 0; col < _settings.columnsPerPage; col++)
{ {
if (addressIndex >= addresses.Count) break; if (addressIndex >= addresses.Count) break;
var x = MmToPoints(_marginLeft + col * _cellWidth); var x = MmToPoints(_settings.pageMarginLeftMm + col * GetCellWidthMm());
var y = MmToPoints(_marginTop + row * _cellHeight); var y = MmToPoints(_settings.pageMarginTopMm + row * GetCellHeightMm());
DrawCell(gfx, x, y, addresses[addressIndex]); DrawCell(gfx, x, y, addresses[addressIndex]);
addressIndex++; addressIndex++;
cellCount++;
} }
if (addressIndex >= addresses.Count) break; if (addressIndex >= addresses.Count) break;
@@ -183,13 +159,11 @@ public class PdfBuilder
private void DrawPageWithPlaceholder(XGraphics gfx, List<string> addresses, ref int addressIndex, private void DrawPageWithPlaceholder(XGraphics gfx, List<string> addresses, ref int addressIndex,
ref bool isFirstCell, string placeholderText) ref bool isFirstCell, string placeholderText)
{ {
var cellCount = 0; for (var row = 0; row < _settings.rowsPerPage; row++)
for (var col = 0; col < _settings.columnsPerPage; col++)
for (var row = 0; row < 7; row++)
for (var col = 0; col < 3; col++)
{ {
var x = MmToPoints(_marginLeft + col * _cellWidth); var x = MmToPoints(_settings.pageMarginLeftMm + col * GetCellWidthMm());
var y = MmToPoints(_marginTop + row * _cellHeight); var y = MmToPoints(_settings.pageMarginTopMm + row * GetCellHeightMm());
// First cell: placeholder // First cell: placeholder
if (isFirstCell) if (isFirstCell)
@@ -206,15 +180,13 @@ public class PdfBuilder
{ {
DrawEmptyCell(gfx, x, y); DrawEmptyCell(gfx, x, y);
} }
cellCount++;
} }
} }
private void DrawCell(XGraphics gfx, double x, double y, string? address) private void DrawCell(XGraphics gfx, double x, double y, string? address)
{ {
var cellWidthPoints = MmToPoints(_cellWidth); var cellWidthPoints = MmToPoints(GetCellWidthMm());
var cellHeightPoints = MmToPoints(_cellHeight); var cellHeightPoints = MmToPoints(GetCellHeightMm());
// Draw cell border // Draw cell border
var rect = new XRect(x, y, cellWidthPoints, cellHeightPoints); var rect = new XRect(x, y, cellWidthPoints, cellHeightPoints);
@@ -226,8 +198,8 @@ public class PdfBuilder
private void DrawEmptyCell(XGraphics gfx, double x, double y) private void DrawEmptyCell(XGraphics gfx, double x, double y)
{ {
var cellWidthPoints = MmToPoints(_cellWidth); var cellWidthPoints = MmToPoints(GetCellWidthMm());
var cellHeightPoints = MmToPoints(_cellHeight); var cellHeightPoints = MmToPoints(GetCellHeightMm());
var rect = new XRect(x, y, cellWidthPoints, cellHeightPoints); var rect = new XRect(x, y, cellWidthPoints, cellHeightPoints);
gfx.DrawRectangle(XPens.Black, rect); 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) private void DrawMarkdownText(XGraphics gfx, string text, double x, double y, double cellWidth, double cellHeight)
{ {
var paddingLeftPoints = MmToPoints(_cellPaddingLeft); var paddingLeftPoints = MmToPoints(_settings.cellPaddingLeftMm);
var paddingTopPoints = MmToPoints(_cellPaddingTop); var paddingRightPoints = MmToPoints(_settings.cellPaddingRightMm);
var paddingBottomPoints = MmToPoints(_cellPaddingBottom); 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 // Split text by newlines and remove empty trailing lines
var rawLines = text.Split(new[] { "\n" }, StringSplitOptions.None); var rawLines = text.Split(new[] { "\n" }, StringSplitOptions.None);
@@ -383,6 +356,18 @@ public class PdfBuilder
return mm * 2.834645669; 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 // Configuration methods to allow customization
/// <summary> /// <summary>
@@ -402,4 +387,4 @@ public class PdfBuilder
if (left < 0 || top < 0 || right < 0 || bottom < 0) if (left < 0 || top < 0 || right < 0 || bottom < 0)
throw new ArgumentException("Margins cannot be negative"); throw new ArgumentException("Margins cannot be negative");
} }
} }