[Python-checkins] r63740 - sandbox/trunk/ttk-gsoc/src/idlelib_ttk.diff

guilherme.polo python-checkins at python.org
Tue May 27 03:53:51 CEST 2008


Author: guilherme.polo
Date: Tue May 27 03:53:51 2008
New Revision: 63740

Log:
Much better fallback now, in case ttk is not present

Modified:
   sandbox/trunk/ttk-gsoc/src/idlelib_ttk.diff

Modified: sandbox/trunk/ttk-gsoc/src/idlelib_ttk.diff
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/idlelib_ttk.diff	(original)
+++ sandbox/trunk/ttk-gsoc/src/idlelib_ttk.diff	Tue May 27 03:53:51 2008
@@ -1,6 +1,6 @@
 Index: Lib/idlelib/AutoCompleteWindow.py
 ===================================================================
---- Lib/idlelib/AutoCompleteWindow.py	(revision 63650)
+--- Lib/idlelib/AutoCompleteWindow.py	(revision 63734)
 +++ Lib/idlelib/AutoCompleteWindow.py	(working copy)
 @@ -4,7 +4,11 @@
  from Tkinter import *
@@ -16,7 +16,7 @@
  KEYPRESS_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keypress>>"
 Index: Lib/idlelib/ToolTip.py
 ===================================================================
---- Lib/idlelib/ToolTip.py	(revision 63650)
+--- Lib/idlelib/ToolTip.py	(revision 63734)
 +++ Lib/idlelib/ToolTip.py	(working copy)
 @@ -3,7 +3,8 @@
  # may be useful for some purposes in (or almost in ;) the current project scope
@@ -28,34 +28,70 @@
  
  class ToolTipBase:
  
+Index: Lib/idlelib/stylist.py
+===================================================================
+--- Lib/idlelib/stylist.py	(revision 0)
++++ Lib/idlelib/stylist.py	(revision 0)
+@@ -0,0 +1,29 @@
++from configHandler import idleConf
++
++TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
++
++class PoorManStyle(object):
++    def __init__(self, parent, styles=None, cfgstyles=None):
++        self.parent = parent
++        self.cfgstyles = cfgstyles
++        self.styles = styles
++
++    def configure(self, style, lookup=None, background=None):
++        if style not in self.cfgstyles: # passed wrong style probably
++            return
++
++        widget = getattr(self.parent, self.cfgstyles[style])
++        if lookup:
++            return widget.cget('bg')
++
++        widget.configure(bg=background)
++
++    def style_it(self, w, style):
++        if TTK:
++            w['style'] = style
++            return
++
++        if not style in self.styles: # may not need to be styled
++            return
++
++        w.configure(**self.styles[style])
 Index: Lib/idlelib/configSectionNameDialog.py
 ===================================================================
---- Lib/idlelib/configSectionNameDialog.py	(revision 63650)
+--- Lib/idlelib/configSectionNameDialog.py	(revision 63734)
 +++ Lib/idlelib/configSectionNameDialog.py	(working copy)
-@@ -4,7 +4,11 @@
+@@ -4,7 +4,12 @@
  """
  from Tkinter import *
  import tkMessageBox
 +from idlelib.configHandler import idleConf
  
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
++TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
++if TTK:
 +    from ttk import *
 +
  class GetCfgSectionNameDialog(Toplevel):
      def __init__(self,parent,title,message,usedNames):
          """
-@@ -46,7 +50,7 @@
-         entryName.focus_set()
-         self.messageInfo.pack(padx=5,pady=5)#,expand=TRUE,fill=BOTH)
-         entryName.pack(padx=5,pady=5)
--        frameButtons=Frame(self)
-+        frameButtons=Frame(self, style='RootColor.TFrame')
-         frameButtons.pack(side=BOTTOM,fill=X)
-         self.buttonOk = Button(frameButtons,text='Ok',
-                 width=8,command=self.Ok)
+@@ -55,6 +60,9 @@
+                 width=8,command=self.Cancel)
+         self.buttonCancel.grid(row=0,column=1,padx=5,pady=5)
+ 
++        if TTK:
++            frameButton['style'] = 'RootColor.TFrame'
++
+     def NameOk(self):
+         #simple validity check for a sensible
+         #ConfigParser file section name
 Index: Lib/idlelib/PyShell.py
 ===================================================================
---- Lib/idlelib/PyShell.py	(revision 63650)
+--- Lib/idlelib/PyShell.py	(revision 63734)
 +++ Lib/idlelib/PyShell.py	(working copy)
 @@ -22,14 +22,25 @@
      print>>sys.__stderr__, "** IDLE can't import Tkinter.  " \
@@ -106,7 +142,7 @@
      flist = PyShellFileList(root)
 Index: Lib/idlelib/Debugger.py
 ===================================================================
---- Lib/idlelib/Debugger.py	(revision 63650)
+--- Lib/idlelib/Debugger.py	(revision 63734)
 +++ Lib/idlelib/Debugger.py	(working copy)
 @@ -5,7 +5,10 @@
  from WindowList import ListedToplevel
@@ -121,7 +157,7 @@
  
 Index: Lib/idlelib/configDialog.py
 ===================================================================
---- Lib/idlelib/configDialog.py	(revision 63650)
+--- Lib/idlelib/configDialog.py	(revision 63734)
 +++ Lib/idlelib/configDialog.py	(working copy)
 @@ -7,7 +7,6 @@
  
@@ -131,17 +167,20 @@
  """
  from Tkinter import *
  import tkMessageBox, tkColorChooser, tkFont
-@@ -20,6 +19,9 @@
+@@ -19,7 +18,12 @@
+ from keybindingDialog import GetKeysDialog
  from configSectionNameDialog import GetCfgSectionNameDialog
  from configHelpSourceEdit import GetHelpSourceDialog
++from stylist import PoorManStyle
  
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
++TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
++if TTK:
 +    from ttk import *
 +
  class ConfigDialog(Toplevel):
  
      def __init__(self,parent,title):
-@@ -47,6 +49,7 @@
+@@ -47,6 +51,7 @@
              'Shell Stderr Text':('stderr','12'),
              }
          self.ResetChangedItems() #load initial values in changed items dict
@@ -149,22 +188,30 @@
          self.CreateWidgets()
          self.resizable(height=FALSE,width=FALSE)
          self.transient(parent)
-@@ -64,32 +67,35 @@
+@@ -64,32 +69,52 @@
          self.wm_deiconify()
          self.wait_window()
  
 +    def SetupStyles(self):
-+        style = Style(self.master)
-+        style.configure('S.TButton', padding=[6, 3])
-+        style.configure('S2.TFrame', padding=2)
-+        style.configure('Color.TFrame', background='blue')
-+        self.ttkstyle = style
++        if TTK:
++            style = Style(self.master)
++            style.configure('S.TButton', padding=[6, 3])
++            style.configure('S2.TFrame', padding=2)
++            style.configure('Color.TFrame', background='blue')
++            self.ttkstyle = style
++            self.style = lambda w, style: w.configure(style=style)
++        else:
++            self.ttkstyle = PoorManStyle(self, styles={
++                'S.TButton': {'pady': 6, 'padx': 3},
++                'S2.TFrame': {'padx': 2, 'pady': 2}
++                }, cfgstyles={'Color.TFrame': 'frameColourSet'})
++            self.style = self.ttkstyle.style_it
 +
      def CreateWidgets(self):
          self.tabPages = TabbedPageSet(self,
                  page_names=['Fonts/Tabs','Highlighting','Keys','General'])
 -        frameActionButtons = Frame(self,pady=2)
-+        frameActionButtons = Frame(self, style='RootColor.TFrame')
++        frameActionButtons = Frame(self)
          #action buttons
          self.buttonHelp = Button(frameActionButtons,text='Help',
 -                command=self.Help,takefocus=FALSE,
@@ -178,13 +225,22 @@
 -        self.buttonCancel = Button(frameActionButtons,text='Cancel',
 -                command=self.Cancel,takefocus=FALSE,
 -                padx=6,pady=3)
-+                command=self.Help, takefocus=FALSE, style='S.TButton')
++                command=self.Help, takefocus=FALSE)
 +        self.buttonOk = Button(frameActionButtons, text='Ok',
-+                command=self.Ok, takefocus=FALSE, style='S.TButton')
++                command=self.Ok, takefocus=FALSE)
 +        self.buttonApply = Button(frameActionButtons, text='Apply',
-+                command=self.Apply, takefocus=FALSE, style='S.TButton')
++                command=self.Apply, takefocus=FALSE)
 +        self.buttonCancel = Button(frameActionButtons, text='Cancel',
-+                command=self.Cancel, takefocus=FALSE, style='S.TButton')
++                command=self.Cancel, takefocus=FALSE)
++
++        # Apply styles
++        s = self.style
++        s(frameActionButtons, 'RootColor.TFrame')
++        s(self.buttonHelp, 'S.TButton')
++        s(self.buttonOk, 'S.TButton')
++        s(self.buttonApply, 'S.TButton')
++        s(self.buttonCancel, 'S.TButton')
++
          self.CreatePageFontTab()
          self.CreatePageHighlight()
          self.CreatePageKeys()
@@ -202,7 +258,7 @@
          Frame(self, height=2, borderwidth=0).pack(side=BOTTOM)
          self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH)
  
-@@ -127,7 +133,7 @@
+@@ -127,7 +152,7 @@
          frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1)
          self.labelFontSample=Label(frameFontSample,
                  text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]',
@@ -211,7 +267,7 @@
          #frameIndent
          frameIndentSize=Frame(frameIndent)
          labelSpaceNumTitle=Label(frameIndentSize, justify=LEFT,
-@@ -149,7 +155,7 @@
+@@ -149,7 +174,7 @@
          self.optMenuFontSize.pack(side=LEFT,anchor=W)
          checkFontBold.pack(side=LEFT,anchor=W,padx=20)
          frameFontSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
@@ -220,7 +276,7 @@
          #frameIndent
          frameIndentSize.pack(side=TOP,fill=X)
          labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5)
-@@ -174,7 +180,7 @@
+@@ -174,7 +199,7 @@
                                text=' Highlighting Theme ')
          #frameCustom
          self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1,
@@ -229,14 +285,15 @@
              takefocus=FALSE,highlightthickness=0,wrap=NONE)
          text=self.textHighlightSample
          text.bind('<Double-Button-1>',lambda e: 'break')
-@@ -197,12 +203,14 @@
+@@ -197,12 +222,15 @@
                  lambda event,elem=element: event.widget.winfo_toplevel()
                  .highlightTarget.set(elem))
          text.config(state=DISABLED)
 -        self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1)
 +
-+        self.frameColourSet=Frame(frameCustom, relief=SOLID, borderwidth=1,
-+            style="Color.TFrame")
++        self.frameColourSet=Frame(frameCustom, relief=SOLID, borderwidth=1)
++        self.style(self.frameColourSet, 'Color.TFrame')
++
          frameFgBg=Frame(frameCustom)
          buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :',
 -            command=self.GetColour,highlightthickness=0)
@@ -247,16 +304,21 @@
          self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite,
              value=1,text='Foreground',command=self.SetColourSampleBinding)
          self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite,
-@@ -275,7 +283,7 @@
+@@ -275,8 +303,11 @@
          self.buttonNewKeys=Button(frameCustom,text='Get New Keys for Selection',
              command=self.GetNewKeys,state=DISABLED)
          #frameKeySets
 -        frames = [Frame(frameKeySets, padx=2, pady=2, borderwidth=0)
-+        frames = [Frame(frameKeySets, borderwidth=0, style='S2.TFrame')
-                   for i in range(2)]
+-                  for i in range(2)]
++        frames = []
++        for i in range(2):
++            f = Frame(frameKeySets, borderwidth=0)
++            self.style(f, 'S2.TFrame')
++            frames.append(f)
          self.radioKeysBuiltin=Radiobutton(frames[0],variable=self.keysAreBuiltin,
              value=1,command=self.SetKeysType,text='Use a Built-in Key Set')
-@@ -748,14 +756,14 @@
+         self.radioKeysCustom=Radiobutton(frames[0],variable=self.keysAreBuiltin,
+@@ -748,14 +779,14 @@
  
      def GetColour(self):
          target=self.highlightTarget.get()
@@ -274,7 +336,7 @@
                  newTheme=self.GetNewThemeName(message)
                  if not newTheme: #user cancelled custom theme creation
                      return
-@@ -767,7 +775,7 @@
+@@ -767,7 +798,7 @@
  
      def OnNewColourSet(self):
          newColour=self.colour.get()
@@ -283,7 +345,7 @@
          if self.fgHilite.get(): plane='foreground'
          else: plane='background'
          sampleElement=self.themeElements[self.highlightTarget.get()][0]
-@@ -777,6 +785,7 @@
+@@ -777,6 +808,7 @@
          self.AddChangedItem('highlight',theme,themeElement,newColour)
  
      def GetNewThemeName(self,message):
@@ -291,7 +353,7 @@
          usedNames=(idleConf.GetSectionList('user','highlight')+
                  idleConf.GetSectionList('default','highlight'))
          newTheme=GetCfgSectionNameDialog(self,'New Custom Theme',
-@@ -846,7 +855,7 @@
+@@ -846,7 +878,7 @@
          if self.fgHilite.get(): plane='foreground'
          else: plane='background'
          colour=self.textHighlightSample.tag_cget(tag,plane)
@@ -302,7 +364,7 @@
          if self.themeIsBuiltin.get(): #a default theme
 Index: Lib/idlelib/ReplaceDialog.py
 ===================================================================
---- Lib/idlelib/ReplaceDialog.py	(revision 63650)
+--- Lib/idlelib/ReplaceDialog.py	(revision 63734)
 +++ Lib/idlelib/ReplaceDialog.py	(working copy)
 @@ -11,9 +11,12 @@
      dialog.open(text)
@@ -336,43 +398,30 @@
          self.do_find(0)
 Index: Lib/idlelib/tabbedpages.py
 ===================================================================
---- Lib/idlelib/tabbedpages.py	(revision 63650)
+--- Lib/idlelib/tabbedpages.py	(revision 63734)
 +++ Lib/idlelib/tabbedpages.py	(working copy)
-@@ -1,360 +1,34 @@
+@@ -1,490 +1,4 @@
 -"""An implementation of tabbed pages using only standard Tkinter.
-+"""Classes exported:
- 
+-
 -Originally developed for use in IDLE. Based on tabpage.py.
 -
 -Classes exported:
 -TabbedPageSet -- A Tkinter implementation of a tabbed-page widget.
 -TabSet -- A widget containing tabs (buttons) in one or more rows.
 -
-+TabbedPageSet -- A custom ttk.Notebook used by IDLE.
- """
- from Tkinter import *
-+from idlelib.configHandler import idleConf
- 
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
-+    from ttk import *
-+else:
-+    print "This will fail for now."
-+    class Notebook(object): pass
-+
- class InvalidNameError(Exception): pass
- class AlreadyExistsError(Exception): pass
- 
-+class FramePage(object):
-+    def __init__(self, notebook):
-+        self.frame = Frame(notebook)
- 
+-"""
+-from Tkinter import *
+-
+-class InvalidNameError(Exception): pass
+-class AlreadyExistsError(Exception): pass
+-
+-
 -class TabSet(Frame):
 -    """A widget containing tabs (buttons) in one or more rows.
 -
 -    Only one tab may be selected at a time.
 -
-+class TabbedPageSet(Notebook):
-     """
+-    """
 -    def __init__(self, page_set, select_command,
 -                 tabs=None, n_rows=1, max_tabs_per_row=5,
 -                 expand_tabs=False, **kw):
@@ -645,21 +694,20 @@
 -    Constains set of 'pages' (or 'panes') with tabs above for selecting which
 -    page is displayed. Only one page will be displayed at a time.
 -
-     Pages may be accessed through the 'pages' attribute, which is a dictionary
-     of pages, using the name given as the key. A page is an instance of a
+-    Pages may be accessed through the 'pages' attribute, which is a dictionary
+-    of pages, using the name given as the key. A page is an instance of a
 -    subclass of Tk's Frame widget.
-+    subclass of ttk's Frame widget.
- 
+-
 -    The page widgets will be created (and destroyed when required) by the
 -    TabbedPageSet. Do not call the page's pack/place/grid/destroy methods.
 -
-     Pages may be added or removed at any time using the add_page() and
-     remove_page() methods.
+-    Pages may be added or removed at any time using the add_page() and
+-    remove_page() methods.
 -
-     """
+-    """
 -    class Page(object):
 -        """Abstract base class for TabbedPageSet's pages.
- 
+-
 -        Subclasses must override the _show() and _hide() methods.
 -
 -        """
@@ -710,14 +758,13 @@
 -    def __init__(self, parent, page_names=None, page_class=PageLift,
 -                 n_rows=1, max_tabs_per_row=5, expand_tabs=False,
 -                 **kw):
-+    def __init__(self, master, page_names=None, **kw):
-         """Constructor arguments:
- 
-         page_names -- A list of strings, each will be the dictionary key to a
-@@ -362,56 +36,13 @@
-         specified in the desired page order. The first page will be the default
-         and first active page. If page_names is None or empty, the
-         TabbedPageSet will be initialized empty.
+-        """Constructor arguments:
+-
+-        page_names -- A list of strings, each will be the dictionary key to a
+-        page's widget, and the name displayed on the page's tab. Should be
+-        specified in the desired page order. The first page will be the default
+-        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 TabSet which will
 -        manage the tabs. See TabSet's docs for details.
@@ -739,18 +786,15 @@
 -          unpacked (i.e. pack_forget). This mechanism may also cause the
 -          TabbedPageSet to resize when the page is changed.
 -
-         """
+-        """
 -        Frame.__init__(self, parent, **kw)
-+        Notebook.__init__(self, master, **kw)
- 
+-
 -        self.page_class = page_class
-         self.pages = {}
+-        self.pages = {}
 -        self._pages_order = []
 -        self._current_page = None
 -        self._default_page = None
-+        for name in page_names:
-+            self.add_page(name)
- 
+-
 -        self.columnconfigure(0, weight=1)
 -        self.rowconfigure(1, weight=1)
 -
@@ -771,35 +815,29 @@
 -
 -        self.change_page(self._default_page)
 -
-     def add_page(self, page_name):
-         """Add a new page with the name given in page_name."""
-         if not page_name:
-@@ -420,62 +51,32 @@
-             raise AlreadyExistsError(
-                 "TabPage named '%s' already exists" % page_name)
- 
+-    def add_page(self, page_name):
+-        """Add a new page with the name given in page_name."""
+-        if not page_name:
+-            raise InvalidNameError("Invalid TabPage name: '%s'" % page_name)
+-        if page_name in self.pages:
+-            raise AlreadyExistsError(
+-                "TabPage named '%s' already exists" % page_name)
+-
 -        self.pages[page_name] = self.page_class(self.pages_frame)
 -        self._pages_order.append(page_name)
 -        self._tab_set.add_tab(page_name)
-+        fpage = FramePage(self)
-+        self.pages[page_name] = fpage
-+        self.add(fpage.frame, text=page_name, padding=6)
- 
+-
 -        if len(self.pages) == 1: # adding first page
 -            self._default_page = page_name
 -            self.change_page(page_name)
-+        # workaround for bug #1878298 at tktoolkit sf bug tracker
-+        self.event_generate('<Expose>')
- 
-     def remove_page(self, page_name):
+-
+-    def remove_page(self, page_name):
 -        """Destroy the page whose name is given in page_name."""
-         if not page_name in self.pages:
-             raise KeyError("No such TabPage: '%s" % page_name)
- 
+-        if not page_name in self.pages:
+-            raise KeyError("No such TabPage: '%s" % page_name)
+-
 -        self._pages_order.remove(page_name)
-+        self.forget(self.index(self.pages[page_name].frame))
-+        del self.pages[page_name]
- 
+-
 -        # handle removing last remaining, default, or currently shown page
 -        if len(self._pages_order) > 0:
 -            if page_name == self._default_page:
@@ -807,9 +845,7 @@
 -                self._default_page = self._pages_order[0]
 -        else:
 -            self._default_page = None
-+        # workaround for bug #1878298 at tktoolkit sf bug tracker
-+        self.event_generate('<Expose>')
- 
+-
 -        if page_name == self._current_page:
 -            self.change_page(self._default_page)
 -
@@ -834,65 +870,76 @@
 -
 -        self._tab_set.set_selected_tab(page_name)
 -
- if __name__ == '__main__':
-     # test dialog
-     root=Tk()
+-if __name__ == '__main__':
+-    # test dialog
+-    root=Tk()
 -    tabPage=TabbedPageSet(root, page_names=['Foobar','Baz'], n_rows=0,
 -                          expand_tabs=False,
 -                          )
-+    style = Style()
-+    style.configure('C.TLabel', padding=20)
-+    tabPage=TabbedPageSet(root, page_names=['Foobar','Baz'])
-     tabPage.pack(side=TOP, expand=TRUE, fill=BOTH)
+-    tabPage.pack(side=TOP, expand=TRUE, fill=BOTH)
 -    Label(tabPage.pages['Foobar'].frame, text='Foo', pady=20).pack()
 -    Label(tabPage.pages['Foobar'].frame, text='Bar', pady=20).pack()
-+    Label(tabPage.pages['Foobar'].frame, text='Foo', style='C.TLabel').pack()
-+    Label(tabPage.pages['Foobar'].frame, text='Bar', style='C.TLabel').pack()
-     Label(tabPage.pages['Baz'].frame, text='Baz').pack()
-     entryPgName=Entry(root)
-     buttonAdd=Button(root, text='Add Page',
+-    Label(tabPage.pages['Baz'].frame, text='Baz').pack()
+-    entryPgName=Entry(root)
+-    buttonAdd=Button(root, text='Add Page',
+-            command=lambda:tabPage.add_page(entryPgName.get()))
+-    buttonRemove=Button(root, text='Remove Page',
+-            command=lambda:tabPage.remove_page(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)
+-    root.mainloop()
++try:
++    from idlelib.tabbedpages_new import TabbedPageSet
++except ImportError:
++    from idlelib.tabbedpages_old import TabbedPageSet
 Index: Lib/idlelib/keybindingDialog.py
 ===================================================================
---- Lib/idlelib/keybindingDialog.py	(revision 63650)
+--- Lib/idlelib/keybindingDialog.py	(revision 63734)
 +++ Lib/idlelib/keybindingDialog.py	(working copy)
-@@ -5,6 +5,11 @@
+@@ -5,6 +5,12 @@
  import tkMessageBox
  import string
  
 +from idlelib.configHandler import idleConf
 +
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
++TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
++if TTK:
 +    from ttk import *
 +
  class GetKeysDialog(Toplevel):
      def __init__(self,parent,title,action,currentKeySequences):
          """
-@@ -48,7 +53,7 @@
-     def CreateWidgets(self):
-         frameMain = Frame(self,borderwidth=2,relief=SUNKEN)
-         frameMain.pack(side=TOP,expand=TRUE,fill=BOTH)
--        frameButtons=Frame(self)
-+        frameButtons=Frame(self, style='RootColor.TFrame')
-         frameButtons.pack(side=BOTTOM,fill=X)
-         self.buttonOK = Button(frameButtons,text='OK',
-                 width=8,command=self.OK)
+@@ -124,6 +130,9 @@
+                  "separated by a space, eg., <Alt-v> <Meta-v>." )
+         labelHelpAdvanced.grid(row=0,column=0,sticky=NSEW)
+ 
++        if TTK:
++            frameButtons['style'] = 'RootColor.TFrame'
++
+     def SetModifiersForPlatform(self):
+         """Determine list of names of key modifiers for this platform.
+ 
 Index: Lib/idlelib/configHelpSourceEdit.py
 ===================================================================
---- Lib/idlelib/configHelpSourceEdit.py	(revision 63650)
+--- Lib/idlelib/configHelpSourceEdit.py	(revision 63734)
 +++ Lib/idlelib/configHelpSourceEdit.py	(working copy)
-@@ -6,7 +6,11 @@
+@@ -6,7 +6,12 @@
  from Tkinter import *
  import tkMessageBox
  import tkFileDialog
 +from idlelib.configHandler import idleConf
  
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
++TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
++if TTK:
 +    from ttk import *
 +
  class GetHelpSourceDialog(Toplevel):
      def __init__(self, parent, title, menuItem='', filePath=''):
          """Get menu entry and url/ local file location for Additional Help
-@@ -25,6 +29,7 @@
+@@ -25,6 +30,7 @@
          self.protocol("WM_DELETE_WINDOW", self.Cancel)
          self.parent = parent
          self.result = None
@@ -900,12 +947,7 @@
          self.CreateWidgets()
          self.menu.set(menuItem)
          self.path.set(filePath)
-@@ -64,11 +69,11 @@
-         browseButton = Button(self.frameMain, text='Browse', width=8,
-                               command=self.browseFile)
-         browseButton.pack(pady=3)
--        frameButtons = Frame(self)
-+        frameButtons = Frame(self, style='RootColor.TFrame')
+@@ -68,11 +74,14 @@
          frameButtons.pack(side=BOTTOM, fill=X)
          self.buttonOk = Button(frameButtons, text='OK',
                                 width=8, default=ACTIVE,  command=self.Ok)
@@ -914,9 +956,16 @@
          self.buttonCancel = Button(frameButtons, text='Cancel',
                                     width=8, command=self.Cancel)
          self.buttonCancel.grid(row=0, column=1, padx=5, pady=5)
+ 
++        if TTK:
++            frameButtons['style'] = 'RootColor.TFrame'
++
+     def browseFile(self):
+         filetypes = [
+             ("HTML Files", "*.htm *.html", "TEXT"),
 Index: Lib/idlelib/GrepDialog.py
 ===================================================================
---- Lib/idlelib/GrepDialog.py	(revision 63650)
+--- Lib/idlelib/GrepDialog.py	(revision 63734)
 +++ Lib/idlelib/GrepDialog.py	(working copy)
 @@ -4,7 +4,11 @@
  from Tkinter import *
@@ -977,7 +1026,7 @@
 -            self.top.withdraw()
 Index: Lib/idlelib/EditorWindow.py
 ===================================================================
---- Lib/idlelib/EditorWindow.py	(revision 63650)
+--- Lib/idlelib/EditorWindow.py	(revision 63734)
 +++ Lib/idlelib/EditorWindow.py	(working copy)
 @@ -365,7 +365,7 @@
          self.menudict = menudict = {}
@@ -990,9 +1039,9 @@
          if sys.platform == 'darwin' and '.framework' in sys.executable:
 Index: Lib/idlelib/aboutDialog.py
 ===================================================================
---- Lib/idlelib/aboutDialog.py	(revision 63650)
+--- Lib/idlelib/aboutDialog.py	(revision 63734)
 +++ Lib/idlelib/aboutDialog.py	(working copy)
-@@ -1,13 +1,15 @@
+@@ -1,13 +1,17 @@
 -"""About Dialog for IDLE
 -
 -"""
@@ -1004,15 +1053,17 @@
  import textView
  import idlever
  
++from idlelib.stylist import PoorManStyle
 +from idlelib.configHandler import idleConf
 +
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
++TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
++if TTK:
 +    from ttk import *
 +
  class AboutDialog(Toplevel):
      """Modal about dialog for idle
  
-@@ -15,10 +17,16 @@
+@@ -15,10 +19,13 @@
      def __init__(self,parent,title):
          Toplevel.__init__(self, parent)
          self.configure(borderwidth=5)
@@ -1021,75 +1072,86 @@
                                    parent.winfo_rooty()+30))
          self.bg = "#707070"
          self.fg = "#ffffff"
-+
-+        style = Style()
-+        style.configure('Color.TLabel', foreground=self.fg, background=self.bg)
-+        style.configure('Color.TFrame', background=self.bg)
-+
++ 
++        self.SetupStyles()
          self.CreateWidgets()
          self.resizable(height=FALSE, width=FALSE)
          self.title(title)
-@@ -31,40 +39,36 @@
+@@ -31,40 +38,44 @@
          self.bind('<Escape>',self.Ok) #dismiss dialog
          self.wait_window()
  
++    def SetupStyles(self):
++        if TTK:
++            style = Style(self.master)
++            style.configure('Color.TLabel', foreground=self.fg,
++                            background=self.bg)
++            style.configure('Color.TFrame', background=self.bg)
++            self.ttkstyle = style
++            self.style = lambda w, style: w.configure(style=style)
++        else:
++            self.style = PoorManStyle(self,
++                styles={'Color.TLabel': {'fg': self.fg, 'bg': self.bg},
++                        'Color.TFrame': {'bg': self.bg}}).style_it
 +
      def CreateWidgets(self):
          frameMain = Frame(self, borderwidth=2, relief=SUNKEN)
--        frameButtons = Frame(self)
+         frameButtons = Frame(self)
 -        frameButtons.pack(side=BOTTOM, fill=X)
-+        frameButtons = Frame(self, style='RootColor.TFrame')
 +        frameButtons.pack(side=BOTTOM, pady=3)
          frameMain.pack(side=TOP, expand=TRUE, fill=BOTH)
-         self.buttonOk = Button(frameButtons, text='Close',
-                                command=self.Ok)
+-        self.buttonOk = Button(frameButtons, text='Close',
+-                               command=self.Ok)
 -        self.buttonOk.pack(padx=5, pady=5)
 -        #self.picture = Image('photo', data=self.pictureData)
 -        frameBg = Frame(frameMain, bg=self.bg)
++        self.buttonOk = Button(frameButtons, text='Close', command=self.Ok)
 +        self.buttonOk.pack()
-+        frameBg = Frame(frameMain, style='Color.TFrame')
++        frameBg = Frame(frameMain)
          frameBg.pack(expand=TRUE, fill=BOTH)
 -        labelTitle = Label(frameBg, text='IDLE', fg=self.fg, bg=self.bg,
-+        labelTitle = Label(frameBg, text='IDLE', style='Color.TLabel',
-                            font=('courier', 24, 'bold'))
+-                           font=('courier', 24, 'bold'))
++        labelTitle = Label(frameBg, text='IDLE', font=('courier', 24, 'bold'))
          labelTitle.grid(row=0, column=0, sticky=W, padx=10, pady=10)
 -        #labelPicture = Label(frameBg, text='[picture]')
 -        #image=self.picture, bg=self.bg)
 -        #labelPicture.grid(row=1, column=1, sticky=W, rowspan=2,
 -        #                  padx=0, pady=3)
          byline = "Python's Integrated DeveLopment Environment" + 5*'\n'
-         labelDesc = Label(frameBg, text=byline, justify=LEFT,
+-        labelDesc = Label(frameBg, text=byline, justify=LEFT,
 -                          fg=self.fg, bg=self.bg)
-+                          style='Color.TLabel')
++        labelDesc = Label(frameBg, text=byline, justify=LEFT)
          labelDesc.grid(row=2, column=0, sticky=W, columnspan=3, padx=10, pady=5)
          labelEmail = Label(frameBg, text='email:  idle-dev at python.org',
 -                           justify=LEFT, fg=self.fg, bg=self.bg)
-+                           justify=LEFT, style='Color.TLabel')
++                           justify=LEFT)
          labelEmail.grid(row=6, column=0, columnspan=2,
                          sticky=W, padx=10, pady=0)
          labelWWW = Label(frameBg, text='www:  http://www.python.org/idle/',
 -                         justify=LEFT, fg=self.fg, bg=self.bg)
-+                         justify=LEFT, style='Color.TLabel')
++                         justify=LEFT)
          labelWWW.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0)
-         Frame(frameBg, borderwidth=1, relief=SUNKEN,
+-        Frame(frameBg, borderwidth=1, relief=SUNKEN,
 -              height=2, bg=self.bg).grid(row=8, column=0, sticky=EW,
-+              height=2, style='Color.TFrame').grid(row=8, column=0, sticky=EW,
-                                          columnspan=3, padx=5, pady=5)
+-                                         columnspan=3, padx=5, pady=5)
++        fbg = Frame(frameBg, borderwidth=1, relief=SUNKEN,  height=2)
++        fbg.grid(row=8, column=0, sticky=EW, columnspan=3, padx=5, pady=5)
          labelPythonVer = Label(frameBg, text='Python version:  ' + \
 -                               sys.version.split()[0], fg=self.fg, bg=self.bg)
-+                               sys.version.split()[0], style='Color.TLabel')
++                               sys.version.split()[0])
          labelPythonVer.grid(row=9, column=0, sticky=W, padx=10, pady=0)
          # handle weird tk version num in windoze python >= 1.6 (?!?)
          tkVer = repr(TkVersion).split('.')
-@@ -73,40 +77,34 @@
+@@ -72,44 +83,50 @@
+         if tkVer[len(tkVer)-1] == '':
              tkVer[len(tkVer)-1] = '0'
          tkVer = '.'.join(tkVer)
-         labelTkVer = Label(frameBg, text='Tk version:  '+
+-        labelTkVer = Label(frameBg, text='Tk version:  '+
 -                           tkVer, fg=self.fg, bg=self.bg)
-+                           tkVer, style='Color.TLabel')
++        labelTkVer = Label(frameBg, text='Tk version:  '+ tkVer)
          labelTkVer.grid(row=9, column=1, sticky=W, padx=2, pady=0)
 -        py_button_f = Frame(frameBg, bg=self.bg)
-+        py_button_f = Frame(frameBg, style='Color.TFrame')
++        py_button_f = Frame(frameBg)
          py_button_f.grid(row=10, column=0, columnspan=2, sticky=NSEW)
          buttonLicense = Button(py_button_f, text='License', width=8,
 -                               highlightbackground=self.bg,
@@ -1103,17 +1165,17 @@
 -                               highlightbackground=self.bg,
                                 command=self.ShowPythonCredits)
          buttonCredits.pack(side=LEFT, padx=10, pady=10)
-         Frame(frameBg, borderwidth=1, relief=SUNKEN,
+-        Frame(frameBg, borderwidth=1, relief=SUNKEN,
 -              height=2, bg=self.bg).grid(row=11, column=0, sticky=EW,
 -                                         columnspan=3, padx=5, pady=5)
-+              height=2, style='Color.TFrame').grid(row=11, column=0, sticky=EW,
-+                                                   columnspan=3, padx=5, pady=5)
-         idle_v = Label(frameBg, text='IDLE version:   ' + idlever.IDLE_VERSION,
+-        idle_v = Label(frameBg, text='IDLE version:   ' + idlever.IDLE_VERSION,
 -                       fg=self.fg, bg=self.bg)
-+                       style='Color.TLabel')
++        fbg2 = Frame(frameBg, borderwidth=1, relief=SUNKEN, height=2)
++        fbg2.grid(row=11, column=0, sticky=EW, columnspan=3, padx=5, pady=5)
++        idle_v = Label(frameBg, text='IDLE version:   ' + idlever.IDLE_VERSION)
          idle_v.grid(row=12, column=0, sticky=W, padx=10, pady=0)
 -        idle_button_f = Frame(frameBg, bg=self.bg)
-+        idle_button_f = Frame(frameBg, style='Color.TFrame')
++        idle_button_f = Frame(frameBg)
          idle_button_f.grid(row=13, column=0, columnspan=3, sticky=NSEW)
          idle_about_b = Button(idle_button_f, text='README', width=8,
 -                                highlightbackground=self.bg,
@@ -1128,9 +1190,27 @@
                                  command=self.ShowIDLECredits)
          idle_credits_b.pack(side=LEFT, padx=10, pady=10)
  
++        s = self.style
++        s(frameButtons, 'RootColor.TFrame')
++        s(frameBg, 'Color.TFrame')
++        s(labelTitle, 'Color.TLabel')
++        s(labelDesc, 'Color.TLabel')
++        s(labelEmail, 'Color.TLabel')
++        s(labelWWW, 'Color.TLabel')
++        s(fbg, 'Color.TFrame')
++        s(labelPythonVer, 'Color.TLabel')
++        s(labelTkVer, 'Color.TLabel')
++        s(py_button_f, 'Color.TFrame')
++        s(fbg2, 'Color.TFrame')
++        s(idle_v, 'Color.TLabel')
++        s(idle_button_f, 'Color.TFrame')
++
+     def ShowLicense(self):
+         self.display_printer_text('About - License', license)
+ 
 Index: Lib/idlelib/config-main.def
 ===================================================================
---- Lib/idlelib/config-main.def	(revision 63650)
+--- Lib/idlelib/config-main.def	(revision 63734)
 +++ Lib/idlelib/config-main.def	(working copy)
 @@ -49,6 +49,7 @@
  print-command-posix=lpr %s
@@ -1142,7 +1222,7 @@
  width= 80
 Index: Lib/idlelib/IOBinding.py
 ===================================================================
---- Lib/idlelib/IOBinding.py	(revision 63650)
+--- Lib/idlelib/IOBinding.py	(revision 63734)
 +++ Lib/idlelib/IOBinding.py	(working copy)
 @@ -18,6 +18,9 @@
  
@@ -1156,7 +1236,7 @@
  except ImportError:
 Index: Lib/idlelib/ScrolledList.py
 ===================================================================
---- Lib/idlelib/ScrolledList.py	(revision 63650)
+--- Lib/idlelib/ScrolledList.py	(revision 63734)
 +++ Lib/idlelib/ScrolledList.py	(working copy)
 @@ -1,5 +1,9 @@
  from Tkinter import *
@@ -1170,9 +1250,9 @@
      default = "(None)"
 Index: Lib/idlelib/textView.py
 ===================================================================
---- Lib/idlelib/textView.py	(revision 63650)
+--- Lib/idlelib/textView.py	(revision 63734)
 +++ Lib/idlelib/textView.py	(working copy)
-@@ -1,10 +1,12 @@
+@@ -1,10 +1,13 @@
 -"""Simple text browser for IDLE
 +"""Simple text browser for IDLE"""
  
@@ -1183,18 +1263,14 @@
 -import tkMessageBox
 +from idlelib.configHandler import idleConf
  
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
++TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
++if TTK:
 +    from ttk import *
 +
  class TextViewer(Toplevel):
      """A simple text viewer dialog for IDLE
  
-@@ -38,19 +40,19 @@
- 
-     def CreateWidgets(self):
-         frameText = Frame(self, relief=SUNKEN, height=700)
--        frameButtons = Frame(self)
-+        frameButtons = Frame(self, style='RootColor.TFrame')
+@@ -42,17 +45,20 @@
          self.buttonOk = Button(frameButtons, text='Close',
                                 command=self.Ok, takefocus=FALSE)
          self.scrollbarView = Scrollbar(frameText, orient=VERTICAL,
@@ -1213,10 +1289,15 @@
 +        frameButtons.pack(side=BOTTOM)
          frameText.pack(side=TOP,expand=TRUE,fill=BOTH)
  
++        if TTK:
++            frameButtons['style'] = 'RootColor.TFrame'
++
      def Ok(self, event=None):
+         self.destroy()
+ 
 Index: Lib/idlelib/SearchDialogBase.py
 ===================================================================
---- Lib/idlelib/SearchDialogBase.py	(revision 63650)
+--- Lib/idlelib/SearchDialogBase.py	(revision 63734)
 +++ Lib/idlelib/SearchDialogBase.py	(working copy)
 @@ -1,35 +1,40 @@
  from Tkinter import *
@@ -1421,7 +1502,7 @@
 +            column += 1
 Index: Lib/idlelib/CallTipWindow.py
 ===================================================================
---- Lib/idlelib/CallTipWindow.py	(revision 63650)
+--- Lib/idlelib/CallTipWindow.py	(revision 63734)
 +++ Lib/idlelib/CallTipWindow.py	(working copy)
 @@ -5,7 +5,11 @@
  
@@ -1446,7 +1527,7 @@
      c=container()
 Index: Lib/idlelib/SearchDialog.py
 ===================================================================
---- Lib/idlelib/SearchDialog.py	(revision 63650)
+--- Lib/idlelib/SearchDialog.py	(revision 63734)
 +++ Lib/idlelib/SearchDialog.py	(working copy)
 @@ -21,10 +21,10 @@
      return _setup(text).find_selection(text)
@@ -1461,43 +1542,530 @@
  
      def default_command(self, event=None):
          if not self.engine.getprog():
+Index: Lib/idlelib/tabbedpages_old.py
+===================================================================
+--- Lib/idlelib/tabbedpages_old.py	(revision 0)
++++ Lib/idlelib/tabbedpages_old.py	(revision 0)
+@@ -0,0 +1,490 @@
++"""An implementation of tabbed pages using only standard Tkinter.
++
++Originally developed for use in IDLE. Based on tabpage.py.
++
++Classes exported:
++TabbedPageSet -- A Tkinter implementation of a tabbed-page widget.
++TabSet -- A widget containing tabs (buttons) in one or more rows.
++
++"""
++from Tkinter import *
++
++class InvalidNameError(Exception): pass
++class AlreadyExistsError(Exception): pass
++
++
++class TabSet(Frame):
++    """A widget containing tabs (buttons) in one or more rows.
++
++    Only one tab may be selected at a time.
++
++    """
++    def __init__(self, page_set, select_command,
++                 tabs=None, n_rows=1, max_tabs_per_row=5,
++                 expand_tabs=False, **kw):
++        """Constructor arguments:
++
++        select_command -- A callable which will be called when a tab is
++        selected. It is called with the name of the selected tab as an
++        argument.
++
++        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 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 TabSet. See
++        _arrange_tabs() for details.
++
++        max_tabs_per_row -- Used for deciding how many rows of tabs are needed,
++        when the number of rows is not constant. See _arrange_tabs() for
++        details.
++
++        """
++        Frame.__init__(self, page_set, **kw)
++        self.select_command = select_command
++        self.n_rows = n_rows
++        self.max_tabs_per_row = max_tabs_per_row
++        self.expand_tabs = expand_tabs
++        self.page_set = page_set
++
++        self._tabs = {}
++        self._tab2row = {}
++        if tabs:
++            self._tab_names = list(tabs)
++        else:
++            self._tab_names = []
++        self._selected_tab = None
++        self._tab_rows = []
++
++        self.padding_frame = Frame(self, height=2,
++                                   borderwidth=0, relief=FLAT,
++                                   background=self.cget('background'))
++        self.padding_frame.pack(side=TOP, fill=X, expand=False)
++
++        self._arrange_tabs()
++
++    def add_tab(self, tab_name):
++        """Add a new tab with the name given in tab_name."""
++        if not tab_name:
++            raise InvalidNameError("Invalid Tab name: '%s'" % tab_name)
++        if tab_name in self._tab_names:
++            raise AlreadyExistsError("Tab named '%s' already exists" %tab_name)
++
++        self._tab_names.append(tab_name)
++        self._arrange_tabs()
++
++    def remove_tab(self, 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 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:
++            raise KeyError("No such Tab: '%s" % page_name)
++
++        # deselect the current selected tab
++        if self._selected_tab is not None:
++            self._tabs[self._selected_tab].set_normal()
++        self._selected_tab = None
++
++        if tab_name is not None:
++            # activate the tab named tab_name
++            self._selected_tab = tab_name
++            tab = self._tabs[tab_name]
++            tab.set_selected()
++            # move the tab row with the selected tab to the bottom
++            tab_row = self._tab2row[tab]
++            tab_row.pack_forget()
++            tab_row.pack(side=TOP, fill=X, expand=0)
++
++    def _add_tab_row(self, tab_names, expand_tabs):
++        if not tab_names:
++            return
++
++        tab_row = Frame(self)
++        tab_row.pack(side=TOP, fill=X, expand=0)
++        self._tab_rows.append(tab_row)
++
++        for tab_name in tab_names:
++            tab = TabSet.TabButton(tab_name, self.select_command,
++                                   tab_row, self)
++            if expand_tabs:
++                tab.pack(side=LEFT, fill=X, expand=True)
++            else:
++                tab.pack(side=LEFT)
++            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):
++        while self._tab_rows:
++            tab_row = self._tab_rows.pop()
++            tab_row.destroy()
++        self._tab2row = {}
++
++    def _arrange_tabs(self):
++        """
++        Arrange the tabs in rows, in the order in which they were added.
++
++        If n_rows >= 1, this will be the number of rows used. Otherwise the
++        number of rows will be calculated according to the number of tabs and
++        max_tabs_per_row. In this case, the number of rows may change when
++        adding/removing tabs.
++
++        """
++        # remove all tabs and rows
++        while self._tabs:
++            self._tabs.popitem()[1].destroy()
++        self._reset_tab_rows()
++
++        if not self._tab_names:
++            return
++
++        if self.n_rows is not None and self.n_rows > 0:
++            n_rows = self.n_rows
++        else:
++            # calculate the required number of rows
++            n_rows = (len(self._tab_names) - 1) // self.max_tabs_per_row + 1
++
++        # 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 range(n_rows):
++            # calculate required number of tabs in this row
++            n_tabs = (len(self._tab_names) - i - 1) // (n_rows - row_index) + 1
++            tab_names = self._tab_names[i:i + n_tabs]
++            i += n_tabs
++            self._add_tab_row(tab_names, expand_tabs)
++
++        # re-select selected tab so it is properly displayed
++        selected = self._selected_tab
++        self.set_selected_tab(None)
++        if selected in self._tab_names:
++            self.set_selected_tab(selected)
++
++    class TabButton(Frame):
++        """A simple tab-like widget."""
++
++        bw = 2 # borderwidth
++
++        def __init__(self, name, select_command, tab_row, tab_set):
++            """Constructor arguments:
++
++            name -- The tab's name, which will appear in its button.
++
++            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, 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._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"""
++            self._place_masks(selected=True)
++
++        def set_normal(self):
++            """Assume normal look"""
++            self._place_masks(selected=False)
++
++        def _init_masks(self):
++            page_set = self.tab_set.page_set
++            background = page_set.pages_frame.cget('background')
++            # mask replaces the middle of the border with the background color
++            self.mask = Frame(page_set, borderwidth=0, relief=FLAT,
++                              background=background)
++            # mskl replaces the bottom-left corner of the border with a normal
++            # left border
++            self.mskl = Frame(page_set, borderwidth=0, relief=FLAT,
++                              background=background)
++            self.mskl.ml = Frame(self.mskl, borderwidth=self.bw,
++                                 relief=RAISED)
++            self.mskl.ml.place(x=0, y=-self.bw,
++                               width=2*self.bw, height=self.bw*4)
++            # mskr replaces the bottom-right corner of the border with a normal
++            # right border
++            self.mskr = Frame(page_set, borderwidth=0, relief=FLAT,
++                              background=background)
++            self.mskr.mr = Frame(self.mskr, borderwidth=self.bw,
++                                 relief=RAISED)
++
++        def _place_masks(self, selected=False):
++            height = self.bw
++            if selected:
++                height += self.bw
++
++            self.mask.place(in_=self,
++                            relx=0.0, x=0,
++                            rely=1.0, y=0,
++                            relwidth=1.0, width=0,
++                            relheight=0.0, height=height)
++
++            self.mskl.place(in_=self,
++                            relx=0.0, x=-self.bw,
++                            rely=1.0, y=0,
++                            relwidth=0.0, width=self.bw,
++                            relheight=0.0, height=height)
++
++            page_set = self.tab_set.page_set
++            if selected and ((not self.is_last_in_row) or
++                             (self.winfo_rootx() + self.winfo_width() <
++                              page_set.winfo_rootx() + page_set.winfo_width())
++                             ):
++                # for a selected tab, if its rightmost edge isn't on the
++                # rightmost edge of the page set, the right mask should be one
++                # borderwidth shorter (vertically)
++                height -= self.bw
++
++            self.mskr.place(in_=self,
++                            relx=1.0, x=0,
++                            rely=1.0, y=0,
++                            relwidth=0.0, width=self.bw,
++                            relheight=0.0, height=height)
++
++            self.mskr.mr.place(x=-self.bw, y=-self.bw,
++                               width=2*self.bw, height=height + self.bw*2)
++
++            # finally, lower the tab set so that all of the frames we just
++            # placed hide it
++            self.tab_set.lower()
++
++class TabbedPageSet(Frame):
++    """A Tkinter tabbed-pane widget.
++
++    Constains set of 'pages' (or 'panes') with tabs above for selecting which
++    page is displayed. Only one page will be displayed at a time.
++
++    Pages may be accessed through the 'pages' attribute, which is a dictionary
++    of pages, using the name given as the key. A page is an instance of a
++    subclass of Tk's Frame widget.
++
++    The page widgets will be created (and destroyed when required) by the
++    TabbedPageSet. Do not call the page's pack/place/grid/destroy methods.
++
++    Pages may be added or removed at any time using the add_page() and
++    remove_page() methods.
++
++    """
++    class Page(object):
++        """Abstract base class for TabbedPageSet's pages.
++
++        Subclasses must override the _show() and _hide() methods.
++
++        """
++        uses_grid = False
++
++        def __init__(self, page_set):
++            self.frame = Frame(page_set, borderwidth=2, relief=RAISED)
++
++        def _show(self):
++            raise NotImplementedError
++
++        def _hide(self):
++            raise NotImplementedError
++
++    class PageRemove(Page):
++        """Page class using the grid placement manager's "remove" mechanism."""
++        uses_grid = True
++
++        def _show(self):
++            self.frame.grid(row=0, column=0, sticky=NSEW)
++
++        def _hide(self):
++            self.frame.grid_remove()
++
++    class PageLift(Page):
++        """Page class using the grid placement manager's "lift" mechanism."""
++        uses_grid = True
++
++        def __init__(self, page_set):
++            super(TabbedPageSet.PageLift, self).__init__(page_set)
++            self.frame.grid(row=0, column=0, sticky=NSEW)
++            self.frame.lower()
++
++        def _show(self):
++            self.frame.lift()
++
++        def _hide(self):
++            self.frame.lower()
++
++    class PagePackForget(Page):
++        """Page class using the pack placement manager's "forget" mechanism."""
++        def _show(self):
++            self.frame.pack(fill=BOTH, expand=True)
++
++        def _hide(self):
++            self.frame.pack_forget()
++
++    def __init__(self, parent, page_names=None, page_class=PageLift,
++                 n_rows=1, max_tabs_per_row=5, expand_tabs=False,
++                 **kw):
++        """Constructor arguments:
++
++        page_names -- A list of strings, each will be the dictionary key to a
++        page's widget, and the name displayed on the page's tab. Should be
++        specified in the desired page order. The first page will be the default
++        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 TabSet which will
++        manage the tabs. See TabSet's docs for details.
++
++        page_class -- Pages can be shown/hidden using three mechanisms:
++
++        * PageLift - All pages will be rendered one on top of the other. When
++          a page is selected, it will be brought to the top, thus hiding all
++          other pages. Using this method, the TabbedPageSet will not be resized
++          when pages are switched. (It may still be resized when pages are
++          added/removed.)
++
++        * PageRemove - When a page is selected, the currently showing page is
++          hidden, and the new page shown in its place. Using this method, the
++          TabbedPageSet may resize when pages are changed.
++
++        * PagePackForget - This mechanism uses the pack placement manager.
++          When a page is shown it is packed, and when it is hidden it is
++          unpacked (i.e. pack_forget). This mechanism may also cause the
++          TabbedPageSet to resize when the page is changed.
++
++        """
++        Frame.__init__(self, parent, **kw)
++
++        self.page_class = page_class
++        self.pages = {}
++        self._pages_order = []
++        self._current_page = None
++        self._default_page = None
++
++        self.columnconfigure(0, weight=1)
++        self.rowconfigure(1, weight=1)
++
++        self.pages_frame = Frame(self)
++        self.pages_frame.grid(row=1, column=0, sticky=NSEW)
++        if self.page_class.uses_grid:
++            self.pages_frame.columnconfigure(0, weight=1)
++            self.pages_frame.rowconfigure(0, weight=1)
++
++        # the order of the following commands is important
++        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)
++        self._tab_set.grid(row=0, column=0, sticky=NSEW)
++
++        self.change_page(self._default_page)
++
++    def add_page(self, page_name):
++        """Add a new page with the name given in page_name."""
++        if not page_name:
++            raise InvalidNameError("Invalid TabPage name: '%s'" % page_name)
++        if page_name in self.pages:
++            raise AlreadyExistsError(
++                "TabPage named '%s' already exists" % page_name)
++
++        self.pages[page_name] = self.page_class(self.pages_frame)
++        self._pages_order.append(page_name)
++        self._tab_set.add_tab(page_name)
++
++        if len(self.pages) == 1: # adding first page
++            self._default_page = page_name
++            self.change_page(page_name)
++
++    def remove_page(self, page_name):
++        """Destroy the page whose name is given in page_name."""
++        if not page_name in self.pages:
++            raise KeyError("No such TabPage: '%s" % page_name)
++
++        self._pages_order.remove(page_name)
++
++        # handle removing last remaining, default, or currently shown page
++        if len(self._pages_order) > 0:
++            if page_name == self._default_page:
++                # set a new default page
++                self._default_page = self._pages_order[0]
++        else:
++            self._default_page = None
++
++        if page_name == self._current_page:
++            self.change_page(self._default_page)
++
++        self._tab_set.remove_tab(page_name)
++        page = self.pages.pop(page_name)
++        page.frame.destroy()
++
++    def change_page(self, page_name):
++        """Show the page whose name is given in page_name."""
++        if self._current_page == page_name:
++            return
++        if page_name is not None and page_name not in self.pages:
++            raise KeyError("No such TabPage: '%s'" % page_name)
++
++        if self._current_page is not None:
++            self.pages[self._current_page]._hide()
++        self._current_page = None
++
++        if page_name is not None:
++            self._current_page = page_name
++            self.pages[page_name]._show()
++
++        self._tab_set.set_selected_tab(page_name)
++
++if __name__ == '__main__':
++    # test dialog
++    root=Tk()
++    tabPage=TabbedPageSet(root, page_names=['Foobar','Baz'], n_rows=0,
++                          expand_tabs=False,
++                          )
++    tabPage.pack(side=TOP, expand=TRUE, fill=BOTH)
++    Label(tabPage.pages['Foobar'].frame, text='Foo', pady=20).pack()
++    Label(tabPage.pages['Foobar'].frame, text='Bar', pady=20).pack()
++    Label(tabPage.pages['Baz'].frame, text='Baz').pack()
++    entryPgName=Entry(root)
++    buttonAdd=Button(root, text='Add Page',
++            command=lambda:tabPage.add_page(entryPgName.get()))
++    buttonRemove=Button(root, text='Remove Page',
++            command=lambda:tabPage.remove_page(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)
++    root.mainloop()
 Index: Lib/idlelib/TreeWidget.py
 ===================================================================
---- Lib/idlelib/TreeWidget.py	(revision 63650)
+--- Lib/idlelib/TreeWidget.py	(revision 63734)
 +++ Lib/idlelib/TreeWidget.py	(working copy)
-@@ -21,6 +21,11 @@
+@@ -21,6 +21,12 @@
  import ZoomHeight
  from configHandler import idleConf
  
 +from idlelib.configHandler import idleConf
 +
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
++TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
++if TTK:
 +    from ttk import *
 +
  ICONDIR = "Icons"
  
  # Look for Icons subdirectory in the same directory as this module
-@@ -68,6 +73,10 @@
-         self.x = self.y = None
-         self.iconimages = {} # cache of PhotoImage instances for icons
- 
-+        # XXX
-+        #style = Style()
-+        #style.configure("P.TLabel", padding=2, borderwidth=0)
-+
-     def destroy(self):
-         for c in self.children[:]:
-             self.children.remove(c)
-@@ -248,7 +257,7 @@
+@@ -248,7 +254,9 @@
              label = self.label
          except AttributeError:
              # padding carefully selected (on Windows) to match Entry widget:
 -            self.label = Label(self.canvas, text=text, bd=0, padx=2, pady=2)
-+            self.label = Label(self.canvas, text=text, style='P.TLabel')
++            self.label = Label(self.canvas, text=text)
++            if not TTK:
++                self.label.configure(bd=0, padx=2, pady=2)
          theme = idleConf.GetOption('main','Theme','name')
          if self.selected:
              self.label.configure(idleConf.GetHighlight(theme, 'hilite'))
-@@ -451,6 +460,8 @@
+@@ -451,6 +459,8 @@
  
  # Testing functions
  
@@ -1506,9 +2074,99 @@
  def test():
      import PyShell
      root = Toplevel(PyShell.root)
+Index: Lib/idlelib/tabbedpages_new.py
+===================================================================
+--- Lib/idlelib/tabbedpages_new.py	(revision 0)
++++ Lib/idlelib/tabbedpages_new.py	(revision 0)
+@@ -0,0 +1,85 @@
++"""Classes exported:
++
++TabbedPageSet -- A custom ttk.Notebook used by IDLE.
++"""
++from Tkinter import *
++from ttk import *
++
++class InvalidNameError(Exception): pass
++class AlreadyExistsError(Exception): pass
++
++class FramePage(object):
++    def __init__(self, notebook):
++        self.frame = Frame(notebook)
++
++class TabbedPageSet(Notebook):
++    """
++    Pages may be accessed through the 'pages' attribute, which is a dictionary
++    of pages, using the name given as the key. A page is an instance of a
++    subclass of ttk's Frame widget.
++
++    Pages may be added or removed at any time using the add_page() and
++    remove_page() methods.
++    """
++
++    def __init__(self, master, page_names=None, **kw):
++        """Constructor arguments:
++
++        page_names -- A list of strings, each will be the dictionary key to a
++        page's widget, and the name displayed on the page's tab. Should be
++        specified in the desired page order. The first page will be the default
++        and first active page. If page_names is None or empty, the
++        TabbedPageSet will be initialized empty.
++        """
++        Notebook.__init__(self, master, **kw)
++
++        self.pages = {}
++        for name in page_names:
++            self.add_page(name)
++
++    def add_page(self, page_name):
++        """Add a new page with the name given in page_name."""
++        if not page_name:
++            raise InvalidNameError("Invalid TabPage name: '%s'" % page_name)
++        if page_name in self.pages:
++            raise AlreadyExistsError(
++                "TabPage named '%s' already exists" % page_name)
++
++        fpage = FramePage(self)
++        self.pages[page_name] = fpage
++        self.add(fpage.frame, text=page_name, padding=6)
++
++        # workaround for bug #1878298 at tktoolkit sf bug tracker
++        self.event_generate('<Expose>')
++
++    def remove_page(self, page_name):
++        if not page_name in self.pages:
++            raise KeyError("No such TabPage: '%s" % page_name)
++
++        self.forget(self.index(self.pages[page_name].frame))
++        del self.pages[page_name]
++
++        # workaround for bug #1878298 at tktoolkit sf bug tracker
++        self.event_generate('<Expose>')
++
++if __name__ == '__main__':
++    # test dialog
++    root=Tk()
++    style = Style()
++    style.configure('C.TLabel', padding=20)
++    tabPage=TabbedPageSet(root, page_names=['Foobar','Baz'])
++    tabPage.pack(side=TOP, expand=TRUE, fill=BOTH)
++    Label(tabPage.pages['Foobar'].frame, text='Foo', style='C.TLabel').pack()
++    Label(tabPage.pages['Foobar'].frame, text='Bar', style='C.TLabel').pack()
++    Label(tabPage.pages['Baz'].frame, text='Baz').pack()
++    entryPgName=Entry(root)
++    buttonAdd=Button(root, text='Add Page',
++            command=lambda:tabPage.add_page(entryPgName.get()))
++    buttonRemove=Button(root, text='Remove Page',
++            command=lambda:tabPage.remove_page(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)
++    root.mainloop()
 Index: Lib/idlelib/MultiStatusBar.py
 ===================================================================
---- Lib/idlelib/MultiStatusBar.py	(revision 63650)
+--- Lib/idlelib/MultiStatusBar.py	(revision 63734)
 +++ Lib/idlelib/MultiStatusBar.py	(working copy)
 @@ -1,5 +1,9 @@
  from Tkinter import *


More information about the Python-checkins mailing list