diff options
author | Kurt B. Kaiser <kbk@shore.net> | 2007-12-11 19:35:12 (GMT) |
---|---|---|
committer | Kurt B. Kaiser <kbk@shore.net> | 2007-12-11 19:35:12 (GMT) |
commit | 7a634e60272abf547d6a0c78f7a054e27773859f (patch) | |
tree | 47dd80a3bed0a0c0526e83d47c9ba04b42cd2424 /Lib | |
parent | 2382832bf336371d6d5b0c32675c74aeb0271f3e (diff) | |
download | cpython-7a634e60272abf547d6a0c78f7a054e27773859f.zip cpython-7a634e60272abf547d6a0c78f7a054e27773859f.tar.gz cpython-7a634e60272abf547d6a0c78f7a054e27773859f.tar.bz2 |
IDLE_tabbedpages.071101.patch Tal Einat
Cosmetic changes, one bug. Remove tabpage.py, replaced by tabbedpages.py
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/idlelib/tabbedpages.py | 82 | ||||
-rw-r--r-- | Lib/idlelib/tabpage.py | 113 |
2 files changed, 47 insertions, 148 deletions
diff --git a/Lib/idlelib/tabbedpages.py b/Lib/idlelib/tabbedpages.py index 98f6a27..8d7113d 100644 --- a/Lib/idlelib/tabbedpages.py +++ b/Lib/idlelib/tabbedpages.py @@ -4,7 +4,7 @@ Originally developed for use in IDLE. Based on tabpage.py. Classes exported: TabbedPageSet -- A Tkinter implementation of a tabbed-page widget. -TabBarSet -- A widget containing tabs (buttons) in one or more rows. +TabSet -- A widget containing tabs (buttons) in one or more rows. """ from Tkinter import * @@ -13,7 +13,7 @@ class InvalidNameError(Exception): pass class AlreadyExistsError(Exception): pass -class TabBarSet(Frame): +class TabSet(Frame): """A widget containing tabs (buttons) in one or more rows. Only one tab may be selected at a time. @@ -30,11 +30,11 @@ class TabBarSet(Frame): tabs -- A list of strings, the names of the tabs. Should be specified in the desired tab order. The first tab will be the default and first - active tab. If tabs is None or empty, the TabBarSet will be initialized + active tab. If tabs is None or empty, the TabSet will be initialized empty. n_rows -- Number of rows of tabs to be shown. If n_rows <= 0 or is - None, then the number of rows will be decided by TabBarSet. See + None, then the number of rows will be decided by TabSet. See _arrange_tabs() for details. max_tabs_per_row -- Used for deciding how many rows of tabs are needed, @@ -76,15 +76,15 @@ class TabBarSet(Frame): self._arrange_tabs() def remove_tab(self, tab_name): - """Remove the tab with the name given in tab_name.""" + """Remove the tab named <tab_name>""" if not tab_name in self._tab_names: raise KeyError("No such Tab: '%s" % page_name) self._tab_names.remove(tab_name) self._arrange_tabs() - def select_tab(self, tab_name): - """Select the tab with the name given in tab_name.""" + def set_selected_tab(self, tab_name): + """Show the tab named <tab_name> as the selected one""" if tab_name == self._selected_tab: return if tab_name is not None and tab_name not in self._tabs: @@ -111,14 +111,11 @@ class TabBarSet(Frame): tab_row = Frame(self) tab_row.pack(side=TOP, fill=X, expand=0) - tab_row.tab_set = self self._tab_rows.append(tab_row) for tab_name in tab_names: - def tab_command(select_command=self.select_command, - tab_name=tab_name): - return select_command(tab_name) - tab = TabBarSet.TabButton(tab_row, tab_name, tab_command) + tab = TabSet.TabButton(tab_name, self.select_command, + tab_row, self) if expand_tabs: tab.pack(side=LEFT, fill=X, expand=True) else: @@ -126,6 +123,7 @@ class TabBarSet(Frame): self._tabs[tab_name] = tab self._tab2row[tab] = tab_row + # tab is the last one created in the above loop tab.is_last_in_row = True def _reset_tab_rows(self): @@ -158,8 +156,9 @@ class TabBarSet(Frame): # calculate the required number of rows n_rows = (len(self._tab_names) - 1) // self.max_tabs_per_row + 1 - i = 0 + # not expanding the tabs with more than one row is very ugly expand_tabs = self.expand_tabs or n_rows > 1 + i = 0 # index in self._tab_names for row_index in xrange(n_rows): # calculate required number of tabs in this row n_tabs = (len(self._tab_names) - i - 1) // (n_rows - row_index) + 1 @@ -169,47 +168,60 @@ class TabBarSet(Frame): # re-select selected tab so it is properly displayed selected = self._selected_tab - self.select_tab(None) + self.set_selected_tab(None) if selected in self._tab_names: - self.select_tab(selected) + self.set_selected_tab(selected) class TabButton(Frame): """A simple tab-like widget.""" bw = 2 # borderwidth - def __init__(self, tab_row, name, command): + def __init__(self, name, select_command, tab_row, tab_set): """Constructor arguments: name -- The tab's name, which will appear in its button. - command -- The command to be called upon selection of the tab. It - is called with the tab's name as an argument. + select_command -- The command to be called upon selection of the + tab. It is called with the tab's name as an argument. """ - Frame.__init__(self, tab_row, borderwidth=self.bw) - self.button = Radiobutton(self, text=name, command=command, + Frame.__init__(self, tab_row, borderwidth=self.bw, relief=RAISED) + + self.name = name + self.select_command = select_command + self.tab_set = tab_set + self.is_last_in_row = False + + self.button = Radiobutton( + self, text=name, command=self._select_event, padx=5, pady=1, takefocus=FALSE, indicatoron=FALSE, highlightthickness=0, selectcolor='', borderwidth=0) self.button.pack(side=LEFT, fill=X, expand=True) - self.tab_set = tab_row.tab_set - - self.is_last_in_row = False - self._init_masks() self.set_normal() + def _select_event(self, *args): + """Event handler for tab selection. + + With TabbedPageSet, this calls TabbedPageSet.change_page, so that + selecting a tab changes the page. + + Note that this does -not- call set_selected -- it will be called by + TabSet.set_selected_tab, which should be called when whatever the + tabs are related to changes. + + """ + self.select_command(self.name) + return + def set_selected(self): """Assume selected look""" - for widget in self, self.mskl.ml, self.mskr.mr: - widget.config(relief=RAISED) self._place_masks(selected=True) def set_normal(self): """Assume normal look""" - for widget in self, self.mskl.ml, self.mskr.mr: - widget.config(relief=RAISED) self._place_masks(selected=False) def _init_masks(self): @@ -351,8 +363,8 @@ class TabbedPageSet(Frame): and first active page. If page_names is None or empty, the TabbedPageSet will be initialized empty. - n_rows, max_tabs_per_row -- Parameters for the TabBarSet which will - manage the tabs. See TabBarSet's docs for details. + n_rows, max_tabs_per_row -- Parameters for the TabSet which will + manage the tabs. See TabSet's docs for details. page_class -- Pages can be shown/hidden using three mechanisms: @@ -372,7 +384,7 @@ class TabbedPageSet(Frame): TabbedPageSet to resize when the page is changed. """ - Frame.__init__(self, parent, kw) + Frame.__init__(self, parent, **kw) self.page_class = page_class self.pages = {} @@ -390,9 +402,9 @@ class TabbedPageSet(Frame): self.pages_frame.rowconfigure(0, weight=1) # the order of the following commands is important - self._tab_set = TabBarSet(self, self.change_page, n_rows=n_rows, - max_tabs_per_row=max_tabs_per_row, - expand_tabs=expand_tabs) + self._tab_set = TabSet(self, self.change_page, n_rows=n_rows, + max_tabs_per_row=max_tabs_per_row, + expand_tabs=expand_tabs) if page_names: for name in page_names: self.add_page(name) @@ -453,7 +465,7 @@ class TabbedPageSet(Frame): self._current_page = page_name self.pages[page_name]._show() - self._tab_set.select_tab(page_name) + self._tab_set.set_selected_tab(page_name) if __name__ == '__main__': # test dialog diff --git a/Lib/idlelib/tabpage.py b/Lib/idlelib/tabpage.py deleted file mode 100644 index 12f8929..0000000 --- a/Lib/idlelib/tabpage.py +++ /dev/null @@ -1,113 +0,0 @@ -""" -a couple of classes for implementing partial tabbed-page like behaviour -""" - -from Tkinter import * - -class InvalidTabPage(Exception): pass -class AlreadyExists(Exception): pass - -class PageTab(Frame): - """ - a 'page tab' like framed button - """ - def __init__(self,parent): - Frame.__init__(self, parent,borderwidth=2,relief=RIDGE) - self.button=Radiobutton(self,padx=5,pady=5,takefocus=FALSE, - indicatoron=FALSE,highlightthickness=0, - borderwidth=0,selectcolor=self.cget('bg')) - self.button.pack() - -class TabPageSet(Frame): - """ - a set of 'pages' with TabButtons for controlling their display - """ - def __init__(self,parent,pageNames=[],**kw): - """ - pageNames - a list of strings, each string will be the dictionary key - to a page's data, and the name displayed on the page's tab. Should be - specified in desired page order. The first page will be the default - and first active page. - """ - Frame.__init__(self, parent, kw) - self.grid_location(0,0) - self.columnconfigure(0,weight=1) - self.rowconfigure(1,weight=1) - self.tabBar=Frame(self) - self.tabBar.grid(row=0,column=0,sticky=EW) - self.activePage=StringVar(self) - self.defaultPage='' - self.pages={} - for name in pageNames: - self.AddPage(name) - - def ChangePage(self,pageName=None): - if pageName: - if pageName in self.pages.keys(): - self.activePage.set(pageName) - else: - raise InvalidTabPage, 'Invalid TabPage Name' - ## pop up the active 'tab' only - for page in self.pages.keys(): - self.pages[page]['tab'].config(relief=RIDGE) - self.pages[self.GetActivePage()]['tab'].config(relief=RAISED) - ## switch page - self.pages[self.GetActivePage()]['page'].lift() - - def GetActivePage(self): - return self.activePage.get() - - def AddPage(self,pageName): - if pageName in self.pages.keys(): - raise AlreadyExists, 'TabPage Name Already Exists' - self.pages[pageName]={'tab':PageTab(self.tabBar), - 'page':Frame(self,borderwidth=2,relief=RAISED)} - self.pages[pageName]['tab'].button.config(text=pageName, - command=self.ChangePage,variable=self.activePage, - value=pageName) - self.pages[pageName]['tab'].pack(side=LEFT) - self.pages[pageName]['page'].grid(row=1,column=0,sticky=NSEW) - if len(self.pages)==1: # adding first page - self.defaultPage=pageName - self.activePage.set(self.defaultPage) - self.ChangePage() - - def RemovePage(self,pageName): - if not pageName in self.pages.keys(): - raise InvalidTabPage, 'Invalid TabPage Name' - self.pages[pageName]['tab'].pack_forget() - self.pages[pageName]['page'].grid_forget() - self.pages[pageName]['tab'].destroy() - self.pages[pageName]['page'].destroy() - del(self.pages[pageName]) - # handle removing last remaining, or default, or active page - if not self.pages: # removed last remaining page - self.defaultPage='' - return - if pageName==self.defaultPage: # set a new default page - self.defaultPage=\ - self.tabBar.winfo_children()[0].button.cget('text') - if pageName==self.GetActivePage(): # set a new active page - self.activePage.set(self.defaultPage) - self.ChangePage() - -if __name__ == '__main__': - #test dialog - root=Tk() - tabPage=TabPageSet(root,pageNames=['Foobar','Baz']) - tabPage.pack(expand=TRUE,fill=BOTH) - Label(tabPage.pages['Foobar']['page'],text='Foo',pady=20).pack() - Label(tabPage.pages['Foobar']['page'],text='Bar',pady=20).pack() - Label(tabPage.pages['Baz']['page'],text='Baz').pack() - entryPgName=Entry(root) - buttonAdd=Button(root,text='Add Page', - command=lambda:tabPage.AddPage(entryPgName.get())) - buttonRemove=Button(root,text='Remove Page', - command=lambda:tabPage.RemovePage(entryPgName.get())) - labelPgName=Label(root,text='name of page to add/remove:') - buttonAdd.pack(padx=5,pady=5) - buttonRemove.pack(padx=5,pady=5) - labelPgName.pack(padx=5) - entryPgName.pack(padx=5) - tabPage.ChangePage() - root.mainloop() |