]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/pdfwin.py
Patch from Andrea: fixes no page chang* events with mouse right click,
[wxWidgets.git] / wxPython / wx / lib / pdfwin.py
1 #----------------------------------------------------------------------
2 # Name: wx.lib.pdfwin
3 # Purpose: A class that allows the use of the Acrobat PDF reader
4 # ActiveX control
5 #
6 # Author: Robin Dunn
7 #
8 # Created: 22-March-2004
9 # RCS-ID: $Id$
10 # Copyright: (c) 2004 by Total Control Software
11 # Licence: wxWindows license
12 #----------------------------------------------------------------------
13
14 import wx
15
16 #----------------------------------------------------------------------
17
18 _acroversion = None
19
20 def get_acroversion():
21 " Return version of Adobe Acrobat executable or None"
22 global _acroversion
23 if _acroversion == None:
24 import _winreg
25 acrosoft = [r'SOFTWARE\Adobe\Acrobat Reader\%version%\InstallPath',
26 r'SOFTWARE\Adobe\Adobe Acrobat\%version%\InstallPath',]
27
28 for regkey in acrosoft:
29 for version in ('7.0', '6.0', '5.0', '4.0'):
30 try:
31 path = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE,
32 regkey.replace('%version%', version))
33 _acroversion = version
34 break
35 except:
36 continue
37 return _acroversion
38
39 #----------------------------------------------------------------------
40
41 # The ActiveX module from Acrobat 7.0 has changed and it seems to now
42 # require much more from the container than what our wx.activex module
43 # provides. If we try to use it via wx.activex then Acrobat crashes.
44 # So instead we will use Internet Explorer (via the win32com modules
45 # so we can use better dynamic dispatch) and embed the Acrobat control
46 # within that. Acrobat provides the IAcroAXDocShim COM class that is
47 # accessible via the IE window's Document property after a PDF file
48 # has been loaded.
49 #
50 # Details of the Acrobat reader methods can be found in
51 # http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACOverview.pdf
52 # http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACReference.pdf
53 #
54 # Co-ordinates passed as parameters are in points (1/72 inch).
55
56
57 if get_acroversion() >= '7.0':
58
59 from wx.lib.activexwrapper import MakeActiveXClass
60 import win32com.client.gencache
61 _browserModule = win32com.client.gencache.EnsureModule(
62 "{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 1)
63
64 class PDFWindowError(RuntimeError):
65 def __init__(self):
66 RuntimeError.__init__(self, "A PDF must be loaded before calling this method.")
67
68
69 class PDFWindow(wx.Panel):
70 def __init__(self, *args, **kw):
71 wx.Panel.__init__(self, *args, **kw)
72
73 # Make a new class that derives from the WebBrowser class
74 # in the COM module imported above. This class also
75 # derives from wxWindow and implements the machinery
76 # needed to integrate the two worlds.
77 _WebBrowserClass = MakeActiveXClass(_browserModule.WebBrowser)
78 self.ie = _WebBrowserClass(self, -1)
79 sizer = wx.BoxSizer()
80 sizer.Add(self.ie, 1, wx.EXPAND)
81 self.SetSizer(sizer)
82
83
84 def LoadFile(self, fileName):
85 """
86 Opens and displays the specified document within the browser.
87 """
88 if self.ie.Document:
89 return self.ie.Document.LoadFile(fileName)
90 else:
91 self.ie.Navigate2(fileName)
92 return True # can we sense failure at this point?
93
94 def GetVersions(self):
95 """
96 Deprecated: No longer available - do not use.
97 """
98 if self.ie.Document:
99 return self.ie.Document.GetVersions()
100 else:
101 raise PDFWindowError()
102
103 def Print(self):
104 """
105 Prints the document according to the specified options in a user dialog box.
106 """
107 if self.ie.Document:
108 return self.ie.Document.Print()
109 else:
110 raise PDFWindowError()
111
112 def goBackwardStack(self):
113 """
114 Goes to the previous view on the view stack, if it exists.
115 """
116 if self.ie.Document:
117 return self.ie.Document.goBackwardStack()
118 else:
119 raise PDFWindowError()
120
121 def goForwardStack(self):
122 """
123 Goes to the next view on the view stack, if it exists.
124 """
125 if self.ie.Document:
126 return self.ie.Document.goForwardStack()
127 else:
128 raise PDFWindowError()
129
130 def gotoFirstPage(self):
131 """
132 Goes to the first page in the document.
133 """
134 if self.ie.Document:
135 return self.ie.Document.gotoFirstPage()
136 else:
137 raise PDFWindowError()
138
139 def gotoLastPage(self):
140 """
141 Goes to the last page in the document.
142 """
143 if self.ie.Document:
144 return self.ie.Document.gotoLastPage()
145 else:
146 raise PDFWindowError()
147
148 def gotoNextPage(self):
149 """
150 Goes to the next page in the document, if it exists
151 """
152 if self.ie.Document:
153 return self.ie.Document.gotoNextPage()
154 else:
155 raise PDFWindowError()
156
157 def gotoPreviousPage(self):
158 """
159 Goes to the previous page in the document, if it exists.
160 """
161 if self.ie.Document:
162 return self.ie.Document.gotoPreviousPage()
163 else:
164 raise PDFWindowError()
165
166 def printAll(self):
167 """
168 Prints the entire document without displaying a user
169 dialog box. The current printer, page settings, and job
170 settings are used. This method returns immediately, even
171 if the printing has not completed.
172 """
173 if self.ie.Document:
174 return self.ie.Document.printAll()
175 else:
176 raise PDFWindowError()
177
178 def printAllFit(self, shrinkToFit):
179 """
180 Prints the entire document without a user dialog box, and
181 (if shrinkToFit) shrinks pages as needed to fit the
182 imageable area of a page in the printer.
183 """
184 if self.ie.Document:
185 return self.ie.Document.printAllFit(shrinkToFit)
186 else:
187 raise PDFWindowError()
188
189 def printPages(self, from_, to):
190 """
191 Prints the specified pages without displaying a user dialog box.
192 """
193 if self.ie.Document:
194 return self.ie.Document.printPages(from_, to)
195 else:
196 raise PDFWindowError()
197
198 def printPagesFit(self, from_, to, shrinkToFit):
199 """
200 Prints the specified pages without displaying a user
201 dialog box, and (if shrinkToFit) shrinks pages as needed
202 to fit the imageable area of a page in the printer.
203 """
204 if self.ie.Document:
205 return self.ie.Document.printPagesFit( from_, to, shrinkToFit)
206 else:
207 raise PDFWindowError()
208
209 def printWithDialog(self):
210 """
211 Prints the document according to the specified options in
212 a user dialog box. These options may include embedded
213 printing and specifying which printer is to be used.
214
215 NB. The page range in the dialog defaults to
216 'From Page 1 to 1' - Use Print() above instead. (dfh)
217 """
218 if self.ie.Document:
219 return self.ie.Document.printWithDialog()
220 else:
221 raise PDFWindowError()
222
223 def setCurrentHighlight(self, a, b, c, d):
224 if self.ie.Document:
225 return self.ie.Document.setCurrentHighlight(a, b, c, d)
226 else:
227 raise PDFWindowError()
228
229 def setCurrentPage(self, npage):
230 """
231 Goes to the specified page in the document. Maintains the
232 current location within the page and zoom level. npage is
233 the page number of the destination page. The first page
234 in a document is page 0.
235
236 ## Oh no it isn't! The first page is 1 (dfh)
237 """
238 if self.ie.Document:
239 return self.ie.Document.setCurrentPage(npage)
240 else:
241 raise PDFWindowError()
242
243 def setLayoutMode(self, layoutMode):
244 """
245 LayoutMode possible values:
246
247 ================= ====================================
248 'DontCare' use the current user preference
249 'SinglePage' use single page mode (as in pre-Acrobat
250 3.0 viewers)
251 'OneColumn' use one-column continuous mode
252 'TwoColumnLeft' use two-column continuous mode, first
253 page on the left
254 'TwoColumnRight' use two-column continuous mode, first
255 page on the right
256 ================= ====================================
257 """
258 if self.ie.Document:
259 return self.ie.Document.setLayoutMode(layoutMode)
260 else:
261 raise PDFWindowError()
262
263 def setNamedDest(self, namedDest):
264 """
265 Changes the page view to the named destination in the specified string.
266 """
267 if self.ie.Document:
268 return self.ie.Document.setNamedDest(namedDest)
269 else:
270 raise PDFWindowError()
271
272 def setPageMode(self, pageMode):
273 """
274 Sets the page mode to display the document only, or to
275 additionally display bookmarks or thumbnails. pageMode =
276 'none' or 'bookmarks' or 'thumbs'.
277
278 ## NB.'thumbs' is case-sensitive, the other are not (dfh)
279 """
280 if self.ie.Document:
281 return self.ie.Document.setPageMode(pageMode)
282 else:
283 raise PDFWindowError()
284
285 def setShowScrollbars(self, On):
286 """
287 Determines whether scrollbars will appear in the document
288 view.
289
290 ## NB. If scrollbars are off, the navigation tools disappear as well (dfh)
291 """
292 if self.ie.Document:
293 return self.ie.Document.setShowScrollbars(On)
294 else:
295 raise PDFWindowError()
296
297 def setShowToolbar(self, On):
298 """
299 Determines whether a toolbar will appear in the application.
300 """
301 if self.ie.Document:
302 return self.ie.Document.setShowToolbar(On)
303 else:
304 raise PDFWindowError()
305
306 def setView(self, viewMode):
307 """
308 Determines how the page will fit in the current view.
309 viewMode possible values:
310
311 ======== ==============================================
312 'Fit' fits whole page within the window both vertically
313 and horizontally.
314 'FitH' fits the width of the page within the window.
315 'FitV' fits the height of the page within the window.
316 'FitB' fits bounding box within the window both vertically
317 and horizontally.
318 'FitBH' fits the width of the bounding box within the window.
319 'FitBV' fits the height of the bounding box within the window.
320 ======== ==============================================
321 """
322 if self.ie.Document:
323 return self.ie.Document.setView(viewMode)
324 else:
325 raise PDFWindowError()
326
327 def setViewRect(self, left, top, width, height):
328 """
329 Sets the view rectangle according to the specified coordinates.
330
331 :param left: The upper left horizontal coordinate.
332 :param top: The vertical coordinate in the upper left corner.
333 :param width: The horizontal width of the rectangle.
334 :param height: The vertical height of the rectangle.
335 """
336 if self.ie.Document:
337 return self.ie.Document.setViewRect(left, top, width, height)
338 else:
339 raise PDFWindowError()
340
341 def setViewScroll(self, viewMode, offset):
342 """
343 Sets the view of a page according to the specified string.
344 Depending on the view mode, the page is either scrolled to
345 the right or scrolled down by the amount specified in
346 offset. Possible values of viewMode are as in setView
347 above. offset is the horizontal or vertical coordinate
348 positioned either at the left or top edge.
349 """
350 if self.ie.Document:
351 return self.ie.Document.setViewScroll(viewMode, offset)
352 else:
353 raise PDFWindowError()
354
355 def setZoom(self, percent):
356 """
357 Sets the magnification according to the specified value
358 expressed as a percentage (float)
359 """
360 if self.ie.Document:
361 return self.ie.Document.setZoom(percent)
362 else:
363 raise PDFWindowError()
364
365 def setZoomScroll(self, percent, left, top):
366 """
367 Sets the magnification according to the specified value,
368 and scrolls the page view both horizontally and vertically
369 according to the specified amounts.
370
371 :param left: the horizontal coordinate positioned at the left edge.
372 :param top: the vertical coordinate positioned at the top edge.
373 """
374 if self.ie.Document:
375 return self.ie.Document.setZoomScroll(percent, left, top)
376 else:
377 raise PDFWindowError()
378
379
380
381 else:
382 import wx.activex
383
384 clsID = '{CA8A9780-280D-11CF-A24D-444553540000}'
385 progID = 'AcroPDF.PDF.1'
386
387
388 # Create eventTypes and event binders
389 wxEVT_Error = wx.activex.RegisterActiveXEvent('OnError')
390 wxEVT_Message = wx.activex.RegisterActiveXEvent('OnMessage')
391
392 EVT_Error = wx.PyEventBinder(wxEVT_Error, 1)
393 EVT_Message = wx.PyEventBinder(wxEVT_Message, 1)
394
395
396 # Derive a new class from ActiveXWindow
397 class PDFWindow(wx.activex.ActiveXWindow):
398 def __init__(self, parent, ID=-1, pos=wx.DefaultPosition,
399 size=wx.DefaultSize, style=0, name='PDFWindow'):
400 wx.activex.ActiveXWindow.__init__(self, parent,
401 wx.activex.CLSID('{CA8A9780-280D-11CF-A24D-444553540000}'),
402 ID, pos, size, style, name)
403
404 # Methods exported by the ActiveX object
405 def QueryInterface(self, riid):
406 return self.CallAXMethod('QueryInterface', riid)
407
408 def AddRef(self):
409 return self.CallAXMethod('AddRef')
410
411 def Release(self):
412 return self.CallAXMethod('Release')
413
414 def GetTypeInfoCount(self):
415 return self.CallAXMethod('GetTypeInfoCount')
416
417 def GetTypeInfo(self, itinfo, lcid):
418 return self.CallAXMethod('GetTypeInfo', itinfo, lcid)
419
420 def GetIDsOfNames(self, riid, rgszNames, cNames, lcid):
421 return self.CallAXMethod('GetIDsOfNames', riid, rgszNames, cNames, lcid)
422
423 def Invoke(self, dispidMember, riid, lcid, wFlags, pdispparams):
424 return self.CallAXMethod('Invoke', dispidMember, riid, lcid, wFlags, pdispparams)
425
426 def LoadFile(self, fileName):
427 return self.CallAXMethod('LoadFile', fileName)
428
429 def setShowToolbar(self, On):
430 return self.CallAXMethod('setShowToolbar', On)
431
432 def gotoFirstPage(self):
433 return self.CallAXMethod('gotoFirstPage')
434
435 def gotoLastPage(self):
436 return self.CallAXMethod('gotoLastPage')
437
438 def gotoNextPage(self):
439 return self.CallAXMethod('gotoNextPage')
440
441 def gotoPreviousPage(self):
442 return self.CallAXMethod('gotoPreviousPage')
443
444 def setCurrentPage(self, n):
445 return self.CallAXMethod('setCurrentPage', n)
446
447 def goForwardStack(self):
448 return self.CallAXMethod('goForwardStack')
449
450 def goBackwardStack(self):
451 return self.CallAXMethod('goBackwardStack')
452
453 def setPageMode(self, pageMode):
454 return self.CallAXMethod('setPageMode', pageMode)
455
456 def setLayoutMode(self, layoutMode):
457 return self.CallAXMethod('setLayoutMode', layoutMode)
458
459 def setNamedDest(self, namedDest):
460 return self.CallAXMethod('setNamedDest', namedDest)
461
462 def Print(self):
463 return self.CallAXMethod('Print')
464
465 def printWithDialog(self):
466 return self.CallAXMethod('printWithDialog')
467
468 def setZoom(self, percent):
469 return self.CallAXMethod('setZoom', percent)
470
471 def setZoomScroll(self, percent, left, top):
472 return self.CallAXMethod('setZoomScroll', percent, left, top)
473
474 def setView(self, viewMode):
475 return self.CallAXMethod('setView', viewMode)
476
477 def setViewScroll(self, viewMode, offset):
478 return self.CallAXMethod('setViewScroll', viewMode, offset)
479
480 def setViewRect(self, left, top, width, height):
481 return self.CallAXMethod('setViewRect', left, top, width, height)
482
483 def printPages(self, from_, to):
484 return self.CallAXMethod('printPages', from_, to)
485
486 def printPagesFit(self, from_, to, shrinkToFit):
487 return self.CallAXMethod('printPagesFit', from_, to, shrinkToFit)
488
489 def printAll(self):
490 return self.CallAXMethod('printAll')
491
492 def printAllFit(self, shrinkToFit):
493 return self.CallAXMethod('printAllFit', shrinkToFit)
494
495 def setShowScrollbars(self, On):
496 return self.CallAXMethod('setShowScrollbars', On)
497
498 def GetVersions(self):
499 return self.CallAXMethod('GetVersions')
500
501 def setCurrentHighlight(self, a, b, c, d):
502 return self.CallAXMethod('setCurrentHighlight', a, b, c, d)
503
504 def postMessage(self, strArray):
505 return self.CallAXMethod('postMessage', strArray)
506
507 # Getters, Setters and properties
508 def _get_src(self):
509 return self.GetAXProp('src')
510 def _set_src(self, src):
511 self.SetAXProp('src', src)
512 src = property(_get_src, _set_src)
513
514 def _get_messageHandler(self):
515 return self.GetAXProp('messageHandler')
516 def _set_messageHandler(self, messageHandler):
517 self.SetAXProp('messageHandler', messageHandler)
518 messagehandler = property(_get_messageHandler, _set_messageHandler)
519
520
521 # PROPERTIES
522 # --------------------
523 # src
524 # type:string arg:string canGet:True canSet:True
525 #
526 # messagehandler
527 # type:VT_VARIANT arg:VT_VARIANT canGet:True canSet:True
528 #
529 #
530 #
531 #
532 # METHODS
533 # --------------------
534 # QueryInterface
535 # retType: VT_VOID
536 # params:
537 # riid
538 # in:True out:False optional:False type:unsupported type 29
539 # ppvObj
540 # in:False out:True optional:False type:unsupported type 26
541 #
542 # AddRef
543 # retType: int
544 #
545 # Release
546 # retType: int
547 #
548 # GetTypeInfoCount
549 # retType: VT_VOID
550 # params:
551 # pctinfo
552 # in:False out:True optional:False type:int
553 #
554 # GetTypeInfo
555 # retType: VT_VOID
556 # params:
557 # itinfo
558 # in:True out:False optional:False type:int
559 # lcid
560 # in:True out:False optional:False type:int
561 # pptinfo
562 # in:False out:True optional:False type:unsupported type 26
563 #
564 # GetIDsOfNames
565 # retType: VT_VOID
566 # params:
567 # riid
568 # in:True out:False optional:False type:unsupported type 29
569 # rgszNames
570 # in:True out:False optional:False type:unsupported type 26
571 # cNames
572 # in:True out:False optional:False type:int
573 # lcid
574 # in:True out:False optional:False type:int
575 # rgdispid
576 # in:False out:True optional:False type:int
577 #
578 # Invoke
579 # retType: VT_VOID
580 # params:
581 # dispidMember
582 # in:True out:False optional:False type:int
583 # riid
584 # in:True out:False optional:False type:unsupported type 29
585 # lcid
586 # in:True out:False optional:False type:int
587 # wFlags
588 # in:True out:False optional:False type:int
589 # pdispparams
590 # in:True out:False optional:False type:unsupported type 29
591 # pvarResult
592 # in:False out:True optional:False type:VT_VARIANT
593 # pexcepinfo
594 # in:False out:True optional:False type:unsupported type 29
595 # puArgErr
596 # in:False out:True optional:False type:int
597 #
598 # LoadFile
599 # retType: bool
600 # params:
601 # fileName
602 # in:True out:False optional:False type:string
603 #
604 # setShowToolbar
605 # retType: VT_VOID
606 # params:
607 # On
608 # in:True out:False optional:False type:bool
609 #
610 # gotoFirstPage
611 # retType: VT_VOID
612 #
613 # gotoLastPage
614 # retType: VT_VOID
615 #
616 # gotoNextPage
617 # retType: VT_VOID
618 #
619 # gotoPreviousPage
620 # retType: VT_VOID
621 #
622 # setCurrentPage
623 # retType: VT_VOID
624 # params:
625 # n
626 # in:True out:False optional:False type:int
627 #
628 # goForwardStack
629 # retType: VT_VOID
630 #
631 # goBackwardStack
632 # retType: VT_VOID
633 #
634 # setPageMode
635 # retType: VT_VOID
636 # params:
637 # pageMode
638 # in:True out:False optional:False type:string
639 #
640 # setLayoutMode
641 # retType: VT_VOID
642 # params:
643 # layoutMode
644 # in:True out:False optional:False type:string
645 #
646 # setNamedDest
647 # retType: VT_VOID
648 # params:
649 # namedDest
650 # in:True out:False optional:False type:string
651 #
652 # Print
653 # retType: VT_VOID
654 #
655 # printWithDialog
656 # retType: VT_VOID
657 #
658 # setZoom
659 # retType: VT_VOID
660 # params:
661 # percent
662 # in:True out:False optional:False type:double
663 #
664 # setZoomScroll
665 # retType: VT_VOID
666 # params:
667 # percent
668 # in:True out:False optional:False type:double
669 # left
670 # in:True out:False optional:False type:double
671 # top
672 # in:True out:False optional:False type:double
673 #
674 # setView
675 # retType: VT_VOID
676 # params:
677 # viewMode
678 # in:True out:False optional:False type:string
679 #
680 # setViewScroll
681 # retType: VT_VOID
682 # params:
683 # viewMode
684 # in:True out:False optional:False type:string
685 # offset
686 # in:True out:False optional:False type:double
687 #
688 # setViewRect
689 # retType: VT_VOID
690 # params:
691 # left
692 # in:True out:False optional:False type:double
693 # top
694 # in:True out:False optional:False type:double
695 # width
696 # in:True out:False optional:False type:double
697 # height
698 # in:True out:False optional:False type:double
699 #
700 # printPages
701 # retType: VT_VOID
702 # params:
703 # from
704 # in:True out:False optional:False type:int
705 # to
706 # in:True out:False optional:False type:int
707 #
708 # printPagesFit
709 # retType: VT_VOID
710 # params:
711 # from
712 # in:True out:False optional:False type:int
713 # to
714 # in:True out:False optional:False type:int
715 # shrinkToFit
716 # in:True out:False optional:False type:bool
717 #
718 # printAll
719 # retType: VT_VOID
720 #
721 # printAllFit
722 # retType: VT_VOID
723 # params:
724 # shrinkToFit
725 # in:True out:False optional:False type:bool
726 #
727 # setShowScrollbars
728 # retType: VT_VOID
729 # params:
730 # On
731 # in:True out:False optional:False type:bool
732 #
733 # GetVersions
734 # retType: VT_VARIANT
735 #
736 # setCurrentHightlight
737 # retType: VT_VOID
738 # params:
739 # a
740 # in:True out:False optional:False type:int
741 # b
742 # in:True out:False optional:False type:int
743 # c
744 # in:True out:False optional:False type:int
745 # d
746 # in:True out:False optional:False type:int
747 #
748 # setCurrentHighlight
749 # retType: VT_VOID
750 # params:
751 # a
752 # in:True out:False optional:False type:int
753 # b
754 # in:True out:False optional:False type:int
755 # c
756 # in:True out:False optional:False type:int
757 # d
758 # in:True out:False optional:False type:int
759 #
760 # postMessage
761 # retType: VT_VOID
762 # params:
763 # strArray
764 # in:True out:False optional:False type:VT_VARIANT
765 #
766 #
767 #
768 #
769 # EVENTS
770 # --------------------
771 # Error
772 # retType: VT_VOID
773 #
774 # Message
775 # retType: VT_VOID
776 #
777 #
778 #
779 #