blob: 12f89291da4dd3f8e54f5397a60ba52c29464a8c [file] [log] [blame]
Steven M. Gava5b357b92001-12-05 06:32:46 +00001"""
2a couple of classes for implementing partial tabbed-page like behaviour
3"""
4
5from Tkinter import *
6
Neal Norwitz5b0b00f2002-11-30 19:10:19 +00007class InvalidTabPage(Exception): pass
8class AlreadyExists(Exception): pass
9
Steven M. Gava5b357b92001-12-05 06:32:46 +000010class PageTab(Frame):
11 """
12 a 'page tab' like framed button
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000013 """
Steven M. Gava5b357b92001-12-05 06:32:46 +000014 def __init__(self,parent):
15 Frame.__init__(self, parent,borderwidth=2,relief=RIDGE)
16 self.button=Radiobutton(self,padx=5,pady=5,takefocus=FALSE,
Steven M. Gava361cfcd2002-01-03 12:02:37 +000017 indicatoron=FALSE,highlightthickness=0,
Steven M. Gava5b357b92001-12-05 06:32:46 +000018 borderwidth=0,selectcolor=self.cget('bg'))
19 self.button.pack()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000020
Steven M. Gava5b357b92001-12-05 06:32:46 +000021class TabPageSet(Frame):
22 """
23 a set of 'pages' with TabButtons for controlling their display
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000024 """
Steven M. Gava361cfcd2002-01-03 12:02:37 +000025 def __init__(self,parent,pageNames=[],**kw):
Steven M. Gava5b357b92001-12-05 06:32:46 +000026 """
27 pageNames - a list of strings, each string will be the dictionary key
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000028 to a page's data, and the name displayed on the page's tab. Should be
29 specified in desired page order. The first page will be the default
Steven M. Gava5b357b92001-12-05 06:32:46 +000030 and first active page.
31 """
32 Frame.__init__(self, parent, kw)
33 self.grid_location(0,0)
34 self.columnconfigure(0,weight=1)
35 self.rowconfigure(1,weight=1)
36 self.tabBar=Frame(self)
37 self.tabBar.grid(row=0,column=0,sticky=EW)
38 self.activePage=StringVar(self)
39 self.defaultPage=''
40 self.pages={}
41 for name in pageNames:
42 self.AddPage(name)
43
44 def ChangePage(self,pageName=None):
45 if pageName:
46 if pageName in self.pages.keys():
47 self.activePage.set(pageName)
48 else:
Neal Norwitz5b0b00f2002-11-30 19:10:19 +000049 raise InvalidTabPage, 'Invalid TabPage Name'
Steven M. Gava5b357b92001-12-05 06:32:46 +000050 ## pop up the active 'tab' only
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000051 for page in self.pages.keys():
Steven M. Gava5b357b92001-12-05 06:32:46 +000052 self.pages[page]['tab'].config(relief=RIDGE)
53 self.pages[self.GetActivePage()]['tab'].config(relief=RAISED)
54 ## switch page
55 self.pages[self.GetActivePage()]['page'].lift()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000056
Steven M. Gava5b357b92001-12-05 06:32:46 +000057 def GetActivePage(self):
58 return self.activePage.get()
59
60 def AddPage(self,pageName):
61 if pageName in self.pages.keys():
Neal Norwitz5b0b00f2002-11-30 19:10:19 +000062 raise AlreadyExists, 'TabPage Name Already Exists'
Steven M. Gava5b357b92001-12-05 06:32:46 +000063 self.pages[pageName]={'tab':PageTab(self.tabBar),
64 'page':Frame(self,borderwidth=2,relief=RAISED)}
65 self.pages[pageName]['tab'].button.config(text=pageName,
66 command=self.ChangePage,variable=self.activePage,
67 value=pageName)
68 self.pages[pageName]['tab'].pack(side=LEFT)
69 self.pages[pageName]['page'].grid(row=1,column=0,sticky=NSEW)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000070 if len(self.pages)==1: # adding first page
Steven M. Gava5b357b92001-12-05 06:32:46 +000071 self.defaultPage=pageName
72 self.activePage.set(self.defaultPage)
73 self.ChangePage()
74
75 def RemovePage(self,pageName):
76 if not pageName in self.pages.keys():
Neal Norwitz5b0b00f2002-11-30 19:10:19 +000077 raise InvalidTabPage, 'Invalid TabPage Name'
Steven M. Gava5b357b92001-12-05 06:32:46 +000078 self.pages[pageName]['tab'].pack_forget()
79 self.pages[pageName]['page'].grid_forget()
80 self.pages[pageName]['tab'].destroy()
81 self.pages[pageName]['page'].destroy()
82 del(self.pages[pageName])
83 # handle removing last remaining, or default, or active page
84 if not self.pages: # removed last remaining page
85 self.defaultPage=''
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000086 return
Steven M. Gava5b357b92001-12-05 06:32:46 +000087 if pageName==self.defaultPage: # set a new default page
88 self.defaultPage=\
89 self.tabBar.winfo_children()[0].button.cget('text')
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000090 if pageName==self.GetActivePage(): # set a new active page
Steven M. Gava5b357b92001-12-05 06:32:46 +000091 self.activePage.set(self.defaultPage)
92 self.ChangePage()
93
94if __name__ == '__main__':
Steven M. Gava34b88512001-12-05 06:39:18 +000095 #test dialog
Steven M. Gava5b357b92001-12-05 06:32:46 +000096 root=Tk()
97 tabPage=TabPageSet(root,pageNames=['Foobar','Baz'])
98 tabPage.pack(expand=TRUE,fill=BOTH)
99 Label(tabPage.pages['Foobar']['page'],text='Foo',pady=20).pack()
100 Label(tabPage.pages['Foobar']['page'],text='Bar',pady=20).pack()
101 Label(tabPage.pages['Baz']['page'],text='Baz').pack()
102 entryPgName=Entry(root)
103 buttonAdd=Button(root,text='Add Page',
104 command=lambda:tabPage.AddPage(entryPgName.get()))
105 buttonRemove=Button(root,text='Remove Page',
106 command=lambda:tabPage.RemovePage(entryPgName.get()))
107 labelPgName=Label(root,text='name of page to add/remove:')
108 buttonAdd.pack(padx=5,pady=5)
109 buttonRemove.pack(padx=5,pady=5)
110 labelPgName.pack(padx=5)
111 entryPgName.pack(padx=5)
Steven M. Gava361cfcd2002-01-03 12:02:37 +0000112 tabPage.ChangePage()
Steven M. Gava5b357b92001-12-05 06:32:46 +0000113 root.mainloop()