Table of Contents

23.12.5 PDF reader project

This chapter presents a tried and tested project. It enables the selection and display of a PDF file. The project uses the gb.poppler component.

The project 'PDF-Reader' has the following functionality:

BILD1

Figure 23.12.5.1: Programme interface PDF reader with search text

BILD2

Figure 23.12.5.2: Programme interface with display of the location coordinates

BILD3

Figure 23.12.5.3: Programme interface with display of properties of the PDF document

23.12.5.1 Source code (extracts) for the PDF reader project

The project focussed on investigating the Gambas component gb.poppler. It helped to fix bugs and shortcomings of this new component, which replaces the outdated gb.pdf component. The presented project is far from being a complete PDF viewer. However, it can be helpful when working with the component for the first time.

The project source code is freely available to anyone and for any type of use.

BILD4

Figure 23.12.5.1.1: Programme interface with dual navigation

Navigation through the individual pages of the document takes place via a thumbnail selection (A) or via a selection from the table of contents (B) - if it is available. If there is no table of contents, the content of the ComboBox only consists of an entry for the thumbnail selection (A) - see Figure 23.12.5.1 Programme interface PDF reader with search text. If the PDF file already contains thumbnails, these are displayed instead of the self-generated thumbnails, which is usually faster.

The project contains special PDF files that can be loaded for test and demonstration purposes via the file selection dialogue.

The following section introduces navigation in the PDF document via a table of contents and navigation via thumbnails:

    [1] Public Sub LoadPdf(PdfDocPath As String, Optional ExpandParent As Boolean = False)
    [2]
    [3]     FMain.Caption = ("PDF-File: ") & File.Name(pdfDocPath)
    [4]
    [5]     hPdfDocument = Null
    [6]     Try hPdfDocument = New PdfDocument(PdfDocPath)
    [7]
    [8]     If Error Then
    [9]        Message.Error("Couldn't load file.")
    [10]        Return
    [11]     Endif
    [12]
    [13]     hPdfDocument.Antialiasing = True         '-- Use Antialiasing
    [14]     hPdfDocument.textAntialiasing = True     '-- Use Antialiasing for text
    [15]     DocumentView1.Column = 1                 '-- To initially display a page at full width
    [16]     DocumentView1.Count = hPdfDocument.Count
    [17] '-- Because DocumentView1.Count = hPdfDocument.Count draws the document only at the first
    [18]     DocumentView1.Refresh()
    [19]
    [20]     CreateThumbnails()
    [21]     ShowIndex(True)
    [22]
    [23]
    [24] End

Comment

Source code CreateThumbnails():

    [1] Public Sub CreateThumbnails()
    [2]
    [3]     Dim hImage, hThumbnail As New Image
    [4]     Dim i As Integer
    [5]     Dim fFactor As Float = 0.10
    [6]
    [7]     ListViewPages.Expand = True
    [8]     ListViewPages.Clear()
    [9]
    [10]     For i = 0 To hPdfDocument.Max
    [11]     '-- Try reading embedded thumbnails first
    [12]         hThumbnail = hPdfDocument[i].Thumbnail
    [13]     '-- Make a thumbnail if no embedded thumbnail is available
    [14]         If IsNull(hThumbnail) Then
    [15]             hImage = hPdfDocument[i].Render(,,,,, 10)
    [16]             hThumbnail = hImage.Stretch(hPdfDocument[i].W * fFactor, hPdfDocument[i].H * fFactor)
    [17]         End If
    [18]         Paint.Begin(hThumbnail)
    [19]            Paint.LineWidth = 1
    [20]            Paint.Brush = Paint.Color(color.Black)
    [21]            Paint.Rectangle(0, 0, hThumbnail.W, hThumbnail.H)
    [22]            Paint.Stroke()
    [23]         Paint.End()
    [24]
    [25]     '-- Label instead of index+1, because the page labels of PDFs can be changed.
    [26]     '-- XViewer also shows the page label.
    [27]         ListViewPages.Add(i, hPdfDocument[i].Label, hThumbnail.Picture)
    [28]     Next
    [29]
    [30]     ListViewPages[0].Selected = True
    [31]
    [32] End

Source code ShowIndex(Optional ExpandParent As Boolean = False)

    [1] Public Sub ShowIndex(Optional ExpandParent As Boolean = False)
    [2]
    [3]     Dim hPdfIndex As PdfIndex
    [4]     Dim i, iLastParent As Integer
    [5]     Dim sIndexText As String
    [6]
    [7]     Dim pic, hpic As Picture
    [8]
    [9]     TreeViewIndex.Expand = True
    [10]     TreeViewIndex.Clear()
    [11]
    [12]     cCollection.Clear()
    [13]
    [14] '-- Load TreeView with table of contents
    [15]     If hPdfDocument.Index.Count > 0 Then
    [16]        ComboBoxSelectMode.Clear()
    [17]        ComboBoxSelectMode.Add("Index & Thumbnail")
    [18]        ComboBoxSelectMode.Add("Thumbnail")
    [19]        ComboBoxSelectMode.Add("Index")
    [20]        ComboBoxSelectMode.Index = 0
    [21]        TreeViewIndex.Visible = True
    [22]        For Each hPdfIndex In hPdfDocument.Index
    [23]            sIndexText = Trim(hPdfIndex.Text)
    [24]            hpic = Null
    [25]        '-- Dummy picture (required to use the paint methods)
    [26]            hpic = New Picture(1, 1)
    [27]            Paint.Begin(hpic)
    [28]              Paint.Font = TreeViewIndex.font
    [29]              pic = Null
    [30]          '-- Generate an invisible pic which enlarges the treeview line if required
    [31]              pic = New Picture(1, Paint.TextSize(sIndexText).H, True)
    [32]            Paint.End()
    [33]
    [34]        '-- Root item?
    [35]            If hPdfIndex.Parent = -1 Then
    [36]               TreeViewIndex.Add(i, sIndexText, pic)
    [37]               iLastParent = i
    [38]           '-- Expand the node
    [39]               TreeViewIndex[i].Expanded = ExpandParent
    [40]        '-- Non-Root parent item?
    [41]            Else If hPdfIndex.Children > 0 Then
    [42]               TreeViewIndex.Add(i, sIndexText, pic, hPdfIndex.Parent)
    [43]               iLastParent = i
    [44]               TreeViewIndex[i].Expanded = ExpandParent  '-- Expand the node ...
    [45]            Else                                         '-- Child item?
    [46]               TreeViewIndex.Add(i, sIndexText, pic, iLastParent)
    [47]            Endif
    [48]        '-- Put it into a collection to make the page accessable from the treeview
    [49]            cCollection.Add(hPdfIndex.Action.Goto.Page, i)
    [50]            Inc i
    [51]        Next
    [52]     Else
    [53]        ComboBoxSelectMode.Clear()
    [54]        ComboBoxSelectMode.Add("Thumbnail")
    [55]        ComboBoxSelectMode.Index = 0
    [56]        TreeViewIndex.Visible = False
    [57]     Endif
    [58]
    [59] End

The following two event handlers complete the navigation and provide the option of displaying a specific PDF page in the DocumentView:

    [1] Public Sub TreeViewIndex_Click()
    [2]
    [3]   DocumentView1.Goto(cCollection[TreeViewIndex.Current.Key] - 1)
    [4]   iFirstVisiblePage = cCollection[TreeViewIndex.Current.Key] - 1
    [5]
    [6] End
    [7]
    [8] ...
    [9]
    [10] Public Sub ListViewPages_Select()
    [11]
    [12]    DocumentView1.Goto(ListViewPages.Current.Key)
    [13]
    [14] End

In the download area you will find the source code of the PDF Reader project as a source code archive as well as sample PDF files.

Download

Project

Download