Commit ce915e7

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2023-12-09 15:56:20
extract PdfConverter to dedicated class and update code
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent 17cccf9
Changed files (1)
lib
model
export_import
lib/model/export_import/pdf_converter.dart
@@ -0,0 +1,132 @@
+import 'dart:typed_data';
+import 'dart:ui';
+
+import 'package:blood_pressure_app/model/blood_pressure.dart';
+import 'package:blood_pressure_app/model/blood_pressure_analyzer.dart';
+import 'package:blood_pressure_app/model/storage/export_columns_store.dart';
+import 'package:blood_pressure_app/model/storage/export_pdf_settings_store.dart';
+import 'package:blood_pressure_app/model/storage/settings_store.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:intl/intl.dart';
+import 'package:pdf/pdf.dart';
+import 'package:pdf/widgets.dart' as pw;
+
+/// Utility class for creating pdf files.
+class PdfConverter {
+  /// Create pdf builder.
+  PdfConverter(this.pdfSettings, this.localizations, this.settings, this.availableColumns);
+
+  /// pdf specific settings.
+  final PdfExportSettings pdfSettings;
+  
+  /// General customised design information that can be applied to the Pdf.
+  final Settings settings;
+  
+  /// Strings in the pdf.
+  final AppLocalizations localizations;
+  
+  /// Columns manager used for ex- and import.
+  final ExportColumnsManager availableColumns;
+
+  /// Create a pdf from a record list.
+  Future<Uint8List> create(List<BloodPressureRecord> records) async {
+    pw.Document pdf = pw.Document();
+    final analyzer = BloodPressureAnalyser(records.toList());
+
+    pdf.addPage(pw.MultiPage(
+        pageFormat: PdfPageFormat.a4,
+        build: (pw.Context context) {
+          return [
+            if (pdfSettings.exportTitle)
+              _buildPdfTitle(records, analyzer),
+            if (pdfSettings.exportStatistics)
+              _buildPdfStatistics(analyzer),
+            if (pdfSettings.exportData)
+              _buildPdfTable(records),
+          ];
+        }));
+    return await pdf.save();
+  }
+
+  pw.Widget _buildPdfTitle(List<BloodPressureRecord> records, BloodPressureAnalyser analyzer) {
+    if (records.length < 2) return pw.Text(localizations.errNoData);
+    final dateFormatter = DateFormat(settings.dateFormatString);
+    return pw.Container(
+        child: pw.Text(
+            localizations.pdfDocumentTitle(
+                dateFormatter.format(analyzer.firstDay!),
+                dateFormatter.format(analyzer.lastDay!)
+            ),
+            style: const pw.TextStyle(
+              fontSize: 16,
+            )
+        )
+    );
+  }
+
+  pw.Widget _buildPdfStatistics(BloodPressureAnalyser analyzer) {
+    return pw.Container(
+      margin: const pw.EdgeInsets.all(20),
+      child: pw.TableHelper.fromTextArray(
+          data: [
+            ['',localizations.sysLong, localizations.diaLong, localizations.pulLong], // TODO: localizations.pulsePressure],
+            [localizations.average, analyzer.avgSys, analyzer.avgDia, analyzer.avgPul],
+            [localizations.maximum, analyzer.maxSys, analyzer.maxDia, analyzer.maxPul],
+            [localizations.minimum, analyzer.minSys, analyzer.minDia, analyzer.minPul],
+          ]
+      ),
+    );
+  }
+
+  pw.Widget _buildPdfTable(Iterable<BloodPressureRecord> records) {
+    final columns = pdfSettings.exportFieldsConfiguration.getActiveColumns(availableColumns);
+    
+    return pw.TableHelper.fromTextArray(
+      border: null,
+      cellAlignment: pw.Alignment.centerLeft,
+      headerDecoration: const pw.BoxDecoration(
+          border: pw.Border(bottom: pw.BorderSide(color: PdfColors.black))
+      ),
+      headerHeight: pdfSettings.headerHeight,
+      cellHeight: pdfSettings.cellHeight,
+      cellAlignments: { 
+        for (final v in List.generate(columns.length, (idx)=>idx)) 
+          v : pw.Alignment.centerLeft,
+      },
+      headerStyle: pw.TextStyle(
+        color: PdfColors.black,
+        fontSize: pdfSettings.headerFontSize,
+        fontWeight: pw.FontWeight.bold,
+      ),
+      cellStyle: pw.TextStyle(
+        fontSize: pdfSettings.cellFontSize,
+      ),
+      headerCellDecoration: pw.BoxDecoration(
+        border: pw.Border(
+          bottom: pw.BorderSide(
+            color: settings.accentColor.toPdfColor(),
+            width: 5,
+          ),
+        ),
+      ),
+      rowDecoration: const pw.BoxDecoration(
+        border: pw.Border(
+          bottom: pw.BorderSide(
+            color: PdfColors.blueGrey,
+            width: .5,
+          ),
+        ),
+      ),
+      headers: columns.map((c) => c.userTitle(localizations)).toList(),
+      data: records.map(
+              (record) => columns.map(
+                  (column) => column.encode(record)
+          ).toList()
+      ).toList(),
+    );
+  }
+}
+
+extension PdfCompatability on Color {
+  PdfColor toPdfColor() => PdfColor(red / 256, green / 256, blue / 256, opacity);
+}
\ No newline at end of file