[feat:] pdf export options (working)
This commit is contained in:
81
CorrectionViewModel.cs
Normal file
81
CorrectionViewModel.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace PLG_Exam.ViewModels;
|
||||
|
||||
public class ExportOptionsViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private bool hasCorrectionLines = false;
|
||||
private int correctionMargin = 50;
|
||||
private double lineSpacing= 1.5;
|
||||
private string textPosition="left";
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
protected void OnPropertyChanged([CallerMemberName] string? name = null) =>
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||
|
||||
// ToggleSwitch
|
||||
public bool HasCorrectionLines
|
||||
{
|
||||
get => hasCorrectionLines;
|
||||
set { hasCorrectionLines = value; OnPropertyChanged(); }
|
||||
}
|
||||
|
||||
// Korrekturrand – RadioButtons mapped auf int
|
||||
public bool IsCorrectionMarginHalf
|
||||
{
|
||||
get => correctionMargin == 100;
|
||||
set { if (value) { correctionMargin = 100; OnPropertyChanged(); } }
|
||||
}
|
||||
|
||||
public bool IsCorrectionMarginQuarter
|
||||
{
|
||||
get => correctionMargin == 50;
|
||||
set { if (value) { correctionMargin = 50; OnPropertyChanged(); } }
|
||||
}
|
||||
|
||||
public bool IsCorrectionMarginNone
|
||||
{
|
||||
get => correctionMargin == 0;
|
||||
set { if (value) { correctionMargin = 0; OnPropertyChanged(); } }
|
||||
}
|
||||
|
||||
// Zeilenabstand
|
||||
public bool IsLineSpacing1
|
||||
{
|
||||
get => lineSpacing == 1.0;
|
||||
set { if (value) { lineSpacing = 1.0; OnPropertyChanged(); } }
|
||||
}
|
||||
|
||||
public bool IsLineSpacing15
|
||||
{
|
||||
get => lineSpacing == 1.5;
|
||||
set { if (value) { lineSpacing = 1.5; OnPropertyChanged(); } }
|
||||
}
|
||||
|
||||
public bool IsLineSpacing2
|
||||
{
|
||||
get => lineSpacing == 2.0;
|
||||
set { if (value) { lineSpacing = 2.0; OnPropertyChanged(); } }
|
||||
}
|
||||
|
||||
// Textposition
|
||||
public bool IsTextLeft
|
||||
{
|
||||
get => textPosition == "left";
|
||||
set { if (value) { textPosition = "left"; OnPropertyChanged(); } }
|
||||
}
|
||||
|
||||
public bool IsTextRight
|
||||
{
|
||||
get => textPosition == "right";
|
||||
set { if (value) { textPosition = "right"; OnPropertyChanged(); } }
|
||||
}
|
||||
|
||||
// Optional: Getter für externe Verwendung
|
||||
public int CorrectionMargin => correctionMargin;
|
||||
public double LineSpacing => lineSpacing;
|
||||
public string TextPosition => textPosition;
|
||||
}
|
||||
48
ExportOptions.axaml
Normal file
48
ExportOptions.axaml
Normal file
@@ -0,0 +1,48 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:PLG_Exam.ViewModels"
|
||||
x:DataType="vm:ExportOptionsViewModel"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
Width="350" Height="350"
|
||||
MinWidth="350" MinHeight="350" MaxHeight="350" MaxWidth="350"
|
||||
x:Class="PLG_Exam.ExportOptions"
|
||||
Title="Klausur abgeben">
|
||||
<ScrollViewer>
|
||||
<StackPanel Margin="20" Spacing="20">
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto" VerticalAlignment="Center">
|
||||
<TextBlock Text="Korrekturlinien" VerticalAlignment="Center" Grid.Column="0" />
|
||||
<ToggleSwitch IsChecked="{Binding HasCorrectionLines}" VerticalAlignment="Center" Grid.Column="1" HorizontalAlignment="Right"/>
|
||||
</Grid>
|
||||
|
||||
<StackPanel>
|
||||
<TextBlock Text="Korrekturrand" FontWeight="Bold"/>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<RadioButton GroupName="CorrectionMargin" Content="300" IsChecked="{Binding IsCorrectionMarginHalf}" />
|
||||
<RadioButton GroupName="CorrectionMargin" Content="150" IsChecked="{Binding IsCorrectionMarginQuarter}" />
|
||||
<RadioButton GroupName="CorrectionMargin" Content="Keiner" IsChecked="{Binding IsCorrectionMarginNone}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel>
|
||||
<TextBlock Text="Zeilenabstand" FontWeight="Bold"/>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<RadioButton GroupName="LineSpacing" Content="1-zeilig" IsChecked="{Binding IsLineSpacing1}" />
|
||||
<RadioButton GroupName="LineSpacing" Content="1.5-zeilig" IsChecked="{Binding IsLineSpacing15}" />
|
||||
<RadioButton GroupName="LineSpacing" Content="2-zeilig" IsChecked="{Binding IsLineSpacing2}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel>
|
||||
<TextBlock Text="Textposition" FontWeight="Bold"/>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<RadioButton GroupName="TextPosition" Content="Links" IsChecked="{Binding IsTextLeft}" />
|
||||
<RadioButton GroupName="TextPosition" Content="Rechts" IsChecked="{Binding IsTextRight}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<Button Content="Abgeben" HorizontalContentAlignment="Center" HorizontalAlignment="Stretch" Click="OnSubmitClick" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Window>
|
||||
27
ExportOptions.axaml.cs
Normal file
27
ExportOptions.axaml.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using PLG_Exam.ViewModels;
|
||||
|
||||
|
||||
namespace PLG_Exam;
|
||||
|
||||
public partial class ExportOptions : Window
|
||||
{
|
||||
public ExportOptions()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new ExportOptionsViewModel();
|
||||
}
|
||||
|
||||
private async void OnSubmitClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var viewModel = (ExportOptionsViewModel)DataContext;
|
||||
MainWindow._instance.ExportToPdf(viewModel.CorrectionMargin, viewModel.LineSpacing, viewModel.HasCorrectionLines, viewModel.TextPosition);
|
||||
this.Close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -175,7 +175,10 @@ namespace PLG_Exam
|
||||
|
||||
private async void OnSubmitClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ExportToPdf();
|
||||
ExportOptions exportOptions = new ExportOptions();
|
||||
exportOptions.WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||
await exportOptions.ShowDialog(this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -720,9 +723,11 @@ namespace PLG_Exam
|
||||
|
||||
|
||||
|
||||
public void ExportToPdf(){
|
||||
public void ExportToPdf(int margin, double lineSpacing, bool hasCorrectionLines, string textPosition){
|
||||
_ = GetCurrentExamDataAsJson();
|
||||
PFDExporter.ExportToPdf(_currentExam);
|
||||
PFDExporter exp = new PFDExporter();
|
||||
//exp.ExportToPdf(_currentExam, margin, lineSpacing, hasCorrectionLines, textPosition);
|
||||
exp.ExportAllCombinations(_currentExam);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
141
PFDExporter.cs
141
PFDExporter.cs
@@ -11,17 +11,31 @@ using System.Globalization;
|
||||
using MigraDoc.DocumentObjectModel;
|
||||
using System.Net.NetworkInformation;
|
||||
using Avalonia.Styling;
|
||||
using System.IO;
|
||||
|
||||
namespace PLG_Exam;
|
||||
|
||||
public static class PFDExporter
|
||||
public class PFDExporter
|
||||
{
|
||||
public static Exam exam;
|
||||
public static async void ExportToPdf(Exam examData)
|
||||
public Exam exam;
|
||||
public async void ExportToPdf(Exam examData, int correctionMargin, double lineSpacing, bool hasCorrectionLines, string textPosition, string filePath = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
exam = examData;
|
||||
corr_margin = correctionMargin*3;
|
||||
if(corr_margin == 0){
|
||||
corr_margin = 50;
|
||||
}
|
||||
if(lineSpacing == 1.0){
|
||||
lineHeight = 15;
|
||||
} else if(lineSpacing == 1.5){
|
||||
lineHeight = 21;
|
||||
} else if(lineSpacing == 2.0){
|
||||
lineHeight = 27;
|
||||
}
|
||||
this.hasCorrectionLines = hasCorrectionLines;
|
||||
this.textPosition = textPosition;
|
||||
//_ = GetCurrentExamDataAsJson();
|
||||
|
||||
if(examData.Name.IsValueNullOrEmpty() || examData.Vorname.IsValueNullOrEmpty() || examData.Title.IsValueNullOrEmpty() || examData.Datum == null){
|
||||
@@ -29,12 +43,15 @@ public static class PFDExporter
|
||||
return;
|
||||
}
|
||||
|
||||
var saveDialog = new SaveFileDialog
|
||||
{
|
||||
DefaultExtension = "pdf",
|
||||
Filters = { new FileDialogFilter { Name = "PDF files", Extensions = { "pdf" } } }
|
||||
};
|
||||
var filePath = await saveDialog.ShowAsync(MainWindow._instance);
|
||||
if(filePath==null){
|
||||
var saveDialog = new SaveFileDialog
|
||||
{
|
||||
DefaultExtension = "pdf",
|
||||
Filters = { new FileDialogFilter { Name = "PDF files", Extensions = { "pdf" } } }
|
||||
};
|
||||
filePath = await saveDialog.ShowAsync(MainWindow._instance);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(filePath)) return;
|
||||
|
||||
var font = new XFont("Cantarell", 14, XFontStyleEx.Bold);
|
||||
@@ -130,7 +147,7 @@ public static class PFDExporter
|
||||
}
|
||||
}
|
||||
|
||||
private static bool isInternetAvailable()
|
||||
private bool isInternetAvailable()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -145,10 +162,10 @@ public static class PFDExporter
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static bool isEscaped = false;
|
||||
public static bool isBold = false;
|
||||
public static bool isUnderline = false;
|
||||
private static List<(string Text, XFont Font, XBrush Brush)> ParseFormattedText(string text, XFont regularFont, XFont boldFont, XFont underlineFont)
|
||||
public bool isEscaped = false;
|
||||
public bool isBold = false;
|
||||
public bool isUnderline = false;
|
||||
private List<(string Text, XFont Font, XBrush Brush)> ParseFormattedText(string text, XFont regularFont, XFont boldFont, XFont underlineFont)
|
||||
{
|
||||
var result = new List<(string Text, XFont Font, XBrush Brush)>();
|
||||
var currentFont = regularFont;
|
||||
@@ -232,7 +249,7 @@ public static class PFDExporter
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void DrawFormattedText(XGraphics gfx, string text, XFont regularFont, XFont boldFont, XFont underlineFont, XRect rect)
|
||||
private void DrawFormattedText(XGraphics gfx, string text, XFont regularFont, XFont boldFont, XFont underlineFont, XRect rect)
|
||||
{
|
||||
var parsedText = ParseFormattedText(text, regularFont, boldFont, underlineFont);
|
||||
double x = rect.X;
|
||||
@@ -246,11 +263,14 @@ public static class PFDExporter
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawTaskWithPageBreak(PdfDocument document, ExamTab tab, XFont font, XFont headerFont, XFont smallFont)
|
||||
private double corr_margin = 300; // Seitenrand Korrektur
|
||||
private double lineHeight = 21; // Höhe einer Textzeile
|
||||
private bool hasCorrectionLines = false; // Korrekturrand aktiv
|
||||
private string textPosition = "left"; // Textposition (links, rechts, zentriert)
|
||||
|
||||
private void DrawTaskWithPageBreak(PdfDocument document, ExamTab tab, XFont font, XFont headerFont, XFont smallFont)
|
||||
{
|
||||
const double margin = 50; // Seitenränder
|
||||
const double corr_margin = 300; // Seitenrand Korrektur
|
||||
const double lineHeight = 21; // Höhe einer Textzeile
|
||||
const double headerHeight = 30; // Platz für die Kopfzeile pro Seite
|
||||
const double footerHeight = 20; // Platz für die Fußzeile
|
||||
const double usableHeight = 842 - margin * 2 - headerHeight - footerHeight; // Höhe des nutzbaren Bereichs
|
||||
@@ -263,26 +283,58 @@ public static class PFDExporter
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
// Wenn eine neue Seite benötigt wird (Seitenumbruch)
|
||||
if (page == null || currentHeight + lineHeight > usableHeight)
|
||||
{
|
||||
page = document.AddPage();
|
||||
gfx = XGraphics.FromPdfPage(page);
|
||||
currentHeight = 0;
|
||||
|
||||
// Kopfzeile zeichnen
|
||||
DrawName(gfx, tab, smallFont, margin, headerHeight, document.PageCount);
|
||||
DrawHeader(gfx, tab, headerFont, margin, headerHeight);
|
||||
}
|
||||
|
||||
var rect = new XRect(corr_margin, margin + headerHeight * headerline_count + currentHeight, page.Width - margin, lineHeight);
|
||||
// Berechnung der Textposition
|
||||
XRect rect;
|
||||
|
||||
|
||||
// Berechnung der Textposition basierend auf `textPosition`
|
||||
if (textPosition == "right")
|
||||
{
|
||||
rect = new XRect(margin + corr_margin - margin, margin + headerHeight + currentHeight, page.Width - margin - corr_margin, lineHeight);
|
||||
if (hasCorrectionLines && corr_margin > margin)
|
||||
{
|
||||
// Korrekturlinie wird nur neben dem Text gezeichnet (nur so breit wie der Korrekturrand)
|
||||
var correctionLineRect = new XRect(margin, margin + headerHeight + currentHeight + 15, corr_margin-margin-10, 1);
|
||||
gfx.DrawRectangle(XBrushes.LightGray, correctionLineRect);
|
||||
currentHeight += 1; // Korrekturlinie nimmt Platz ein
|
||||
}
|
||||
}
|
||||
else // links
|
||||
{
|
||||
rect = new XRect(margin, margin + headerHeight + currentHeight, page.Width - (2 * margin) - corr_margin, lineHeight);
|
||||
if (hasCorrectionLines && corr_margin > margin)
|
||||
{
|
||||
// Korrekturlinie wird nur neben dem Text gezeichnet (nur so breit wie der Korrekturrand)
|
||||
var correctionLineRect = new XRect(page.Width - corr_margin, margin + headerHeight + currentHeight + 15, corr_margin - margin, 1);
|
||||
gfx.DrawRectangle(XBrushes.LightGray, correctionLineRect);
|
||||
currentHeight += 1; // Korrekturlinie nimmt Platz ein
|
||||
}
|
||||
}
|
||||
|
||||
// Text formatieren und zeichnen
|
||||
DrawFormattedText(gfx, line, font, new XFont(font.Name, font.Size, XFontStyleEx.Bold), new XFont(font.Name, font.Size, XFontStyleEx.Underline), rect);
|
||||
currentHeight += lineHeight;
|
||||
currentHeight += lineHeight; // Zeilenhöhe für die nächste Zeile erhöhen
|
||||
}
|
||||
|
||||
gfx?.Dispose();
|
||||
}
|
||||
|
||||
private static int headerline_count = 0;
|
||||
private static void DrawHeader(XGraphics gfx, ExamTab tab, XFont font, double margin, double headerHeight)
|
||||
|
||||
|
||||
private int headerline_count = 0;
|
||||
private void DrawHeader(XGraphics gfx, ExamTab tab, XFont font, double margin, double headerHeight)
|
||||
{
|
||||
var maxWidth = gfx.PageSize.Width - margin * 2; // verfügbare Breite
|
||||
var lines = SplitTextIntoLines($"Aufgabe {tab.Aufgabennummer}: {tab.Überschrift}", maxWidth, font);
|
||||
@@ -300,7 +352,7 @@ public static class PFDExporter
|
||||
|
||||
}
|
||||
|
||||
private static void AddPageNumbers(PdfDocument document, XFont font, double margin)
|
||||
private void AddPageNumbers(PdfDocument document, XFont font, double margin)
|
||||
{
|
||||
|
||||
int totalPages = document.PageCount;
|
||||
@@ -316,7 +368,7 @@ public static class PFDExporter
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawName(XGraphics gfx, ExamTab tab, XFont font, double margin, double headerHeight, int page_num)
|
||||
private void DrawName(XGraphics gfx, ExamTab tab, XFont font, double margin, double headerHeight, int page_num)
|
||||
{
|
||||
var headerText = $"{exam.Name}, {exam.Vorname}";
|
||||
gfx.DrawString(headerText, font, XBrushes.Gray, new XRect(margin, margin-15, gfx.PageSize.Width - margin * 2, headerHeight), XStringFormats.TopLeft);
|
||||
@@ -330,7 +382,7 @@ public static class PFDExporter
|
||||
}
|
||||
|
||||
// Methode zum Aufteilen des Textes in Zeilen
|
||||
private static List<string> SplitTextIntoLines(string text, double maxWidth, XFont font)
|
||||
private List<string> SplitTextIntoLines(string text, double maxWidth, XFont font)
|
||||
{
|
||||
var lines = new List<string>();
|
||||
|
||||
@@ -384,7 +436,7 @@ public static class PFDExporter
|
||||
|
||||
|
||||
|
||||
private static void SetPdfLanguage(PdfSharp.Pdf.PdfDocument document, string language = "de")
|
||||
private void SetPdfLanguage(PdfSharp.Pdf.PdfDocument document, string language = "de")
|
||||
{
|
||||
var catalog = document.Internals.Catalog;
|
||||
|
||||
@@ -397,4 +449,41 @@ public static class PFDExporter
|
||||
catalog.Elements.Add("/Lang", new PdfSharp.Pdf.PdfString(language));
|
||||
}
|
||||
}
|
||||
|
||||
public void ExportAllCombinations(Exam curr_exam)
|
||||
{
|
||||
exam = curr_exam;
|
||||
// Mögliche Werte für die Variablen
|
||||
var textPositions = new[] { "left", "right" };
|
||||
var hasCorrectionLinesOptions = new[] { true, false };
|
||||
var correctionMargins = new[] { 100.0, 50.0, 0.0 };
|
||||
var lineHeights = new[] { 2.0, 1.5, 1.0 };
|
||||
|
||||
// Ordner für die gespeicherten PDFs
|
||||
string folderPath = "/home/fierke/Schreibtisch";
|
||||
if (!Directory.Exists(folderPath))
|
||||
{
|
||||
Directory.CreateDirectory(folderPath); // Ordner erstellen, falls nicht vorhanden
|
||||
}
|
||||
|
||||
// Generiere alle Kombinationen und exportiere das PDF
|
||||
foreach (var textPosition in textPositions)
|
||||
{
|
||||
foreach (var hasCorrectionLines in hasCorrectionLinesOptions)
|
||||
{
|
||||
foreach (var correctionMargin in correctionMargins)
|
||||
{
|
||||
foreach (var lineHeight in lineHeights)
|
||||
{
|
||||
// Dateiname basierend auf den aktuellen Parametern
|
||||
string fileName = $"{textPosition}_{hasCorrectionLines}_{correctionMargin}_{lineHeight}.pdf";
|
||||
string filePath = Path.Combine(folderPath, fileName);
|
||||
|
||||
// Erstelle das PDF für diese Kombination
|
||||
ExportToPdf(curr_exam,(int)correctionMargin,lineHeight, hasCorrectionLines,textPosition,filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user