"""pageturner.py: Tkinter widget for viewing a sequence of content pages Do not edit this file. It is extracted automatically from its documentation file. See: http://www.nmt.edu/tcc/help/lang/python/examples/pageturner/ """ #================================================================ # Imports #---------------------------------------------------------------- from Tkinter import * # - - - - - c l a s s P a g e T u r n e r - - - - - class PageTurner(Frame): """Widget to allow user to page through a set of content pages. Exports: PageTurner ( master=None, size=None ): [ (master is the containing widget) and (size is a (width, height) tuple to get a fixed page viewing area of that size, or None for one that automatically resizes for each page) -> return a new PageTurner widget with those attributes and no content pages ] .pageNoEntry: [ displays the current page number ] .nPagesLabel: [ displays the number of pages ] .prevButton: [ the 'Previous page' button ] .nextButton: [ the 'Next page' button ] .headFrame: [ a Frame inside self for displaying page headings, if any ] .bodyFrame: [ a Frame inside self for displaying the current content page, if any ] .addPage ( f ): [ f is a Frame -> self := self with f added as its next content page ] .setPageNo ( n ): [ n is a positive integer -> if n < (number of content pages) -> self := self displaying page n (counting from 1) else -> I ] Included widgets: .__buttonFrame: [ frame containing all operating controls ] Invariants: .__size: [ the size argument passed to the constructor ] .__pageList: [ a list whose members are the content pages in viewing order ] .__pageNo: [ if self contains any pages -> current page number, counting from 1 else -> 0 ] .__pageNoVar: [ the StringVar associated with self.pageNoEntry. Invariant: if len(self.__pageList) == 0 -> 0 else -> self.__pageNo ] .__nPagesVar: [ the StringVar associated with self.nPagesLabel ] """ # - - - P a g e T u r n e r . _ _ i n i t _ _ - - - def __init__ ( self, master=None, size=None ): """Constructor for the PageTurner widget.""" #-- 1 -- # [ master := master with a new Frame added but not gridded # self := that new Frame ] Frame.__init__ ( self, master ) #-- 2 -- self.__size = size #-- 3 -- self.__pageList = [] self.__pageNo = 0 #-- 4 -- # [ self := self with all widgets created ] self.__createWidgets() # - - - P a g e T u r n e r . _ _ c r e a t e W i d g e t s - - - def __createWidgets ( self ): """Create and grid all internal widgets. [ self.__size is as invariant -> self := self with all widgets created ] """ #-- 1 -- # [ self := self with a new Frame added and gridded # containing self's control widgets ] self.__buttonFrame = self.__createButtons() rowx = 0 self.__buttonFrame.grid ( row=rowx, column=0, columnspan=99, sticky=E+W ) #-- 2 -- # [ self := self with a new, empty Frame added # and gridded # self.headFrame := that Frame ] self.headFrame = Frame ( self ) rowx += 1 self.headFrame.grid ( row=rowx, sticky=W ) #-- 3 -- # [ self := self with a new, empty Frame added # and gridded # self.bodyFrame := that Frame ] self.bodyFrame = Frame ( self, relief=SUNKEN, borderwidth=2 ) rowx += 1 self.bodyFrame.grid ( row=rowx, sticky=W ) #-- 4 -- # [ if self.__size is not None -> # self.bodyFrame := self.bodyFrame fixed as size # self.__size # else -> I ] if self.__size: self.bodyFrame['width'] = self.__size[0] self.bodyFrame['height'] = self.__size[1] self.bodyFrame.grid_propagate(0) # - - - P a g e T u r n e r . _ _ c r e a t e B u t t o n s - - - def __createButtons ( self ): """Create the frame containing all the controls. [ return a new Frame containing self's control widgets ] """ #-- 1 -- # [ self := self with a new Frame added # buttons := that new Frame ] buttons = Frame ( self ) #-- 2 -- # [ buttons := buttons with a Label added containing "Page " ] self.__pageLabel = Label ( buttons, text="Page " ) colx = 0 self.__pageLabel.grid ( row=0, column=colx ) buttons.columnconfigure(colx, weight=1) #-- 3 -- # [ buttons := buttons with an Entry added with a StringVar # control variable, and a handler that turns to the # given page when the user presses Enter # self.pageNoEntry := that Entry # self.__pageNoVar := that StringVar self.__pageNoVar = StringVar() self.__pageNoVar.set("0") self.pageNoEntry = Entry ( buttons, relief=SUNKEN, width=3, textvariable=self.__pageNoVar ) self.pageNoEntry.bind ( "", self.__pageNoHandler ) colx += 1 self.pageNoEntry.grid ( row=0, column=colx ) buttons.columnconfigure(colx, weight=1) #-- 4 -- # [ buttons := buttons with a Label added containing " of " ] self.__ofLabel = Label ( buttons, text=" of " ) colx += 1 self.__ofLabel.grid ( row=0, column=colx ) buttons.columnconfigure(colx, weight=1) #-- 5 -- # [ buttons := buttons with a Label added with a StringVar # control variable # self.nPagesLabel := that Label # self.__nPagesVar := that StringVar ] self.__nPagesVar = StringVar() self.__nPagesVar.set("0") self.nPagesLabel = Label ( buttons, relief=FLAT, width=3, textvariable=self.__nPagesVar ) colx += 1 self.nPagesLabel.grid ( row=0, column=colx ) buttons.columnconfigure(colx, weight=1) #-- 6 -- # [ buttons := buttons with an empty column that # expands by a factor of 10000 ] colx += 1 buttons.columnconfigure(colx, weight=10000) #-- 7 -- # [ buttons := buttons with a new Button added that moves to # the previous page # self.prevButton := that Button ] self.prevButton = Button ( buttons, text="Previous page", command=self.__prevHandler, state=DISABLED ) colx += 1 self.prevButton.grid ( row=0, column=colx, sticky=E ) buttons.columnconfigure(colx, weight=1) #-- 8 -- # [ buttons := buttons with a new Button added that moves to # the next page # self.nextButton := that Button ] self.nextButton = Button ( buttons, text="Next page", command=self.__nextHandler, state=DISABLED ) colx += 1 self.nextButton.grid ( row=0, column=colx, sticky=E ) buttons.columnconfigure(colx, weight=1) #-- 9 -- return buttons # - - - P a g e T u r n e r . _ _ p a g e N o H a n d l e r - - - def __pageNoHandler ( self, event ): """Handle a change to self.pageNoEntry [ event is an Event object -> if self.__pageNoVar contains a valid integer that is in the range [1,len(self.__pageList)] -> self := self displaying int(self.__pageNoVar.get()) else -> self.pageNoEntry := self.__pageNo as a string ] """ #-- 1 -- # [ if self.__pageNoVar contains an integer in # [1,len(self.__pageList)] -> # self := self displaying page (pageNo) # return # else -> I ] try: pageNo = int ( self.__pageNoVar.get() ) if ( 1 <= pageNo <= len(self.__pageList) ): self.setPageNo ( pageNo ) return except ValueError: pass #-- 2 -- # [ self.pageNoEntry := self.__pageNo as a string ] self.__pageNoVar.set ( self.__pageNo ) # - - - P a g e T u r n e r . _ _ p r e v H a n d l e r - - - def __prevHandler ( self ): """Handle the 'Previous page' button. [ if self.__pageNo > 1 -> self := self displaying page (self.__pageNo-1) else -> I ] """ if self.__pageNo > 1: self.setPageNo ( self.__pageNo - 1 ) # - - - P a g e T u r n e r . _ _ n e x t H a n d l e r - - - def __nextHandler ( self ): """Handle the 'Next page' button. [ if self.__pageNo < len(self.__pageList) -> self := self displaying page (self.__pageNo+1) else -> I ] """ if self.__pageNo < len(self.__pageList): self.setPageNo ( self.__pageNo + 1 ) # - - - P a g e T u r n e r . a d d P a g e - - - def addPage ( self, page ): """Add a new content page.""" #-- 1 -- # [ self.__pageList +:= page # self.nPagesLabel := 1+len(self.__pageList) ] self.__pageList.append ( page ) self.__nPagesVar.set ( str ( len(self.__pageList) ) ) #-- 2 -- # [ if self.__pageNo == 0 -> # self := self with the first page displayed # else -> I ] if self.__pageNo == 0: self.setPageNo ( 1 ) # - - - P a g e T u r n e r . s e t P a g e N o - - - def setPageNo ( self, n ): """Display the nth page, counting from 1.""" #-- 1 -- # [ if (n < 1) or (n > len(self.__pageList)) -> # return # else -> I ] if not ( 1 <= n <= len(self.__pageList) ): return #-- 2 -- # [ if self.__pageNo > 0 -> # self.__pageList[self.__pageNo-1] := itself ungridded # else -> I ] if self.__pageNo > 0: oldPage = self.__pageList[self.__pageNo-1] oldPage.grid_forget() #-- 3 -- # [ self.__pageNoVar := n # self.__nPagesVar := len(self.__pageList) ] self.__pageNoVar.set ( str ( n ) ) self.__nPagesVar.set ( str ( len ( self.__pageList ) ) ) #-- 4 -- # [ self.__pageList[n-1] := itself, gridded # self.__pageNo := n ] newPage = self.__pageList[n-1] newPage.grid ( row=0, column=0, sticky=NW ) self.bodyFrame.columnconfigure(0, weight=1) self.bodyFrame.rowconfigure(0, weight=1) self.__pageNo = n #-- 5 -- # [ self.prevButton := self.prevButton enabled # [ self.nextButton := self.nextButton enabled ] self.prevButton["state"] = NORMAL self.nextButton["state"] = NORMAL