Steven M. Gava | 5b357b9 | 2001-12-05 06:32:46 +0000 | [diff] [blame^] | 1 | ##---------------------------------------------------------------------------## |
| 2 | ## |
| 3 | ## pyChing -- a Python program to cast and interpret I Ching hexagrams |
| 4 | ## |
| 5 | ## Copyright (C) 1999,2000 Stephen M. Gava |
| 6 | ## |
| 7 | ## This program is free software; you can redistribute it and/or modify |
| 8 | ## it under the terms of the GNU General Public License as published by |
| 9 | ## the Free Software Foundation; either version 2 of the License, or |
| 10 | ## (at your option) any later version. |
| 11 | ## |
| 12 | ## This program is distributed in the hope that it will be of some |
| 13 | ## interest to somebody, but WITHOUT ANY WARRANTY; without even the |
| 14 | ## implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| 15 | ## See the GNU General Public License for more details. |
| 16 | ## |
| 17 | ## You should have received a copy of the GNU General Public License |
| 18 | ## along with this program; see the file COPYING or COPYING.txt. If not, |
| 19 | ## write to the Free Software Foundation, Inc., |
| 20 | ## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 21 | ## The license can also be found at the GNU/FSF website: http://www.gnu.org |
| 22 | ## |
| 23 | ## Stephen M. Gava |
| 24 | ## <elguavas@users.sourceforge.net> |
| 25 | ## http://pyching.sourgeforge.net |
| 26 | ## |
| 27 | ##---------------------------------------------------------------------------## |
| 28 | """ |
| 29 | a couple of classes for implementing partial tabbed-page like behaviour |
| 30 | """ |
| 31 | |
| 32 | from Tkinter import * |
| 33 | |
| 34 | class PageTab(Frame): |
| 35 | """ |
| 36 | a 'page tab' like framed button |
| 37 | """ |
| 38 | def __init__(self,parent): |
| 39 | Frame.__init__(self, parent,borderwidth=2,relief=RIDGE) |
| 40 | self.button=Radiobutton(self,padx=5,pady=5,takefocus=FALSE, |
| 41 | underline=0,indicatoron=FALSE,highlightthickness=0, |
| 42 | borderwidth=0,selectcolor=self.cget('bg')) |
| 43 | self.button.pack() |
| 44 | |
| 45 | class TabPageSet(Frame): |
| 46 | """ |
| 47 | a set of 'pages' with TabButtons for controlling their display |
| 48 | """ |
| 49 | def __init__(self,parent,pageNames,**kw): |
| 50 | """ |
| 51 | pageNames - a list of strings, each string will be the dictionary key |
| 52 | to a page's data, and the name displayed on the page's tab. Should be |
| 53 | specified in desired page order. The first page will be the default |
| 54 | and first active page. |
| 55 | """ |
| 56 | Frame.__init__(self, parent, kw) |
| 57 | self.grid_location(0,0) |
| 58 | self.columnconfigure(0,weight=1) |
| 59 | self.rowconfigure(1,weight=1) |
| 60 | self.tabBar=Frame(self) |
| 61 | self.tabBar.grid(row=0,column=0,sticky=EW) |
| 62 | self.activePage=StringVar(self) |
| 63 | self.defaultPage='' |
| 64 | self.pages={} |
| 65 | for name in pageNames: |
| 66 | self.AddPage(name) |
| 67 | |
| 68 | def ChangePage(self,pageName=None): |
| 69 | if pageName: |
| 70 | if pageName in self.pages.keys(): |
| 71 | self.activePage.set(pageName) |
| 72 | else: |
| 73 | raise 'Invalid TabPage Name' |
| 74 | ## pop up the active 'tab' only |
| 75 | for page in self.pages.keys(): |
| 76 | self.pages[page]['tab'].config(relief=RIDGE) |
| 77 | self.pages[self.GetActivePage()]['tab'].config(relief=RAISED) |
| 78 | ## switch page |
| 79 | self.pages[self.GetActivePage()]['page'].lift() |
| 80 | |
| 81 | def GetActivePage(self): |
| 82 | return self.activePage.get() |
| 83 | |
| 84 | def AddPage(self,pageName): |
| 85 | if pageName in self.pages.keys(): |
| 86 | raise 'TabPage Name Already Exists' |
| 87 | self.pages[pageName]={'tab':PageTab(self.tabBar), |
| 88 | 'page':Frame(self,borderwidth=2,relief=RAISED)} |
| 89 | self.pages[pageName]['tab'].button.config(text=pageName, |
| 90 | command=self.ChangePage,variable=self.activePage, |
| 91 | value=pageName) |
| 92 | self.pages[pageName]['tab'].pack(side=LEFT) |
| 93 | self.pages[pageName]['page'].grid(row=1,column=0,sticky=NSEW) |
| 94 | if len(self.pages)==1: # adding first page |
| 95 | self.defaultPage=pageName |
| 96 | self.activePage.set(self.defaultPage) |
| 97 | self.ChangePage() |
| 98 | |
| 99 | def RemovePage(self,pageName): |
| 100 | if not pageName in self.pages.keys(): |
| 101 | raise 'Invalid TabPage Name' |
| 102 | self.pages[pageName]['tab'].pack_forget() |
| 103 | self.pages[pageName]['page'].grid_forget() |
| 104 | self.pages[pageName]['tab'].destroy() |
| 105 | self.pages[pageName]['page'].destroy() |
| 106 | del(self.pages[pageName]) |
| 107 | # handle removing last remaining, or default, or active page |
| 108 | if not self.pages: # removed last remaining page |
| 109 | self.defaultPage='' |
| 110 | return |
| 111 | if pageName==self.defaultPage: # set a new default page |
| 112 | self.defaultPage=\ |
| 113 | self.tabBar.winfo_children()[0].button.cget('text') |
| 114 | if pageName==self.GetActivePage(): # set a new active page |
| 115 | self.activePage.set(self.defaultPage) |
| 116 | self.ChangePage() |
| 117 | |
| 118 | if __name__ == '__main__': |
| 119 | #test the dialog |
| 120 | root=Tk() |
| 121 | tabPage=TabPageSet(root,pageNames=['Foobar','Baz']) |
| 122 | tabPage.pack(expand=TRUE,fill=BOTH) |
| 123 | Label(tabPage.pages['Foobar']['page'],text='Foo',pady=20).pack() |
| 124 | Label(tabPage.pages['Foobar']['page'],text='Bar',pady=20).pack() |
| 125 | Label(tabPage.pages['Baz']['page'],text='Baz').pack() |
| 126 | entryPgName=Entry(root) |
| 127 | buttonAdd=Button(root,text='Add Page', |
| 128 | command=lambda:tabPage.AddPage(entryPgName.get())) |
| 129 | buttonRemove=Button(root,text='Remove Page', |
| 130 | command=lambda:tabPage.RemovePage(entryPgName.get())) |
| 131 | labelPgName=Label(root,text='name of page to add/remove:') |
| 132 | buttonAdd.pack(padx=5,pady=5) |
| 133 | buttonRemove.pack(padx=5,pady=5) |
| 134 | labelPgName.pack(padx=5) |
| 135 | entryPgName.pack(padx=5) |
| 136 | root.mainloop() |
| 137 | |