from AppKit import *
from Quartz import *
import objc
from PyObjCTools import NibClassBuilder
class MyPDFDocument (NibClassBuilder.AutoBaseClass):
_outline = objc.ivar()
_searchResults = objc.ivar()
def dealloc(self):
NSNotificationCenter.defaultCenter().removeObserver_(self)
self._searchResults = None
super(MyPDFDocument, self).dealloc()
def windowNibName(self):
return "MyDocument"
def windowControllerDidLoadNib_(self, controller):
super(MyPDFDocument, self).windowControllerDidLoadNib_(controller)
if self.fileName():
pdfDoc = PDFDocument.alloc().initWithURL_(
NSURL.fileURLWithPath_(self.fileName()))
self._pdfView.setDocument_(pdfDoc)
# Page changed notification.
NSNotificationCenter.defaultCenter().addObserver_selector_name_object_(
self, "pageChanged:", PDFViewPageChangedNotification, self._pdfView)
# Find notifications.
center = NSNotificationCenter.defaultCenter()
center.addObserver_selector_name_object_(
self, 'startFind:', PDFDocumentDidBeginFindNotification,
self._pdfView.document())
center.addObserver_selector_name_object_(
self, 'findProgress:', PDFDocumentDidEndPageFindNotification,
self._pdfView.document())
center.addObserver_selector_name_object_(
self, 'endFind:', PDFDocumentDidEndFindNotification,
self._pdfView.document())
# Set self to be delegate (find).
self._pdfView.document().setDelegate_(self)
# Get outline.
self._outline = self._pdfView.document().outlineRoot()
if self._outline is not None:
# Remove text that says, "No outline."
self._noOutlineText.removeFromSuperview()
self._noOutlineText = None
# Force it to load up.
self._outlineView.reloadData()
else:
# Remove outline view (leaving instead text that says,
# "No outline.").
self._outlineView.enclosingScrollView().removeFromSuperview()
self._outlineView = None
# Open drawer.
self._drawer.open()
# Size the window.
windowSize = self._pdfView.rowSizeForPage_(
self._pdfView.currentPage())
if (self._pdfView.displayMode() & 0x01) and (
self._pdfView.document().pageCount() > 1):
windowSize.width += NSScroller.scrollerWidth()
controller.window().setContentSize_(windowSize)
def dataRepresentationOfType_(self, aType):
return None
def loadDataRepresentation_ofType_(self, data, aType):
return True
@objc.IBAction
def toggleDrawer_(self, sender):
self._drawer.toggle_(self)
@objc.IBAction
def takeDestinationFromOutline_(self, sender):
# Get the destination associated with the search result list.
# Tell the PDFView to go there.
self._pdfView.goToDestination_(
sender.itemAtRow_(sender.selectedRow()).destination())
@objc.IBAction
def displaySinglePage_(self, sender):
# Display single page mode.
if self._pdfView.displayMode() > kPDFDisplaySinglePageContinuous:
self._pdfView.setDisplayMode_(self._pdfView.displayMode() - 2)
@objc.IBAction
def displayTwoUp_(self, sender):
# Display two-up.
if self._pdfView.displayMode() < kPDFDisplayTwoUp:
self._pdfView.setDisplayMode_(self._pdfView.displayMode() + 2)
def pageChanged_(self, notification):
# Skip out if there is no outline.
if selfl_pdfView.document().outlineRoot() is None:
return
# What is the new page number (zero-based).
newPageIndex = self._pdfView.document().indexForPage_(
self._pdfView.currentPage())
# Walk outline view looking for best firstpage number match.
newlySelectedRow = -1;
numRows = self._outlineView.numberOfRows()
for i in range(numRows):
outlineItem = self._outlineView.itemAtRow_(i)
if self._pdfView.document().indexForPage_(
outlineItem.destination().page()) == newPageIndex:
newlySelectedRow = i
self._outlineView.selectRow_byExtendingSelection_(
newlySelectedRow, False)
break
elif self._pdfView.document().indexForPage_(outlineItem.destionation().page()) > newPageIndex:
newlySelectedRow = i - 1
self._outlineView.selectRow_byExtendingSelection_(
newlySelectedRow, False)
break
# Auto-scroll.
if newlySelectedRow != -1:
self._outlineView.scrollRowToVisible_(newlySelectedRow)
def doFind_(self, sender):
if self._pdfView.document().isFinding():
self._pdfView.document().cancelFindString()
# Lazily allocate _searchResults.
if self._searchResults is None:
self._searchResults = NSMutableArray.arrayWithCapacity_(10)
self._pdfView.document().beginFindString_withOptions_(
sender.stringValue(), NSCaseInsensitiveSearch)
def startFind_(self, notification):
# Empty arrays.
self._searchResults.removeAllObjects()
self._searchTable.reloadData()
self._searchProgress.startAnimation_(self)
def findProgress_(self, notification):
pageIndex = notification.userInfo().objectForKey_(
"PDFDocumentPageIndex") #.doubleValue()
self._searchProgress.setDoubleValue_(
pageIndex / self._pdfView.document().pageCount())
def didMatchString_(self, instance):
# Add page label to our array.
self._searchResults.addObject_(instance.copy())
self._searchTable.reloadData()
def endFind_(self, notification):
self._searchProgress.stopAnimation_(self)
self._searchProgress.setDoubleValue_(0)
# The table view is used to hold search results. Column 1 lists the
# page number for the search result, column two the section in the PDF
# (x-ref with the PDF outline) where the result appears.
def numberOfRowsInTableView_(self, aTableView):
if self._searchResults is None:
return 0
return self._searchResults.count()
def tableView_objectValueForTableColumn_row_(
self, aTableView, theColumn, rowIndex):
if theColumn.identifier() == "page":
return self._searchResults.objectAtIndex_(rowIndex).pages().objectAtIndex_(0).label()
elif theColumn.identifier() == 'section':
value = self._pdfView.document().outlineItemForSelection_(
self._searchResults.objectAtIndex_(rowIndex))
if value is None:
return None
return value.label()
else:
return None
def tableViewSelectionDidChange_(self, notification):
# What was selected. Skip out if the row has not changed.
rowIndex = notification.object().selectedRow()
if rowIndex >= 0:
self._pdfView.setCurrentSelection_(
self._searchResults.objectAtIndex_(rowIndex))
self._pdfView.centerSelectionInVisibleArea_(self)
# The outline view is for the PDF outline. Not all PDF's have an outline.
def outlineView_numberOfChildrenOfItem_(self, outlineView, item):
if item is None:
if self._outline is not None:
return self._outline.numberOfChildren()
else:
return 0
else:
return item.numberOfChildren()
def outlineView_child_ofItem_(self, outlineView, index, item):
if item is None:
if self._outline is not None:
return self._outline.childAtIndex_(index).retain()
else:
return None
else:
return item.childAtIndex_(index).retain()
def outlineView_isItemExpandable_(self, outlineView, item):
if item is None:
if self._outline:
return self._outline.numberOfChildren() > 0
else:
return False
else:
return item.numberOfChildren() > 0
def outlineView_objectValueForTableColumn_byItem_(
self, outlineView, tableColumn, item):
return item.label()
|