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