wxWidgets / Phoenix

wxPython's Project Phoenix. A new implementation of wxPython, better, stronger, faster than he was before.
http://wxpython.org/
2.29k stars 515 forks source link

pdfViewer.xpageoffset is erroneously set under certain scrolling conditions #1004

Open geoflipman opened 6 years ago

geoflipman commented 6 years ago

Operating system: Windows 10 wxPython version & source: 4.0.3, I think source was pypi Python version & source: 2.7.13, stock

Description of the problem: pdfViewer.xpageoffset is erroneously set under certain scrolling conditions. Under these conditions the left side of the PDF page cannot be seen in the viewer window even when scrolling to the left. I have tried this with 3 different pdfs, under 3 different zoom levels,

Steps to reproduce: This bug can be reproduced by running the demo viewer: https://github.com/wxWidgets/Phoenix/blob/master/demo/PDFViewer.py But I have also included code that more easily shows the problem below

  1. load multipage pdf, with zoom such that the x scroll bar is active
    • at this point, xpageoffset = 0
  2. scroll to the right (positive x direction) any number of increments
  3. now scroll DOWN until a page gap is in the view window
    • at this point, xpageoffset will be set to (-1 numberofscrollincrements scrollincrementsize)
  4. xpageoffset is reset to 0 by scrolling 100% left, then changing pages (gap is visible in viewer window)

The example below demonstrates the problem. Left-double-click in the window to print current value of xpageoffset. The last line in OnLoadButton is a convenient place to set the zoom level.

#!/usr/bin/env python

import wx
import sys
import os

try:
    from wx.lib.pdfviewer import pdfViewer, pdfButtonPanel
    havePyPdf = True
except ImportError:
    havePyPdf = False

########################################################################
class PanelPDF(wx.Panel):

    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent=parent, size=(810,500))

        hsizer = wx.BoxSizer(wx.HORIZONTAL)
        vsizer = wx.BoxSizer(wx.VERTICAL)
        self.viewer = pdfViewer(self, wx.NewId(), wx.DefaultPosition, wx.DefaultSize, wx.HSCROLL|wx.VSCROLL|wx.SUNKEN_BORDER)
        vsizer.Add(self.viewer, 1, wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM, 5)
        loadbutton = wx.Button(self, wx.NewId(), "Load PDF file", wx.DefaultPosition, wx.DefaultSize, 0 )
        vsizer.Add(loadbutton, 0, wx.ALIGN_CENTER|wx.ALL, 5)
        hsizer.Add(vsizer, 1, wx.GROW|wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5)
        self.SetSizer(hsizer)
        self.SetAutoLayout(True)

        self.Bind(wx.EVT_BUTTON, self.OnLoadButton, loadbutton)
        self.viewer.Bind(wx.EVT_LEFT_DCLICK, self.OnLDclick)

    def OnLDclick(self, evt):
        xpageoffset = self.viewer.xpageoffset
        print("xpageoffset: ", xpageoffset)
        return()

    def OnLoadButton(self, event):
        dlg = wx.FileDialog(self, wildcard="*.pdf")
        if dlg.ShowModal() == wx.ID_OK:
            wx.BeginBusyCursor()
            self.viewer.LoadFile(dlg.GetPath())
            wx.EndBusyCursor()
        dlg.Destroy()
        self.viewer.SetZoom(1.5)  ##set zoom to whatever

########################################################################
class MyForm(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "test frame", size=(810,500))

        self.panel_1 = PanelPDF(self)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.panel_1, 1, wx.EXPAND)

        self.SetSizer(self.sizer)

########################################################################
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()

I'm guessing the problem starts here:

https://github.com/wxWidgets/Phoenix/blob/d49953b7cd12eec1689382c81fd7ea9460ebe20b/wx/lib/pdfviewer/viewer.py#L422

geoflipman commented 6 years ago

I don't understand this library very deeply, but changing line 422 to self.xpageoffset = 0 solves the problem for the cases I have looked at.

david-hughes commented 5 years ago

Yes you are right. It works correctly in wxPython Classic but some changes I made around September 2016 to remove the cacheing of rendered pages meant that for some reason self.xpageoffset should now always be zero. I will submit a pull request to fix this, thanks.