TableOfContents.cs 6.44 KB
Newer Older
1
2
3
4
5
6
7
8
9
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Action;
using iText.Kernel.Pdf.Canvas.Draw;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
using System.Collections.Generic;
using System.IO;
10
using Styles = PDFGenerator.Utilities.Globals.Constants.EvaluationReport.Styles;
11

12
namespace PDFGenerator.DocumentStructures.EvaluationReport
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
    public struct TocItem
    {
        public string Title { get; set; }
        public int Indent { get; set; }
        public int Page { get; set; }
    }

    public class TableOfContents
    {
        private List<TocItem> TocItems { get; set; }
        public int TocPages { get; private set; }
        private Document Document { get; }

        public TableOfContents(Document document)
        {
            TocItems = new List<TocItem>();
            Document = document;
        }

        /// <summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
34
        /// Adds a new item to the table of contents item list.
35
        /// </summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
36
        /// <param name="item">Item to add the table of contents item list.</param>
37
38
39
40
41
42
43
44
        public void AddToTOC(TocItem item)
        {
            TocItems.Add(item);
        }

        /// <summary>
        /// Renders the content for the table of contents.
        /// </summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
45
        /// <param name="appendixStart">The page number for the beginning of appendix.</param>
46
47
48
49
50
51
52
53
54
55
        public void Render(int appendixStart)
        {
            TocPages = NumerOfPagesForTOC(appendixStart);

            AddTOC(Document, appendixStart);
        }

        /// <summary>
        /// Determines the number of pages for rendering the table of contents.
        /// </summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
56
        /// <param name="appendixStart">The page number for the beginning of appendix.</param>
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
        /// <returns></returns>
        private int NumerOfPagesForTOC(int appendixStart)
        {
            int pages = 0;
            using (MemoryStream memoryStream = new MemoryStream())
            {
                PdfWriter writer = new PdfWriter(memoryStream);
                PdfDocument pdfDocument = new PdfDocument(writer);
                PageSize pageSize = Document.GetPdfDocument().GetDefaultPageSize();

                Document document = new Document(pdfDocument, pageSize);
                document.SetMargins(
                    Document.GetTopMargin(),
                    Document.GetRightMargin(),
                    Document.GetBottomMargin(),
                    Document.GetLeftMargin()
                );

                AddTOC(document, appendixStart);
                pages = document.GetPdfDocument().GetNumberOfPages();
                document.Close();
            }

            return pages;
        }

        /// <summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
84
        /// Adds the table of contents to the document.
85
        /// </summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
86
87
        /// <param name="document">The PDF document.</param>
        /// <param name="appendixStart">The page number for the beginning of appendix.</param>
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
        private void AddTOC(Document document, int appendixStart)
        {
            Paragraph paragraph = new Paragraph(new Text("Inhaltsverzeichnis").AddStyle(Styles.H1)).SetMarginBottom(20f);
            document.Add(paragraph);

            float width = document.GetPdfDocument().GetDefaultPageSize().GetWidth();
            TabStop tabStop = new TabStop(width, TabAlignment.RIGHT, new DottedLine());  // maximal document width exclusive margin

            foreach (TocItem item in TocItems)
            {
                Text title = new Text(item.Title);
                Text page = item.Page < appendixStart ? new Text("\t" + (TocPages + item.Page)) : new Text("\t" + ToRoman(item.Page + 1 - appendixStart));

                if (item.Indent == 0)
                {
                    title.AddStyle(Styles.H3);
                    page.AddStyle(Styles.H3);

                    paragraph = new Paragraph()
                    .AddTabStops(tabStop)
                    .Add(title)
                    .Add(new Tab())
                    .Add(page)
                    .SetAction(PdfAction.CreateGoTo(item.Title))
                    .SetMarginTop(10f);

                    document.Add(paragraph);
                    continue;
                }

                title.AddStyle(Styles.Paragraph);
                page.AddStyle(Styles.Paragraph);

                paragraph = new Paragraph()
                    .AddTabStops(tabStop)
                    .Add(title)
                    .Add(new Tab())
                    .Add(page)
                    .SetAction(PdfAction.CreateGoTo(item.Title))
                    .SetMarginTop(-1.43f)
                    .SetMarginLeft(17f * item.Indent)
                    .SetMultipliedLeading(1.4f);

                document.Add(paragraph);
            }
        }

        /// <summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
136
        /// Converts a number to roman numerals.
137
        /// </summary>
Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
138
139
        /// <param name="number">Page number to convert.</param>
        /// <returns>The converted number in roman numerals.</returns>
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
        public static string ToRoman(int number)
        {
            if (number >= 1000)
            {
                return "m" + ToRoman(number - 1000);
            }

            if (number >= 900)
            {
                return "cm" + ToRoman(number - 900);
            }

            if (number >= 500)
            {
                return "d" + ToRoman(number - 500);
            }

            if (number >= 400)
            {
                return "cd" + ToRoman(number - 400);
            }

            if (number >= 100)
            {
                return "c" + ToRoman(number - 100);
            }

            if (number >= 90)
            {
                return "xc" + ToRoman(number - 90);
            }

            if (number >= 50)
            {
                return "l" + ToRoman(number - 50);
            }

            if (number >= 40)
            {
                return "xl" + ToRoman(number - 40);
            }

            if (number >= 10)
            {
                return "x" + ToRoman(number - 10);
            }

            if (number >= 9)
            {
                return "ix" + ToRoman(number - 9);
            }

            if (number >= 5)
            {
                return "v" + ToRoman(number - 5);
            }

            if (number >= 4)
            {
                return "iv" + ToRoman(number - 4);
            }

            if (number >= 1)
            {
                return "i" + ToRoman(number - 1);
            }

Sebastian Drenckberg's avatar
Sebastian Drenckberg committed
207
            // if number < 1
208
209
210
211
            return string.Empty;
        }
    }
}