EvaluationReportRenderer.cs 9.81 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
using PDFGenerator.EvaluationReport;
using PDFGenerator.Utilities;
using System.Collections.Generic;
using System.IO;
using static PDFGenerator.Utilities.Globals.Constants;

namespace PDFGenerator.Renderers
{
    public class EvaluationReportRenderer : IRenderer
    {
        private Document Document { get; set; }
        private PdfWriter PdfWriter { get; set; }
        private MemoryStream MemoryStream { get; set; }
        private int PageBeforeTOC { get; set; }
        private int AppendixStart { get; set; }
        private Appendix Appendix { get; set; }
        private Bookmarks Bookmarks { get; }
        private TableOfContents TableOfContents { get; }

        private PDFGenerator.Models.EvaluationReport EvaluationReport { get; }

        public EvaluationReportRenderer(PDFGenerator.Models.EvaluationReport evaluationReport)
        {
            EvaluationReport = evaluationReport;

Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
32
            // open PDF document in write mode
33
34
35
            MemoryStream = new MemoryStream();
            PdfWriter = new PdfWriter(MemoryStream);

Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
36
            // initialize PDF document
37
38
39
40
41
            PdfDocument pdfDocument = new PdfDocument(PdfWriter);

            // change the page mode so that the bookmarks panel is opened by default
            pdfDocument.GetCatalog().SetPageMode(PdfName.UseOutlines);

Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
42
            // create document to add new elements
43
44
45
46
47
48
49
50
51
52
            Document = new Document(pdfDocument, PageSize.A4);
            Document.SetMargins(Margins.Top_Margin, Margins.Right_Margin, Margins.Bottom_Margin, Margins.Left_Margin);

            Bookmarks = new Bookmarks();
            TableOfContents = new TableOfContents(Document);

            Appendix = new Appendix(EvaluationReport.Appendix, Document, Bookmarks, TableOfContents);
        }

        /// <summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
53
        /// Renders all sections for the evaluation report, reorders pages in the document and adds a header to it.
54
        /// </summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
55
        /// <returns>The generated PDF document as byte array.</returns>
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
        public byte[] Render()
        {
            RenderSections();
            Document.Close();

            try
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    MoveTocToFront(memoryStream);
                    return memoryStream.ToArray();
                }
            }
            finally
            {
                MemoryStream.Dispose();
            }
        }

        /// <summary>
        /// Renders all sections for the evaluation report.
        /// </summary>
        private void RenderSections()
        {
            RenderCover();
            RenderPreface();
            RenderCourseInformationTables();
            RenderCourseGeneralInformation();
            RenderEvaluationResults();
            RenderAppendix();
            RenderTableOfContents();
        }

        /// <summary>
        /// Renders the cover section.
        /// </summary>
        private void RenderCover()
        {
            new Cover(EvaluationReport.Cover, Document, Bookmarks, TableOfContents)
            .Render();
        }

        /// <summary>
        /// Renders the preface section.
        /// </summary>
        private void RenderPreface()
        {
            new Preface(EvaluationReport.Preface, Document, Bookmarks, TableOfContents)
            .Render();
        }

        /// <summary>
        /// Renders the table of contents section.
        /// </summary>
        private void RenderTableOfContents()
        {
            TableOfContents.Render(AppendixStart);
        }

        /// <summary>
        /// Renders the section regarding the tabular overview of course information.
        /// </summary>
        private void RenderCourseInformationTables()
        {
            new CourseInformationTables(EvaluationReport.CourseInformationTables, Document, Bookmarks, TableOfContents)
            .Render();
        }

        /// <summary>
        /// Renders the section regarding further course general information.
        /// </summary>
        private void RenderCourseGeneralInformation()
        {
            CourseGeneralInformation courseGeneralInformation = new CourseGeneralInformation(
                EvaluationReport.CourseGeneralInformation, Document, Bookmarks, TableOfContents
            );

            courseGeneralInformation.Render();

            Appendix.UpdateAppendix(courseGeneralInformation.CustomUploads);
        }

        /// <summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
139
        /// Renders the section regarding the assessment of criterion targets and kpis.
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
        /// </summary>
        private void RenderEvaluationResults()
        {
            EvaluationResults evaluationResults = new EvaluationResults(EvaluationReport.EvaluationResults, Document, Bookmarks, TableOfContents);
            evaluationResults.Render();

            Appendix.UpdateAppendix(evaluationResults.CustomUploads);
        }

        /// <summary>
        /// Renders the appendix section.
        /// </summary>
        private void RenderAppendix()
        {
            AppendixStart = Document.GetPdfDocument().GetNumberOfPages();
            Appendix.Render();

            PageBeforeTOC = Document.GetPdfDocument().GetNumberOfPages();
            Appendix.AddPageBreak();
        }

        /// <summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
162
        /// Moves the table of contents directly after the cover and adds document header.
163
        /// </summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
164
        /// <param name="memoryStream">The PDF document to apply the changes on.</param>
165
166
167
168
169
170
171
        private void MoveTocToFront(MemoryStream memoryStream)
        {
            PdfReader pdfReader = new PdfReader(new MemoryStream(MemoryStream.ToArray()));
            PdfDocument sourceDocument = new PdfDocument(pdfReader);
            PdfDocument resultDocument = new PdfDocument(new PdfWriter(memoryStream));

            // the first page of a PdfDocument is 1
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
172
            // exclude appendix start page as last page if there are no attachments
173
            int firstPage = 1;
174
            int lastPage = EvaluationReport.Appendix.Attachments.Count > 0 ? PageBeforeTOC : PageBeforeTOC - 1;
175

Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
176
177
178
            // this method should be called to preserve the outlines of the source pdf file
            // otherwise they will be absent in the reusulting document to which pages are copied

179
            // initializes an outline tree of the document and sets outline mode to true:
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
180
            // the method will read the whole document and create the outline tree
181
182
            resultDocument.InitializeOutlines();

Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
183
            // reorders 'cover > chapters > toc' to 'cover > toc > chapters' 
184
185
186
187
188
            List<int> reorderedPages = new List<int> { firstPage };
            for (int i = PageBeforeTOC + 1; i <= PageBeforeTOC + TableOfContents.TocPages; i++)
            {
                reorderedPages.Add(i);
            }
189
            for (int i = firstPage + 1; i <= lastPage; i++)
190
191
192
193
194
195
196
            {
                reorderedPages.Add(i);
            }

            sourceDocument.CopyPagesTo(reorderedPages, resultDocument);
            sourceDocument.Close();

Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
197
            // add page numbers
198
199
200
201
202
203
204
            AddHeader(resultDocument);
            resultDocument.Close();
        }

        /// <summary>
        /// Adds a header to the document.
        /// </summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
205
        /// <param name="pdfDocument">The PDF document.</param>
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
        private void AddHeader(PdfDocument pdfDocument)
        {
            Document document = new Document(pdfDocument);
            Rectangle ps;

            int firstPage = 1;
            int n = pdfDocument.GetNumberOfPages();

            string textLeft;
            string textRight;
            string pageNumber;

            // header for cover excluded
            for (int i = firstPage + 1; i <= n; i++)
            {
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
221
                // get page by the page number
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
                ps = pdfDocument.GetPage(i).GetPageSizeWithRotation();

                float height = ps.GetHeight();
                float width = ps.GetWidth();

                pageNumber = i < (AppendixStart + TableOfContents.TocPages) ?
                    i.ToString() :
                    TableOfContents.ToRoman(i + 1 - AppendixStart - TableOfContents.TocPages);

                if (i % 2 == 0)
                {
                    textLeft = pageNumber;
                    textRight = "Evaluationsbericht";
                }
                else
                {
                    textLeft = "Evaluationsbericht";
                    textRight = pageNumber;
                }

                document.ShowTextAligned(
                        new Paragraph(new Text(textLeft).AddStyle(Styles.Small)).SetFixedLeading(0),
                        Margins.Left_Margin,
                        height - 31.1f,
                        i,
                        TextAlignment.LEFT,
                        VerticalAlignment.TOP,
                        0
                    );

                document.ShowTextAligned(
                    new Paragraph(new Text(textRight).AddStyle(Styles.Small)).SetFixedLeading(0),
                    width - Margins.Right_Margin,
                    height - 31.1f,
                    i,
                    TextAlignment.RIGHT,
                    VerticalAlignment.TOP,
                    0
                );

                // canvas is used for drawing a reactangle with a very small height (0.5f) just to simulate a line as boundary to the header
                // directly below the 'Evaluationsbericht' expression and page number
                PdfPage pdfPage = pdfDocument.GetPage(i);
                PdfCanvas canvas = new PdfCanvas(pdfPage.GetLastContentStream(), pdfPage.GetResources(), pdfDocument);
                canvas.Rectangle(new Rectangle(Margins.Left_Margin, height - 48.7f, width - Margins.Right_Margin - Margins.Left_Margin, 0.5f))
                .Fill();
            }
        }
    }
}