Share My Creation PDFBoxWrapper Class Module - show PDF-document in B4J

PDFBoxWrapper is a Class Module that use PDFBox to view PDF-documents.

The PDFBoxWrapper Class module need a Pane and a layout to show the PDF-document in the Pane. The Pane and the name of the layout must be specified as parameters to the initialize routine of the class.
The layout must contain a ScrollPane named "myScrollPane".
The layout can also optional contain:
  • Spinner for scaleing the page ,named "SpinnerZoom"
  • Spinner turning pages, named "SpinnerPageNumber"
  • Button rotate pages 90degrees clockwise, named ButtonRotate
  • Label for showing loaded PDF-document named "LabelFileName"
PDFBox need to be referred in the Project Attributes Region:
B4X:
#AdditionalJar: pdfbox-app-2.0.14.jar
The file pdfbox-app-2.0.14.jar must be in the additional libraries folder

The PDFBoxWrapper Class module and a working layout for the PDF-viewer can be obtained from the attached Example project.

To use the attached example you have to download the pdfbox-app-2.0.14.jar https://pdfbox.apache.org/download.cgi#20x and place it in the additional libraries folder.

PDFBoxWrapperExampleScreenDump.png
 

Attachments

  • PDFBoxWrapperExample versjon 03032020.zip
    9 KB · Views: 1,013
Last edited:

knutf

Active Member
Licensed User
Longtime User
Just wondering if there is a way to get the x and y coordinates in the pdf-document where I release the mouse (using the myScrollPane_MouseReleased event)

I've made some changes / additions to the pdfBoxWrapper that hopefully will help you:

The imageViews that contains the rendered PDF-pages has got an event name and also the page number in the tag:
B4X:
        For i = 0 To getNumberOfPages - 1
            Dim rect As PDFrectangle = getPageSizeInPixels(i,myZoom)
            rect.imv.Initialize("PageRect")
            rect.imv.Tag = i

I have added a sub that returns the coordinate system of a given PDF-page:
B4X:
'Gives the MediaBox of the page
'A rectangle, expressed in default user space units, defining the boundaries of the physical medium on which the page is intended to be displayed or printed.
'Returns a PDFrectangle where:
'   .x and .y is lower left corner of the page
'   .height and .width is the height and width of the MadiaBox
Public Sub getMediaBox(p As Int) As PDFrectangle
    Dim pg As JavaObject = thisDoc.RunMethodJO("getPage",Array(p))
    Dim r As PDFrectangle
    r.Initialize
    Dim mb As JavaObject = pg.RunMethodJO("getMediaBox",Null)
    If getRotationAngle(p) Mod 180 = 0 Then
        r.height = mb.RunMethod("getHeight",Null)
        r.width = mb.RunMethod("getWidth",Null)
        r.x = mb.RunMethod("getLowerLeftX",Null)
        r.y = mb.RunMethod("getLowerLeftY",Null)
    Else
        r.height = mb.RunMethod("getWidth",Null)
        r.width = mb.RunMethod("getHeight",Null)
        r.y = mb.RunMethod("getLowerLeftX",Null)
        r.x = mb.RunMethod("getLowerLeftY",Null)
    End If
    Return r
End Sub

And I have also added a sub that calculate the mouse position relative to a PDF document coordinate system:
B4X:
'Calculate the mouse position relative to PDF document MediaBox
'    ED:        The EventData passed to the mouse event
'    IV:        The ImageView receiving the mouse event (sender)
'Returns a PDFrectangle where
'    .index is page number
'    .x and .y is the mouse position relative to the PDF-page
'        x is increased when mouse goes from left to right on the page
'        y is increased when mouse gous from top to down on the page
Private Sub getMousePositionInPage(ED As MouseEvent,IV As ImageView) As PDFrectangle
    Dim IV As ImageView = Sender
    Dim Position As PDFrectangle
    Position.index = IV.Tag
    Dim pageRect As PDFrectangle = PagesRects.Get(Position.index)
    Dim mediaBox As PDFrectangle = getMediaBox(Position.index)
    Position.x = ED.X * mediaBox.width / (pageRect.width - LeftRightSpace * 2)' + mediaBox.x
    Position.y = mediaBox.height - ED.y * mediaBox.height / (pageRect.Height - pageSpace) + mediaBox.y
    Return Position
End Sub

You can use it in any mouse event. In the attached example it is used in a MouseMoved event to show the mouse position in PDF page in the log
B4X:
Private Sub PageRect_MouseMoved (EventData As MouseEvent)
    Log(getMousePositionInPage(EventData,Sender))
End Sub

I have not tested this with the PDFBox drawImage methode, but I think the coordinates the sub getMousePositionInPage returns will position the image correctly on the page. Please let me know whether it works or not!
 

Attachments

  • ShowPDFinB4J version 22032020.zip
    9.5 KB · Views: 450

moster67

Expert
Licensed User
Longtime User
Many thanks for your help. It would have taken me ages...

The only change I made was in your "getMousePositionInPage" sub where I changed the position.y statement as follows:
B4X:
'Position.y = mediaBox.height - ED.y * mediaBox.height / (pageRect.Height - pageSpace) + mediaBox.y   
Position.y = ED.y * mediaBox.height / (pageRect.Height - pageSpace) + mediaBox.y
so it will return the position.y-value showing y=0 at the top of the page.

Now I should be in a position to carry on.

Once again many thanks for sharing this project and for your help.
 

knutf

Active Member
Licensed User
Longtime User
so it will return the position.y-value showing y=0 at the top of the page.
Are you sure that the y-value should be 0 at the top of the page The mediaBox returned from PDFBox library has a member
LowerLeftY = 0. You are planning to use the drawImage methode of the PDFBox library, and I think it use the same coordinate system as indicated by the mediaBox
 

moster67

Expert
Licensed User
Longtime User
Are you sure that the y-value should be 0 at the top of the page
Not sure at all :)
I still have to test it with the drawImage method of PDFBox but I got busy with my normal job. I hope to continue today.
Anyway, I only assumed, y-value would be top at the page since it is quite common in other image operations. I will find out soon enough and besides, you already provided the correct way to get LowerLeftY if you are correct (which you probably are).
 

moster67

Expert
Licensed User
Longtime User
@knutf
You were right - it uses the same coordinate system as indicated by the mediaBox
Thanks for that.
 

james_sgp

Active Member
Licensed User
Longtime User
Hi, would i be able to open a protected PDF using PDFBox (i.e the is a password to view the PDF)?

James
 

peacemaker

Expert
Licensed User
Longtime User
Just for ref some code for autoscaling the PDF:

B4X:
Sub B4XPage_Resize (Width As Int, Height As Int)
    Dim value As Float = Width / Main.fx.PrimaryScreen.MaxX * 100 * 1.5
    PDF.Repaint(PDF.StringZoomToFloat(value))
End Sub
 
Top