[Python-checkins] r65574 - sandbox/trunk/ttk-gsoc/src/tabs_ttk_and_co.diff
guilherme.polo
python-checkins at python.org
Thu Aug 7 16:15:02 CEST 2008
Author: guilherme.polo
Date: Thu Aug 7 16:15:00 2008
New Revision: 65574
Log:
Removed idle patch .diff file, I will be adding it elsewhere
Removed:
sandbox/trunk/ttk-gsoc/src/tabs_ttk_and_co.diff
Deleted: sandbox/trunk/ttk-gsoc/src/tabs_ttk_and_co.diff
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/tabs_ttk_and_co.diff Thu Aug 7 16:15:00 2008
+++ (empty file)
@@ -1,8367 +0,0 @@
-Index: ToolTip.py
-===================================================================
---- ToolTip.py (revision 63995)
-+++ ToolTip.py (revision 65541)
-@@ -1,89 +0,0 @@
--# general purpose 'tooltip' routines - currently unused in idlefork
--# (although the 'calltips' extension is partly based on this code)
--# may be useful for some purposes in (or almost in ;) the current project scope
--# Ideas gleaned from PySol
--
--from Tkinter import *
--
--class ToolTipBase:
--
-- def __init__(self, button):
-- self.button = button
-- self.tipwindow = None
-- self.id = None
-- self.x = self.y = 0
-- self._id1 = self.button.bind("<Enter>", self.enter)
-- self._id2 = self.button.bind("<Leave>", self.leave)
-- self._id3 = self.button.bind("<ButtonPress>", self.leave)
--
-- def enter(self, event=None):
-- self.schedule()
--
-- def leave(self, event=None):
-- self.unschedule()
-- self.hidetip()
--
-- def schedule(self):
-- self.unschedule()
-- self.id = self.button.after(1500, self.showtip)
--
-- def unschedule(self):
-- id = self.id
-- self.id = None
-- if id:
-- self.button.after_cancel(id)
--
-- def showtip(self):
-- if self.tipwindow:
-- return
-- # The tip window must be completely outside the button;
-- # otherwise when the mouse enters the tip window we get
-- # a leave event and it disappears, and then we get an enter
-- # event and it reappears, and so on forever :-(
-- x = self.button.winfo_rootx() + 20
-- y = self.button.winfo_rooty() + self.button.winfo_height() + 1
-- self.tipwindow = tw = Toplevel(self.button)
-- tw.wm_overrideredirect(1)
-- tw.wm_geometry("+%d+%d" % (x, y))
-- self.showcontents()
--
-- def showcontents(self, text="Your text here"):
-- # Override this in derived class
-- label = Label(self.tipwindow, text=text, justify=LEFT,
-- background="#ffffe0", relief=SOLID, borderwidth=1)
-- label.pack()
--
-- def hidetip(self):
-- tw = self.tipwindow
-- self.tipwindow = None
-- if tw:
-- tw.destroy()
--
--class ToolTip(ToolTipBase):
-- def __init__(self, button, text):
-- ToolTipBase.__init__(self, button)
-- self.text = text
-- def showcontents(self):
-- ToolTipBase.showcontents(self, self.text)
--
--class ListboxToolTip(ToolTipBase):
-- def __init__(self, button, items):
-- ToolTipBase.__init__(self, button)
-- self.items = items
-- def showcontents(self):
-- listbox = Listbox(self.tipwindow, background="#ffffe0")
-- listbox.pack()
-- for item in self.items:
-- listbox.insert(END, item)
--
--def main():
-- # Test code
-- root = Tk()
-- b = Button(root, text="Hello", command=root.destroy)
-- b.pack()
-- root.update()
-- tip = ListboxToolTip(b, ["Hello", "world"])
-- root.mainloop()
--
--if __name__ == '__main__':
-- main()
-Index: AutoCompleteWindow.py
-===================================================================
---- AutoCompleteWindow.py (revision 63995)
-+++ AutoCompleteWindow.py (revision 65541)
-@@ -1,10 +1,16 @@
- """
- An auto-completion window for IDLE, used by the AutoComplete extension
- """
--from Tkinter import *
-+from Tkinter import Toplevel, Listbox, Scrollbar, TclError
-+from Tkconstants import END, LEFT, RIGHT, BOTH, VERTICAL, Y
-+
-+import AutoComplete
- from MultiCall import MC_SHIFT
--import AutoComplete
-+from configHandler import idleConf
-
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
-+ from ttk import Scrollbar
-+
- HIDE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-hide>>"
- HIDE_SEQUENCES = ("<FocusOut>", "<ButtonPress>")
- KEYPRESS_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keypress>>"
-Index: UndoDelegator.py
-===================================================================
---- UndoDelegator.py (revision 63995)
-+++ UndoDelegator.py (revision 65541)
-@@ -1,5 +1,5 @@
- import string
--from Tkinter import *
-+
- from Delegator import Delegator
-
- #$ event <<redo>>
-@@ -74,7 +74,7 @@
- if is_saved != self.was_saved:
- self.was_saved = is_saved
- if self.saved_change_hook:
-- self.saved_change_hook()
-+ self.saved_change_hook(None)
-
- def insert(self, index, chars, tags=None):
- self.addcmd(InsertCommand(index, chars, tags))
-@@ -336,6 +336,7 @@
- return self.depth
-
- def main():
-+ from Tkinter import Tk, Text
- from Percolator import Percolator
- root = Tk()
- root.wm_protocol("WM_DELETE_WINDOW", root.quit)
-Index: Bindings.py
-===================================================================
---- Bindings.py (revision 63995)
-+++ Bindings.py (revision 65541)
-@@ -6,15 +6,16 @@
- makes it possible, for example, to define a Debug menu which is only present in
- the PythonShell window, and a Format menu which is only present in the Editor
- windows.
--
- """
- import sys
-+
- from configHandler import idleConf
-
- menudefs = [
- # underscore prefixes character to underscore
- ('file', [
- ('_New Window', '<<open-new-window>>'),
-+ ('New _Tab', '<<new-tab>>'),
- ('_Open...', '<<open-window-from-file>>'),
- ('Open _Module...', '<<open-module>>'),
- ('Class _Browser', '<<open-class-browser>>'),
-@@ -26,6 +27,7 @@
- None,
- ('Prin_t Window', '<<print-window>>'),
- None,
-+ ('Close Tab', '<<close-tab>>'),
- ('_Close', '<<close-window>>'),
- ('E_xit', '<<close-all-windows>>'),
- ]),
-@@ -80,7 +82,6 @@
- ]),
- ]
-
--import sys
- if sys.platform == 'darwin' and '.app' in sys.executable:
- # Running as a proper MacOS application bundle. This block restructures
- # the menus a little to make them conform better to the HIG.
-Index: AutoComplete.py
-===================================================================
---- AutoComplete.py (revision 63995)
-+++ AutoComplete.py (revision 65541)
-@@ -38,11 +38,11 @@
- popupwait = idleConf.GetOption("extensions", "AutoComplete",
- "popupwait", type="int", default=0)
-
-- def __init__(self, editwin=None):
-- self.editwin = editwin
-- if editwin is None: # subprocess and test
-+ def __init__(self, editpage=None):
-+ self.editpage = editpage
-+ if editpage is None: # subprocess and test
- return
-- self.text = editwin.text
-+ self.text = editpage.text
- self.autocompletewindow = None
-
- # id of delayed call, and the index of the text insert when the delayed
-@@ -120,7 +120,7 @@
- self.text.after_cancel(self._delayed_completion_id)
- self._delayed_completion_id = None
-
-- hp = HyperParser(self.editwin, "insert")
-+ hp = HyperParser(self.editpage, "insert")
- curline = self.text.get("insert linestart", "insert")
- i = j = len(curline)
- if hp.is_in_string() and (not mode or mode==COMPLETE_FILES):
-@@ -176,7 +176,7 @@
- module may be inoperative if the module was not the last to run.
- """
- try:
-- rpcclt = self.editwin.flist.pyshell.interp.rpcclt
-+ rpcclt = self.editpage.editwin.flist.pyshell.interp.rpcclt
- except:
- rpcclt = None
- if rpcclt:
-Index: configHandler.py
-===================================================================
---- configHandler.py (revision 63995)
-+++ configHandler.py (revision 65541)
-@@ -19,10 +19,10 @@
- """
- import os
- import sys
--import string
--import macosxSupport
- from ConfigParser import ConfigParser, NoOptionError, NoSectionError
-
-+import macosxSupport
-+
- class InvalidConfigType(Exception): pass
- class InvalidConfigSet(Exception): pass
- class InvalidFgBg(Exception): pass
-@@ -295,7 +295,10 @@
- back=themeDict['normal-background']
- else:
- back=themeDict[element+'-background']
-- highlight={"foreground": fore,"background": back}
-+ #bold = 0
-+ #if element + '-bold' in themeDict:
-+ # bold = themeDict[element + '-bold']
-+ highlight={"foreground": fore, "background": back}#, "font": bold}
- if not fgBg: #return dict of both colours
- return highlight
- else: #return specified colour only
-@@ -558,6 +561,10 @@
- defined here.
- """
- keyBindings={
-+ '<<close-tab>>': ['<Control-w>'],
-+ '<<new-tab>>': ['<Control-t>'],
-+ '<<next-tab>>': ['<Control-Next'],
-+ '<<prev-tab>>': ['<Control-Prior'],
- '<<copy>>': ['<Control-c>', '<Control-C>'],
- '<<cut>>': ['<Control-x>', '<Control-X>'],
- '<<paste>>': ['<Control-v>', '<Control-V>'],
-@@ -649,7 +656,7 @@
- menuItem='' #make these empty
- helpPath='' #so value won't be added to list
- else: #config entry contains ';' as expected
-- value=string.split(value,';')
-+ value = value.split(';')
- menuItem=value[0].strip()
- helpPath=value[1].strip()
- if menuItem and helpPath: #neither are empty strings
-Index: HyperParser.py
-===================================================================
---- HyperParser.py (revision 63995)
-+++ HyperParser.py (revision 65541)
-@@ -10,22 +10,22 @@
-
- import string
- import keyword
-+
- import PyParse
-+from editorpage import index2line
-
- class HyperParser:
-
-- def __init__(self, editwin, index):
-+ def __init__(self, editpage, index):
- """Initialize the HyperParser to analyze the surroundings of the given
- index.
- """
-
-- self.editwin = editwin
-- self.text = text = editwin.text
-+ self.editwin = editwin = editpage.editwin
-+ self.text = text = editpage.text
-
- parser = PyParse.Parser(editwin.indentwidth, editwin.tabwidth)
-
-- def index2line(index):
-- return int(float(index))
- lno = index2line(text.index(index))
-
- if not editwin.context_use_ps1:
-@@ -38,7 +38,7 @@
- # its status will be the same as the char before it, if should.
- parser.set_str(text.get(startatindex, stopatindex)+' \n')
- bod = parser.find_good_parse_start(
-- editwin._build_char_in_string_func(startatindex))
-+ editwin.build_char_in_string_func(startatindex))
- if bod is not None or startat == 1:
- break
- parser.set_lo(bod or 0)
-Index: ColorDelegator.py
-===================================================================
---- ColorDelegator.py (revision 63995)
-+++ ColorDelegator.py (revision 65541)
-@@ -1,8 +1,8 @@
-+import re
- import time
--import re
- import keyword
- import __builtin__
--from Tkinter import *
-+
- from Delegator import Delegator
- from configHandler import idleConf
-
-@@ -182,8 +182,11 @@
- ok = False
- while not ok:
- mark = next
-- next = self.index(mark + "+%d lines linestart" %
-- lines_to_get)
-+ # XXX self could be None here in some cases.
-+ # I can reproduce it by clicking "Apply" then "Ok"
-+ # quickly in the config dialog (while editing a not so
-+ # small file).
-+ next = self.index(mark + "+%d lines linestart" % lines_to_get)
- lines_to_get = min(lines_to_get * 2, 100)
- ok = "SYNC" in self.tag_names(next + "-1c")
- line = self.get(mark, next)
-@@ -248,6 +251,7 @@
- self.tag_remove(tag, "1.0", "end")
-
- def main():
-+ from Tkinter import Tk, Text
- from Percolator import Percolator
- root = Tk()
- root.wm_protocol("WM_DELETE_WINDOW", root.quit)
-Index: configSectionNameDialog.py
-===================================================================
---- configSectionNameDialog.py (revision 63995)
-+++ configSectionNameDialog.py (revision 65541)
-@@ -2,96 +2,111 @@
- Dialog that allows user to specify a new config file section name.
- Used to get new highlight theme and keybinding set names.
- """
--from Tkinter import *
-+from Tkinter import Toplevel, Entry, Frame, Label, Button, StringVar
-+from Tkconstants import TOP, BOTTOM, RIGHT, BOTH, SUNKEN, X
- import tkMessageBox
-
-+from configHandler import idleConf
-+
-+TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
-+if TTK:
-+ from ttk import Entry, Frame, Label, Button
-+
- class GetCfgSectionNameDialog(Toplevel):
-- def __init__(self,parent,title,message,usedNames):
-+ def __init__(self, parent, title, message, usedNames):
- """
- message - string, informational message to display
- usedNames - list, list of names already in use for validity check
- """
- Toplevel.__init__(self, parent)
- self.configure(borderwidth=5)
-- self.resizable(height=FALSE,width=FALSE)
-+ self.resizable(height=False, width=False)
- self.title(title)
- self.transient(parent)
- self.grab_set()
- self.protocol("WM_DELETE_WINDOW", self.Cancel)
- self.parent = parent
-- self.message=message
-- self.usedNames=usedNames
-- self.result=''
-+ self.message = message
-+ self.usedNames = usedNames
-+ self.result = ''
- self.CreateWidgets()
- self.withdraw() #hide while setting geometry
- self.update_idletasks()
-- #needs to be done here so that the winfo_reqwidth is valid
-- self.messageInfo.config(width=self.frameMain.winfo_reqwidth())
- self.geometry("+%d+%d" %
-- ((parent.winfo_rootx()+((parent.winfo_width()/2)
-- -(self.winfo_reqwidth()/2)),
-- parent.winfo_rooty()+((parent.winfo_height()/2)
-- -(self.winfo_reqheight()/2)) )) ) #centre dialog over parent
-+ ((parent.winfo_rootx() + ((parent.winfo_width() / 2)
-+ - (self.winfo_reqwidth() / 2)),
-+ parent.winfo_rooty() + ((parent.winfo_height() / 2)
-+ - (self.winfo_reqheight() / 2)) )) ) #centre dialog over parent
- self.deiconify() #geometry set, unhide
- self.wait_window()
-
- def CreateWidgets(self):
-- self.name=StringVar(self)
-- self.fontSize=StringVar(self)
-- self.frameMain = Frame(self,borderwidth=2,relief=SUNKEN)
-- self.frameMain.pack(side=TOP,expand=TRUE,fill=BOTH)
-- self.messageInfo=Message(self.frameMain,anchor=W,justify=LEFT,padx=5,pady=5,
-- text=self.message)#,aspect=200)
-- entryName=Entry(self.frameMain,textvariable=self.name,width=30)
-+ self.name = StringVar(self)
-+ self.fontSize = StringVar(self)
-+ self.frameMain = Frame(self, borderwidth=2, relief=SUNKEN)
-+ self.messageInfo = Label(self.frameMain, text=self.message)
-+ entryName = Entry(self.frameMain, textvariable=self.name, width=30)
-+ frameButtons = Frame(self)
-+ self.buttonOk = Button(frameButtons, text='Ok', command=self.Ok)
-+ self.buttonCancel = Button(frameButtons, text='Cancel',
-+ command=self.Cancel)
-+
- entryName.focus_set()
-- self.messageInfo.pack(padx=5,pady=5)#,expand=TRUE,fill=BOTH)
-- entryName.pack(padx=5,pady=5)
-- frameButtons=Frame(self)
-- frameButtons.pack(side=BOTTOM,fill=X)
-- self.buttonOk = Button(frameButtons,text='Ok',
-- width=8,command=self.Ok)
-- self.buttonOk.grid(row=0,column=0,padx=5,pady=5)
-- self.buttonCancel = Button(frameButtons,text='Cancel',
-- width=8,command=self.Cancel)
-- self.buttonCancel.grid(row=0,column=1,padx=5,pady=5)
-
-+ self.frameMain.pack(side=TOP, expand=True, fill=BOTH)
-+ self.messageInfo.pack(padx=5, pady=5)
-+ entryName.pack(padx=5, pady=5)
-+ frameButtons.pack(side=BOTTOM, fill=X)
-+ self.buttonOk.pack(padx=1, pady=5, side=RIGHT)
-+ self.buttonCancel.pack(pady=5, padx=5, side=RIGHT)
-+
-+ if TTK:
-+ self.messageInfo['padding'] = 5
-+ frameButtons['style'] = 'RootColor.TFrame'
-+ else:
-+ self.messageInfo.configure(padx=5, pady=5)
-+
- def NameOk(self):
- #simple validity check for a sensible
- #ConfigParser file section name
-- nameOk=1
-- name=self.name.get()
-+ nameOk = 1
-+ name = self.name.get()
- name.strip()
-+
- if not name: #no name specified
- tkMessageBox.showerror(title='Name Error',
-- message='No name specified.', parent=self)
-- nameOk=0
-- elif len(name)>30: #name too long
-+ message='No name specified.', parent=self)
-+ nameOk = 0
-+ elif len(name) > 30: #name too long
- tkMessageBox.showerror(title='Name Error',
-- message='Name too long. It should be no more than '+
-- '30 characters.', parent=self)
-+ message=('Name too long. It should be no more than '
-+ '30 characters.'), parent=self)
- nameOk=0
- elif name in self.usedNames:
- tkMessageBox.showerror(title='Name Error',
- message='This name is already in use.', parent=self)
- nameOk=0
-+
- return nameOk
-
- def Ok(self, event=None):
- if self.NameOk():
-- self.result=self.name.get().strip()
-+ self.result = self.name.get().strip()
- self.destroy()
-
- def Cancel(self, event=None):
-- self.result=''
-+ self.result = ''
- self.destroy()
-
- if __name__ == '__main__':
-+ from Tkinter import Tk
- #test the dialog
-- root=Tk()
- def run():
-- keySeq=''
-- dlg=GetCfgSectionNameDialog(root,'Get Name',
-- 'The information here should need to be word wrapped. Test.')
-+ keySeq = ''
-+ dlg = GetCfgSectionNameDialog(root, 'Get Name',
-+ 'The information here should need to be word wrapped. Test.', [])
- print dlg.result
-- Button(root,text='Dialog',command=run).pack()
-+
-+ root=Tk()
-+ Button(root, text='Dialog', command=run).pack()
- root.mainloop()
-Index: stylist.py
-===================================================================
---- stylist.py (revision 0)
-+++ stylist.py (revision 65541)
-@@ -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: ZoomHeight.py
-===================================================================
---- ZoomHeight.py (revision 63995)
-+++ ZoomHeight.py (revision 65541)
-@@ -12,11 +12,11 @@
- ])
- ]
-
-- def __init__(self, editwin):
-- self.editwin = editwin
-+ def __init__(self, editpage):
-+ self.editpage = editpage
-
- def zoom_height_event(self, event):
-- top = self.editwin.top
-+ top = self.editpage.editwin.top
- zoom_height(top)
-
- def zoom_height(top):
-Index: PyShell.py
-===================================================================
---- PyShell.py (revision 63995)
-+++ PyShell.py (revision 65541)
-@@ -1,40 +1,50 @@
- #! /usr/bin/env python
--
- import os
--import os.path
-+import re
- import sys
-+import time
-+import types
- import string
- import getopt
--import re
- import socket
--import time
-+import linecache
- import threading
--import traceback
--import types
--import macosxSupport
--
--import linecache
- from code import InteractiveInterpreter
-
- try:
-- from Tkinter import *
-+ from Tkinter import Tk, Toplevel, TclError
-+ from Tkconstants import END
- except ImportError:
- print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
- "Your Python may not be configured for Tk. **"
- sys.exit(1)
-+try:
-+ from ttk import Style
-+ TTK = 1
-+except ImportError:
-+ print >> sys.stderr, "** IDLE can't import ttk."
-+ TTK = 0
-+
- import tkMessageBox
-
--from EditorWindow import EditorWindow, fixwordbreaks
--from FileList import FileList
--from ColorDelegator import ColorDelegator
--from UndoDelegator import UndoDelegator
--from OutputWindow import OutputWindow
-+import macosxSupport
- from configHandler import idleConf
--import idlever
-
-+# store ttk availability
-+idleConf.SetOption('main', 'General', 'use-ttk', str(TTK))
-+idleConf.SaveUserCfgFiles()
-+
- import rpc
-+import utils
-+import idlever
- import Debugger
-+import IOBinding
- import RemoteDebugger
-+from FileList import FileList
-+from OutputWindow import OutputWindow
-+from EditorWindow import EditorWindow, fixwordbreaks
-+from UndoDelegator import UndoDelegator
-+from ColorDelegator import ColorDelegator
-
- IDENTCHARS = string.ascii_letters + string.digits + "_"
- LOCALHOST = '127.0.0.1'
-@@ -55,18 +65,20 @@
- except ImportError:
- pass
- else:
-- def idle_showwarning(message, category, filename, lineno):
-+ def idle_showwarning(message, category, filename, lineno, line=None):
- file = warning_stream
- try:
-- file.write(warnings.formatwarning(message, category, filename, lineno))
-+ file.write(warnings.formatwarning(message, category, filename,
-+ lineno, line))
- except IOError:
- pass ## file (probably __stderr__) is invalid, warning dropped.
- warnings.showwarning = idle_showwarning
-- def idle_formatwarning(message, category, filename, lineno):
-+ def idle_formatwarning(message, category, filename, lineno, line=None):
- """Format warnings the IDLE way"""
- s = "\nWarning (from warnings module):\n"
- s += ' File \"%s\", line %s\n' % (filename, lineno)
-- line = linecache.getline(filename, lineno).strip()
-+ if line is None:
-+ line = linecache.getline(filename, lineno).strip()
- if line:
- s += " %s\n" % line
- s += "%s: %s\n>>> " % (category.__name__, message)
-@@ -100,58 +112,67 @@
- class PyShellEditorWindow(EditorWindow):
- "Regular text edit window in IDLE, supports breakpoints"
-
-+ rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
-+ ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
-+
- def __init__(self, *args):
-- self.breakpoints = []
- EditorWindow.__init__(self, *args)
-- self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
-- self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
-- self.text.bind("<<open-python-shell>>", self.flist.open_shell)
-
- self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
-- 'breakpoints.lst')
-+ 'breakpoints.lst')
-+ self.top.bind('<<tab-created>>', self.__configure_new_tab)
-+ self.__configure_new_tab()
-+
-+ def __configure_new_tab(self, event=None):
-+ page = self.text_notebook.last_page().editpage
-+ page.breakpoints = []
-+ text = page.text
-+
-+ text.bind("<<set-breakpoint-here>>",
-+ utils.callback(self._set_breakpoint_here, text, page))
-+ text.bind("<<clear-breakpoint-here>>",
-+ utils.callback(self._clear_breakpoint_here, text, page))
-+ text.bind("<<open-python-shell>>", self.flist.open_shell)
-+
- # whenever a file is changed, restore breakpoints
-- if self.io.filename: self.restore_file_breaks()
-- def filename_changed_hook(old_hook=self.io.filename_change_hook,
-+ if page.io.filename:
-+ self.restore_file_breaks(text, page)
-+
-+ def filename_changed_hook(old_hook=page.io.filename_change_hook,
- self=self):
-- self.restore_file_breaks()
-+ self.restore_file_breaks(text, page)
- old_hook()
-- self.io.set_filename_change_hook(filename_changed_hook)
-+ page.io.set_filename_change_hook(filename_changed_hook)
-
-- rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
-- ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
--
-- def set_breakpoint(self, lineno):
-- text = self.text
-- filename = self.io.filename
-+ def set_breakpoint(self, lineno, text, page):
-+ filename = page.io.filename
- text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
- try:
-- i = self.breakpoints.index(lineno)
-+ i = page.breakpoints.index(lineno)
- except ValueError: # only add if missing, i.e. do once
-- self.breakpoints.append(lineno)
-+ page.breakpoints.append(lineno)
- try: # update the subprocess debugger
- debug = self.flist.pyshell.interp.debugger
- debug.set_breakpoint_here(filename, lineno)
- except: # but debugger may not be active right now....
- pass
-
-- def set_breakpoint_here(self, event=None):
-- text = self.text
-- filename = self.io.filename
-+ def _set_breakpoint_here(self, event=None, text=None, page=None):
-+ filename = page.io.filename
- if not filename:
- text.bell()
- return
- lineno = int(float(text.index("insert")))
-- self.set_breakpoint(lineno)
-+ self.set_breakpoint(lineno, text, page)
-
-- def clear_breakpoint_here(self, event=None):
-- text = self.text
-- filename = self.io.filename
-+ def _clear_breakpoint_here(self, event=None, text=None, page=None):
-+ filename = page.io.filename
- if not filename:
- text.bell()
- return
- lineno = int(float(text.index("insert")))
- try:
-- self.breakpoints.remove(lineno)
-+ page.breakpoints.remove(lineno)
- except:
- pass
- text.tag_remove("BREAK", "insert linestart",\
-@@ -163,13 +184,17 @@
- pass
-
- def clear_file_breaks(self):
-- if self.breakpoints:
-- text = self.text
-- filename = self.io.filename
-+ for page in self.text_notebook.pages.itervalues():
-+ page = page.editpage
-+ text = page.text
-+ filename = page.io.filename
-+
-+ if not page.breakpoints:
-+ continue
- if not filename:
- text.bell()
-- return
-- self.breakpoints = []
-+ continue
-+ page.breakpoints = []
- text.tag_remove("BREAK", "1.0", END)
- try:
- debug = self.flist.pyshell.interp.debugger
-@@ -177,7 +202,7 @@
- except:
- pass
-
-- def store_file_breaks(self):
-+ def store_file_breaks(self, page):
- "Save breakpoints when file is saved"
- # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
- # be run. The breaks are saved at that time. If we introduce
-@@ -200,8 +225,8 @@
- # debugger is loaded) is updated during the save, the visible
- # breaks stay synched with the subprocess even if one of these
- # unexpected breakpoint deletions occurs.
-- breaks = self.breakpoints
-- filename = self.io.filename
-+ breaks = page.breakpoints
-+ filename = page.io.filename
- try:
- lines = open(self.breakpointPath,"r").readlines()
- except IOError:
-@@ -210,49 +235,42 @@
- for line in lines:
- if not line.startswith(filename + '='):
- new_file.write(line)
-- self.update_breakpoints()
-- breaks = self.breakpoints
-+ self.update_breakpoints(page)
-+ breaks = page.breakpoints
- if breaks:
- new_file.write(filename + '=' + str(breaks) + '\n')
- new_file.close()
-
-- def restore_file_breaks(self):
-- self.text.update() # this enables setting "BREAK" tags to be visible
-- filename = self.io.filename
-+ def restore_file_breaks(self, text, page):
-+ text.update() # this enables setting "BREAK" tags to be visible
-+ filename = page.io.filename
- if filename is None:
- return
- if os.path.isfile(self.breakpointPath):
-- lines = open(self.breakpointPath,"r").readlines()
-+ lines = open(self.breakpointPath, "r").readlines()
- for line in lines:
- if line.startswith(filename + '='):
- breakpoint_linenumbers = eval(line[len(filename)+1:])
- for breakpoint_linenumber in breakpoint_linenumbers:
-- self.set_breakpoint(breakpoint_linenumber)
-+ self.set_breakpoint(breakpoint_linenumber, text, page)
-
-- def update_breakpoints(self):
-- "Retrieves all the breakpoints in the current window"
-- text = self.text
-+ def update_breakpoints(self, page):
-+ "Retrieves all the breakpoints in the current page"
-+ text = page.text
- ranges = text.tag_ranges("BREAK")
- linenumber_list = self.ranges_to_linenumbers(ranges)
-- self.breakpoints = linenumber_list
-+ page.breakpoints = linenumber_list
-
- def ranges_to_linenumbers(self, ranges):
- lines = []
- for index in range(0, len(ranges), 2):
-- lineno = int(float(ranges[index]))
-- end = int(float(ranges[index+1]))
-+ lineno = int(float(str(ranges[index])))
-+ end = int(float(str(ranges[index+1])))
- while lineno < end:
- lines.append(lineno)
- lineno += 1
- return lines
-
--# XXX 13 Dec 2002 KBK Not used currently
--# def saved_change_hook(self):
--# "Extend base method - clear breaks if module is modified"
--# if not self.get_saved():
--# self.clear_file_breaks()
--# EditorWindow.saved_change_hook(self)
--
- def _close(self):
- "Extend base method - clear breaks when module is closed"
- self.clear_file_breaks()
-@@ -589,7 +607,6 @@
- self.save_warnings_filters = warnings.filters[:]
- warnings.filterwarnings(action="error", category=SyntaxWarning)
- if isinstance(source, types.UnicodeType):
-- import IOBinding
- try:
- source = source.encode(IOBinding.encoding)
- except UnicodeError:
-@@ -814,30 +831,47 @@
- flist = PyShellFileList(root)
- #
- OutputWindow.__init__(self, flist, None, None)
-+ # remove things related to tabs. The window running the shell is
-+ # considered special enough to have a single window for it.
-+
-+ # remove tabs area
-+ if TTK:
-+ self.text_notebook['style'] = 'PyShell.TNotebook'
-+ style = Style(self.top)
-+ style.layout('PyShell.TNotebook.Tab', [('null', '')])
-+ else:
-+ self.text_notebook._tab_set.grid_forget()
-+
-+ # remove commands related to tab
-+ if 'file' in self.menudict:
-+ menu = self.menudict['file']
-+ curr_entry = None
-+ i = 0
-+ while True:
-+ last_entry, curr_entry = curr_entry, menu.entryconfigure(i)
-+ if last_entry == curr_entry:
-+ break
-+
-+ if 'label' in curr_entry and 'Tab' in curr_entry['label'][-1]:
-+ if 'New' in ' '.join(curr_entry['label'][-1]):
-+ menu.delete(i)
-+ i += 1
-+ self.text.unbind('<<new-tab>>')
-+ #self.text.unbind('<<close-tab>>')
-+
- #
--## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
- self.usetabs = True
- # indentwidth must be 8 when using tabs. See note in EditorWindow:
- self.indentwidth = 8
- self.context_use_ps1 = True
- #
-- text = self.text
-- text.configure(wrap="char")
-- text.bind("<<newline-and-indent>>", self.enter_callback)
-- text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
-- text.bind("<<interrupt-execution>>", self.cancel_callback)
-- text.bind("<<end-of-file>>", self.eof_callback)
-- text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
-- text.bind("<<toggle-debugger>>", self.toggle_debugger)
-- text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
-- if use_subprocess:
-- text.bind("<<view-restart>>", self.view_restart_mark)
-- text.bind("<<restart-shell>>", self.restart_shell)
-- #
-+ self.wtext = None
-+ self.textpage = None
-+ self.__configure_new_tab()
-+
- self.save_stdout = sys.stdout
- self.save_stderr = sys.stderr
- self.save_stdin = sys.stdin
-- import IOBinding
- self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
- self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
- self.console = PseudoFile(self, "console", IOBinding.encoding)
-@@ -845,11 +879,37 @@
- sys.stdout = self.stdout
- sys.stderr = self.stderr
- sys.stdin = self
-- #
-- self.history = self.History(self.text)
-- #
-+
- self.pollinterval = 50 # millisec
-
-+ if TTK:
-+ self.set_theme(Style(self.root))
-+
-+ def __configure_new_tab(self):
-+ # select the last page (the one added)
-+ page = self.text_notebook.last_page().editpage
-+ self.wtext = text = page.text
-+ self.textpage = page
-+
-+ text.configure(wrap="char")
-+ text.bind("<<newline-and-indent>>",
-+ utils.callback(self._enter_callback, text))
-+ text.bind("<<plain-newline-and-indent>>",
-+ utils.callback(self._linefeed_callback, text))
-+ text.bind("<<interrupt-execution>>",
-+ utils.callback(self._cancel_callback, text))
-+ text.bind("<<end-of-file>>",
-+ utils.callback(self._eof_callback, text))
-+ text.bind("<<toggle-debugger>>", self._toggle_debugger)
-+ text.bind("<<toggle-jit-stack-viewer>>", self._toggle_jit_stack_viewer)
-+ text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
-+ if use_subprocess:
-+ text.bind("<<view-restart>>",
-+ utils.callback(self._view_restart_mark, text))
-+ text.bind("<<restart-shell>>", self.restart_shell)
-+
-+ page.history = self.History(text)
-+
- def get_standard_extension_names(self):
- return idleConf.GetExtensions(shell_only=True)
-
-@@ -866,11 +926,11 @@
- def get_warning_stream(self):
- return warning_stream
-
-- def toggle_debugger(self, event=None):
-+ def _toggle_debugger(self, event=None):
- if self.executing:
- tkMessageBox.showerror("Don't debug now",
- "You can only toggle the debugger when idle",
-- master=self.text)
-+ master=self.text_notebook)
- self.set_debugger_indicator()
- return "break"
- else:
-@@ -884,7 +944,7 @@
- db = self.interp.getdebugger()
- self.setvar("<<toggle-debugger>>", not not db)
-
-- def toggle_jit_stack_viewer(self, event=None):
-+ def _toggle_jit_stack_viewer(self, event=None):
- pass # All we need is the variable
-
- def close_debugger(self):
-@@ -930,7 +990,7 @@
- "Kill?",
- "The program is still running!\n Do you want to kill it?",
- default="ok",
-- parent=self.text)
-+ parent=self.text_notebook)
- if response is False:
- return "cancel"
- if self.reading:
-@@ -938,7 +998,7 @@
- self.canceled = True
- self.closing = True
- # Wait for poll_subprocess() rescheduling to stop
-- self.text.after(2 * self.pollinterval, self.close2)
-+ self.text_notebook.after(2 * self.pollinterval, self.close2)
-
- def close2(self):
- return EditorWindow.close(self)
-@@ -956,7 +1016,9 @@
- self.interp = None
- self.console = None
- self.flist.pyshell = None
-- self.history = None
-+ for page in self.text_notebook.pages.itervalues():
-+ page.editpage.history = None
-+
- EditorWindow._close(self)
-
- def ispythonsource(self, filename):
-@@ -996,38 +1058,12 @@
- Tkinter._default_root = None # 03Jan04 KBK What's this?
- return True
-
-- def readline(self):
-- save = self.reading
-- try:
-- self.reading = 1
-- self.top.mainloop() # nested mainloop()
-- finally:
-- self.reading = save
-- line = self.text.get("iomark", "end-1c")
-- if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
-- line = "\n"
-- if isinstance(line, unicode):
-- import IOBinding
-- try:
-- line = line.encode(IOBinding.encoding)
-- except UnicodeError:
-- pass
-- self.resetoutput()
-- if self.canceled:
-- self.canceled = 0
-- if not use_subprocess:
-- raise KeyboardInterrupt
-- if self.endoffile:
-- self.endoffile = 0
-- line = ""
-- return line
--
- def isatty(self):
- return True
-
-- def cancel_callback(self, event=None):
-+ def _cancel_callback(self, event=None, text=None):
- try:
-- if self.text.compare("sel.first", "!=", "sel.last"):
-+ if text.compare("sel.first", "!=", "sel.last"):
- return # Active selection -- always use default binding
- except:
- pass
-@@ -1047,11 +1083,11 @@
- self.top.quit() # exit the nested mainloop() in readline()
- return "break"
-
-- def eof_callback(self, event):
-+ def _eof_callback(self, event, text):
- if self.executing and not self.reading:
- return # Let the default binding (delete next char) take over
-- if not (self.text.compare("iomark", "==", "insert") and
-- self.text.compare("insert", "==", "end-1c")):
-+ if not (text.compare("iomark", "==", "insert") and
-+ text.compare("insert", "==", "end-1c")):
- return # Let the default binding (delete next char) take over
- if not self.executing:
- self.resetoutput()
-@@ -1062,24 +1098,24 @@
- self.top.quit()
- return "break"
-
-- def linefeed_callback(self, event):
-+ def _linefeed_callback(self, event, text):
- # Insert a linefeed without entering anything (still autoindented)
- if self.reading:
-- self.text.insert("insert", "\n")
-- self.text.see("insert")
-+ text.insert("insert", "\n")
-+ text.see("insert")
- else:
- self.newline_and_indent_event(event)
- return "break"
-
-- def enter_callback(self, event):
-+ def _enter_callback(self, event, text):
- if self.executing and not self.reading:
- return # Let the default binding (insert '\n') take over
- # If some text is selected, recall the selection
- # (but only if this before the I/O mark)
- try:
-- sel = self.text.get("sel.first", "sel.last")
-+ sel = text.get("sel.first", "sel.last")
- if sel:
-- if self.text.compare("sel.last", "<=", "iomark"):
-+ if text.compare("sel.last", "<=", "iomark"):
- self.recall(sel, event)
- return "break"
- except:
-@@ -1087,51 +1123,52 @@
- # If we're strictly before the line containing iomark, recall
- # the current line, less a leading prompt, less leading or
- # trailing whitespace
-- if self.text.compare("insert", "<", "iomark linestart"):
-+ if text.compare("insert", "<", "iomark linestart"):
- # Check if there's a relevant stdin range -- if so, use it
-- prev = self.text.tag_prevrange("stdin", "insert")
-- if prev and self.text.compare("insert", "<", prev[1]):
-- self.recall(self.text.get(prev[0], prev[1]), event)
-+ prev = text.tag_prevrange("stdin", "insert")
-+ if prev and text.compare("insert", "<", prev[1]):
-+ self.recall(text.get(prev[0], prev[1]), event)
- return "break"
-- next = self.text.tag_nextrange("stdin", "insert")
-- if next and self.text.compare("insert lineend", ">=", next[0]):
-- self.recall(self.text.get(next[0], next[1]), event)
-+ next = text.tag_nextrange("stdin", "insert")
-+ if next and text.compare("insert lineend", ">=", next[0]):
-+ self.recall(text.get(next[0], next[1]), event)
- return "break"
- # No stdin mark -- just get the current line, less any prompt
-- indices = self.text.tag_nextrange("console", "insert linestart")
-+ indices = text.tag_nextrange("console", "insert linestart")
- if indices and \
-- self.text.compare(indices[0], "<=", "insert linestart"):
-- self.recall(self.text.get(indices[1], "insert lineend"), event)
-+ text.compare(indices[0], "<=", "insert linestart"):
-+ self.recall(text.get(indices[1], "insert lineend"), event)
- else:
-- self.recall(self.text.get("insert linestart", "insert lineend"), event)
-+ self.recall(text.get("insert linestart", "insert lineend"),
-+ event)
- return "break"
- # If we're between the beginning of the line and the iomark, i.e.
- # in the prompt area, move to the end of the prompt
-- if self.text.compare("insert", "<", "iomark"):
-- self.text.mark_set("insert", "iomark")
-+ if text.compare("insert", "<", "iomark"):
-+ text.mark_set("insert", "iomark")
- # If we're in the current input and there's only whitespace
- # beyond the cursor, erase that whitespace first
-- s = self.text.get("insert", "end-1c")
-+ s = text.get("insert", "end-1c")
- if s and not s.strip():
-- self.text.delete("insert", "end-1c")
-+ text.delete("insert", "end-1c")
- # If we're in the current input before its last line,
- # insert a newline right at the insert point
-- if self.text.compare("insert", "<", "end-1c linestart"):
-+ if text.compare("insert", "<", "end-1c linestart"):
- self.newline_and_indent_event(event)
- return "break"
- # We're in the last line; append a newline and submit it
-- self.text.mark_set("insert", "end-1c")
-+ text.mark_set("insert", "end-1c")
- if self.reading:
-- self.text.insert("insert", "\n")
-- self.text.see("insert")
-+ text.insert("insert", "\n")
-+ text.see("insert")
- else:
- self.newline_and_indent_event(event)
-- self.text.tag_add("stdin", "iomark", "end-1c")
-- self.text.update_idletasks()
-+ text.tag_add("stdin", "iomark", "end-1c")
-+ text.update_idletasks()
- if self.reading:
- self.top.quit() # Break out of recursive mainloop() in raw_input()
- else:
-- self.runit()
-+ self._runit(text)
- return "break"
-
- def recall(self, s, event):
-@@ -1139,15 +1176,15 @@
- s = re.sub(r'^\s*\n', '' , s)
- s = re.sub(r'\n\s*$', '', s)
- lines = s.split('\n')
-- self.text.undo_block_start()
-+ self.wtext.undo_block_start()
- try:
-- self.text.tag_remove("sel", "1.0", "end")
-- self.text.mark_set("insert", "end-1c")
-- prefix = self.text.get("insert linestart", "insert")
-+ self.wtext.tag_remove("sel", "1.0", "end")
-+ self.wtext.mark_set("insert", "end-1c")
-+ prefix = self.wtext.get("insert linestart", "insert")
- if prefix.rstrip().endswith(':'):
- self.newline_and_indent_event(event)
-- prefix = self.text.get("insert linestart", "insert")
-- self.text.insert("insert", lines[0].strip())
-+ prefix = self.wtext.get("insert linestart", "insert")
-+ self.wtext.insert("insert", lines[0].strip())
- if len(lines) > 1:
- orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
- new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
-@@ -1155,13 +1192,13 @@
- if line.startswith(orig_base_indent):
- # replace orig base indentation with new indentation
- line = new_base_indent + line[len(orig_base_indent):]
-- self.text.insert('insert', '\n'+line.rstrip())
-+ self.wtext.insert('insert', '\n'+line.rstrip())
- finally:
-- self.text.see("insert")
-- self.text.undo_block_stop()
-+ self.wtext.see("insert")
-+ self.wtext.undo_block_stop()
-
-- def runit(self):
-- line = self.text.get("iomark", "end-1c")
-+ def _runit(self, text):
-+ line = text.get("iomark", "end-1c")
- # Strip off last newline and surrounding whitespace.
- # (To allow you to hit return twice to end a statement.)
- i = len(line)
-@@ -1179,18 +1216,18 @@
- return self.interp.remote_stack_viewer()
- try:
- sys.last_traceback
-- except:
-+ except AttributeError:
- tkMessageBox.showerror("No stack trace",
- "There is no stack trace yet.\n"
- "(sys.last_traceback is not defined)",
-- master=self.text)
-+ master=self.text_notebook)
- return
- from StackViewer import StackBrowser
- sv = StackBrowser(self.root, self.flist)
-
-- def view_restart_mark(self, event=None):
-- self.text.see("iomark")
-- self.text.see("restart")
-+ def _view_restart_mark(self, event=None, text=None):
-+ text.see("iomark")
-+ text.see("restart")
-
- def restart_shell(self, event=None):
- self.interp.restart_subprocess()
-@@ -1202,25 +1239,30 @@
- except:
- s = ""
- self.console.write(s)
-- self.text.mark_set("insert", "end-1c")
-+
-+ curr_page = self.current_page
-+ if not curr_page:
-+ return
-+
-+ curr_page.text.mark_set("insert", "end-1c")
- self.set_line_and_column()
-- self.io.reset_undo()
-+ curr_page.io.reset_undo()
-
- def resetoutput(self):
-- source = self.text.get("iomark", "end-1c")
-- if self.history:
-- self.history.history_store(source)
-- if self.text.get("end-2c") != "\n":
-- self.text.insert("end-1c", "\n")
-- self.text.mark_set("iomark", "end-1c")
-+ source = self.wtext.get("iomark", "end-1c")
-+ if self.textpage.history:
-+ self.textpage.history.history_store(source)
-+ if self.wtext.get("end-2c") != "\n":
-+ self.wtext.insert("end-1c", "\n")
-+ self.wtext.mark_set("iomark", "end-1c")
- self.set_line_and_column()
- sys.stdout.softspace = 0
-
- def write(self, s, tags=()):
- try:
-- self.text.mark_gravity("iomark", "right")
-- OutputWindow.write(self, s, tags, "iomark")
-- self.text.mark_gravity("iomark", "left")
-+ self.wtext.mark_gravity("iomark", "right")
-+ OutputWindow.write(self, s, tags, "iomark", self.wtext)
-+ self.wtext.mark_gravity("iomark", "left")
- except:
- pass
- if self.canceled:
-@@ -1381,6 +1423,19 @@
- # start editor and/or shell windows:
- root = Tk(className="Idle")
-
-+ if TTK:
-+ # create base styles used along idle files
-+ style = Style()
-+
-+ rootbg = style.map('.', 'background')
-+ fstyle = {'background': []}
-+ for sspec in rootbg:
-+ if 'active' in sspec[:-1]:
-+ fstyle['background'].append(('!disabled', sspec[-1]))
-+ break
-+ style.map('RootColor.TFrame', **fstyle)
-+ # end styles
-+
- fixwordbreaks(root)
- root.withdraw()
- flist = PyShellFileList(root)
-Index: ParenMatch.py
-===================================================================
---- ParenMatch.py (revision 63995)
-+++ ParenMatch.py (revision 65541)
-@@ -56,14 +56,13 @@
- RESTORE_SEQUENCES = ("<KeyPress>", "<ButtonPress>",
- "<Key-Return>", "<Key-BackSpace>")
-
-- def __init__(self, editwin):
-- self.editwin = editwin
-- self.text = editwin.text
-+ def __init__(self, editpage):
-+ self.editpage = editpage
-+ self.text = editpage.text
- # Bind the check-restore event to the function restore_event,
- # so that we can then use activate_restore (which calls event_add)
- # and deactivate_restore (which calls event_delete).
-- editwin.text.bind(self.RESTORE_VIRTUAL_EVENT_NAME,
-- self.restore_event)
-+ editpage.text.bind(self.RESTORE_VIRTUAL_EVENT_NAME, self.restore_event)
- self.counter = 0
- self.is_restore_active = 0
- self.set_style(self.STYLE)
-@@ -90,7 +89,7 @@
- self.set_timeout = self.set_timeout_none
-
- def flash_paren_event(self, event):
-- indices = HyperParser(self.editwin, "insert").get_surrounding_brackets()
-+ indices = HyperParser(self.editpage, "insert").get_surrounding_brackets()
- if indices is None:
- self.warn_mismatched()
- return
-@@ -103,7 +102,7 @@
- closer = self.text.get("insert-1c")
- if closer not in _openers:
- return
-- hp = HyperParser(self.editwin, "insert-1c")
-+ hp = HyperParser(self.editpage, "insert-1c")
- if not hp.is_in_code():
- return
- indices = hp.get_surrounding_brackets(_openers[closer], True)
-@@ -159,14 +158,13 @@
- if index != self.text.index("insert"):
- self.handle_restore_timer(c)
- else:
-- self.editwin.text_frame.after(CHECK_DELAY, callme, callme)
-- self.editwin.text_frame.after(CHECK_DELAY, callme, callme)
-+ self.text.master.after(CHECK_DELAY, callme, callme)
-+ self.text.master.after(CHECK_DELAY, callme, callme)
-
- def set_timeout_last(self):
- """The last highlight created will be removed after .5 sec"""
- # associate a counter with an event; only disable the "paren"
- # tag if the event is for the most recent timer.
- self.counter += 1
-- self.editwin.text_frame.after(self.FLASH_DELAY,
-- lambda self=self, c=self.counter: \
-- self.handle_restore_timer(c))
-+ self.text.master.after(self.FLASH_DELAY,
-+ lambda self=self, c=self.counter: self.handle_restore_timer(c))
-Index: config-keys.def
-===================================================================
---- config-keys.def (revision 63995)
-+++ config-keys.def (revision 65541)
-@@ -8,6 +8,10 @@
- # configuration gui.
-
- [IDLE Classic Windows]
-+close-tab=<Control-Key-w> <Control-Key-W>
-+new-tab=<Control-Key-t> <Control-Key-T>
-+next-tab=<Control-Key-Next>
-+prev-tab=<Control-Key-Prior>
- copy=<Control-Key-c> <Control-Key-C>
- cut=<Control-Key-x> <Control-Key-X>
- paste=<Control-Key-v> <Control-Key-V>
-@@ -59,6 +63,10 @@
- del-word-right=<Control-Key-Delete>
-
- [IDLE Classic Unix]
-+close-tab=<Alt-Key-w><Control-Key-w>
-+new-tab=<Alt-Key-t><Control-Key-t>
-+next-tab=<Control-Key-Next>
-+prev-tab=<Control-Key-Prior>
- copy=<Alt-Key-w> <Meta-Key-w>
- cut=<Control-Key-w>
- paste=<Control-Key-y>
-@@ -110,6 +118,10 @@
- del-word-right=<Alt-Key-d>
-
- [IDLE Classic Mac]
-+close-tab=<Control-key-w>
-+new-tab=<Control-Key-t>
-+next-tab=<Control-Key-Next>
-+prev-tab=<Control-Key-Prior>
- copy=<Command-Key-c>
- cut=<Command-Key-x>
- paste=<Command-Key-v>
-@@ -161,6 +173,10 @@
- del-word-right=<Control-Key-Delete>
-
- [IDLE Classic OSX]
-+close-tab=<Control-Key-w>
-+new-tab = <Control-Key-t>
-+next-tab=<Control-Key-Next>
-+prev-tab=<Control-Key-Prior>
- toggle-tabs = <Control-Key-t>
- interrupt-execution = <Control-Key-c>
- untabify-region = <Control-Key-6>
-Index: Debugger.py
-===================================================================
---- Debugger.py (revision 63995)
-+++ Debugger.py (revision 65541)
-@@ -1,11 +1,17 @@
- import os
- import bdb
- import types
--from Tkinter import *
-+from Tkinter import Frame, Button, Entry, Checkbutton, Label, Scrollbar, \
-+ Canvas, BooleanVar
-+from Tkconstants import W, LEFT, DISABLED, X, Y, BOTH, NW, GROOVE, RIGHT
-+
-+import macosxSupport
- from WindowList import ListedToplevel
- from ScrolledList import ScrolledList
--import macosxSupport
-+from configHandler import idleConf
-
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
-+ from ttk import Frame, Button, Checkbutton, Scrollbar
-
- class Idb(bdb.Bdb):
-
-@@ -92,7 +98,7 @@
- self.top.bind("<Escape>", self.close)
- #
- self.bframe = bframe = Frame(top)
-- self.bframe.pack(anchor="w")
-+ self.bframe.pack(anchor=W)
- self.buttons = bl = []
- #
- self.bcont = b = Button(bframe, text="Go", command=self.cont)
-@@ -107,11 +113,11 @@
- bl.append(b)
- #
- for b in bl:
-- b.configure(state="disabled")
-- b.pack(side="left")
-+ b.configure(state=DISABLED)
-+ b.pack(side=LEFT)
- #
- self.cframe = cframe = Frame(bframe)
-- self.cframe.pack(side="left")
-+ self.cframe.pack(side=LEFT)
- #
- if not self.vstack:
- self.__class__.vstack = BooleanVar(top)
-@@ -136,18 +142,18 @@
- text="Globals", command=self.show_globals, variable=self.vglobals)
- self.bglobals.grid(row=1, column=1)
- #
-- self.status = Label(top, anchor="w")
-- self.status.pack(anchor="w")
-- self.error = Label(top, anchor="w")
-- self.error.pack(anchor="w", fill="x")
-+ self.status = Label(top, anchor=W)
-+ self.status.pack(anchor=W)
-+ self.error = Label(top, anchor=W)
-+ self.error.pack(anchor=W, fill=X)
- self.errorbg = self.error.cget("background")
- #
- self.fstack = Frame(top, height=1)
-- self.fstack.pack(expand=1, fill="both")
-+ self.fstack.pack(expand=1, fill=BOTH)
- self.flocals = Frame(top)
-- self.flocals.pack(expand=1, fill="both")
-+ self.flocals.pack(expand=1, fill=BOTH)
- self.fglobals = Frame(top, height=1)
-- self.fglobals.pack(expand=1, fill="both")
-+ self.fglobals.pack(expand=1, fill=BOTH)
- #
- if self.vstack.get():
- self.show_stack()
-@@ -155,6 +161,7 @@
- self.show_locals()
- if self.vglobals.get():
- self.show_globals()
-+ #
-
- def interaction(self, message, frame, info=None):
- self.frame = frame
-@@ -313,12 +320,14 @@
- "Load PyShellEditorWindow breakpoints into subprocess debugger"
- pyshell_edit_windows = self.pyshell.flist.inversedict.keys()
- for editwin in pyshell_edit_windows:
-- filename = editwin.io.filename
-- try:
-- for lineno in editwin.breakpoints:
-- self.set_breakpoint_here(filename, lineno)
-- except AttributeError:
-- continue
-+ for page in editwin.text_notebook.pages.itervalues():
-+ editpage = page.editpage
-+ filename = editpage.io.filename
-+ try:
-+ for lineno in editpage.breakpoints:
-+ self.set_breakpoint_here(filename, lineno)
-+ except AttributeError:
-+ continue
-
- class StackViewer(ScrolledList):
-
-@@ -348,8 +357,7 @@
- funcname = code.co_name
- import linecache
- sourceline = linecache.getline(filename, lineno)
-- import string
-- sourceline = string.strip(sourceline)
-+ sourceline = sourceline.strip()
- if funcname in ("?", "", None):
- item = "%s, line %d: %s" % (modname, lineno, sourceline)
- else:
-@@ -413,24 +421,25 @@
- height = 20*len(dict) # XXX 20 == observed height of Entry widget
- self.master = master
- self.title = title
-+
- import repr
- self.repr = repr.Repr()
- self.repr.maxstring = 60
- self.repr.maxother = 60
- self.frame = frame = Frame(master)
-- self.frame.pack(expand=1, fill="both")
-- self.label = Label(frame, text=title, borderwidth=2, relief="groove")
-- self.label.pack(fill="x")
-- self.vbar = vbar = Scrollbar(frame, name="vbar")
-- vbar.pack(side="right", fill="y")
-+ self.frame.pack(expand=1, fill=BOTH)
-+ self.label = Label(frame, text=title, borderwidth=2, relief=GROOVE)
-+ self.label.pack(fill=X)
-+ vbar = Scrollbar(frame, name="vbar")
-+ vbar.pack(side=RIGHT, fill=Y)
- self.canvas = canvas = Canvas(frame,
- height=min(300, max(40, height)),
- scrollregion=(0, 0, width, height))
-- canvas.pack(side="left", fill="both", expand=1)
-+ canvas.pack(side=LEFT, fill=BOTH, expand=1)
- vbar["command"] = canvas.yview
- canvas["yscrollcommand"] = vbar.set
- self.subframe = subframe = Frame(canvas)
-- self.sfid = canvas.create_window(0, 0, window=subframe, anchor="nw")
-+ self.sfid = canvas.create_window(0, 0, window=subframe, anchor=NW)
- self.load_dict(dict)
-
- dict = -1
-@@ -458,10 +467,10 @@
- if rpc_client:
- svalue = svalue[1:-1]
- l = Label(subframe, text=name)
-- l.grid(row=row, column=0, sticky="nw")
-+ l.grid(row=row, column=0, sticky=NW)
- l = Entry(subframe, width=0, borderwidth=0)
- l.insert(0, svalue)
-- l.grid(row=row, column=1, sticky="nw")
-+ l.grid(row=row, column=1, sticky=NW)
- row = row+1
- self.dict = dict
- # XXX Could we use a <Configure> callback for the following?
-Index: configDialog.py
-===================================================================
---- configDialog.py (revision 63995)
-+++ configDialog.py (revision 65541)
-@@ -7,19 +7,30 @@
-
- Note that tab width in IDLE is currently fixed at eight due to Tk issues.
- Refer to comments in EditorWindow autoindent code for details.
--
- """
--from Tkinter import *
-+from Tkinter import Toplevel, Frame, Button, Scale, Label, LabelFrame, Text, \
-+ Listbox, Scrollbar, Checkbutton, Radiobutton, Entry, \
-+ Checkbutton, StringVar, BooleanVar, IntVar
-+from Tkconstants import LEFT, RIGHT, BOTTOM, TOP, BOTH, GROOVE, SOLID, NONE, \
-+ END, DISABLED, NSEW, Y, X, W, E, HORIZONTAL, NS, EW, \
-+ N, ANCHOR, NORMAL
- import tkMessageBox, tkColorChooser, tkFont
--import string
-
-+from stylist import PoorManStyle
-+from tabbedpages import get_tabbedpage
- from configHandler import idleConf
-+from keybindingDialog import GetKeysDialog
- from dynOptionMenuWidget import DynOptionMenu
--from tabbedpages import TabbedPageSet
--from keybindingDialog import GetKeysDialog
-+from configHelpSourceEdit import GetHelpSourceDialog
- from configSectionNameDialog import GetCfgSectionNameDialog
--from configHelpSourceEdit import GetHelpSourceDialog
-
-+TabbedPageSet = get_tabbedpage()
-+TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
-+if TTK:
-+ from ttk import Frame, Button, Checkbutton, LabelFrame, LabeledScale, \
-+ Combobox, Checkbutton, Entry, Radiobutton, Scrollbar, \
-+ Label, Style
-+
- class ConfigDialog(Toplevel):
-
- def __init__(self,parent,title):
-@@ -27,8 +38,8 @@
- self.wm_withdraw()
-
- self.configure(borderwidth=5)
-- self.geometry("+%d+%d" % (parent.winfo_rootx()+20,
-- parent.winfo_rooty()+30))
-+ self.geometry("+%d+%d" % (parent.winfo_rootx() + 20,
-+ parent.winfo_rooty() + 30))
- #Theme Elements. Each theme element key is its display name.
- #The first value of the tuple is the sample area tag name.
- #The second value is the display name list sort index.
-@@ -47,8 +58,9 @@
- 'Shell Stderr Text':('stderr','12'),
- }
- self.ResetChangedItems() #load initial values in changed items dict
-+ self.SetupStyles()
- self.CreateWidgets()
-- self.resizable(height=FALSE,width=FALSE)
-+ self.resizable(height=False, width=False)
- self.transient(parent)
- self.grab_set()
- self.protocol("WM_DELETE_WINDOW", self.Cancel)
-@@ -64,34 +76,54 @@
- self.wm_deiconify()
- self.wait_window()
-
-+ def SetupStyles(self):
-+ 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)
-+ page_names=['Fonts/Tabs','Highlighting','Keys','General'])
-+ frameActionButtons = Frame(self)
- #action buttons
- self.buttonHelp = Button(frameActionButtons,text='Help',
-- command=self.Help,takefocus=FALSE,
-- padx=6,pady=3)
-- self.buttonOk = Button(frameActionButtons,text='Ok',
-- command=self.Ok,takefocus=FALSE,
-- padx=6,pady=3)
-- self.buttonApply = Button(frameActionButtons,text='Apply',
-- command=self.Apply,takefocus=FALSE,
-- padx=6,pady=3)
-- self.buttonCancel = Button(frameActionButtons,text='Cancel',
-- command=self.Cancel,takefocus=FALSE,
-- padx=6,pady=3)
-+ command=self.Help, takefocus=False)
-+ self.buttonOk = Button(frameActionButtons, text='Ok',
-+ command=self.Ok, takefocus=False)
-+ self.buttonApply = Button(frameActionButtons, text='Apply',
-+ command=self.Apply, takefocus=False)
-+ self.buttonCancel = Button(frameActionButtons, text='Cancel',
-+ 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()
- self.CreatePageGeneral()
-- self.buttonHelp.pack(side=RIGHT,padx=5)
-- self.buttonOk.pack(side=LEFT,padx=5)
-- self.buttonApply.pack(side=LEFT,padx=5)
-- self.buttonCancel.pack(side=LEFT,padx=5)
-- frameActionButtons.pack(side=BOTTOM)
-+ self.buttonHelp.pack(side=LEFT, pady=6)
-+ self.buttonApply.pack(side=RIGHT, pady=6)
-+ self.buttonOk.pack(side=RIGHT, padx=6, pady=6)
-+ self.buttonCancel.pack(side=RIGHT, pady=6)
-+ frameActionButtons.pack(side=BOTTOM, fill=X, expand=True)
- Frame(self, height=2, borderwidth=0).pack(side=BOTTOM)
-- self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH)
-+ self.tabPages.pack(side=TOP,expand=True,fill=BOTH)
-
- def CreatePageFontTab(self):
- #tkVars
-@@ -113,8 +145,8 @@
- frameFontParam=Frame(frameFont)
- labelFontNameTitle=Label(frameFontName,justify=LEFT,
- text='Font Face :')
-- self.listFontName=Listbox(frameFontName,height=5,takefocus=FALSE,
-- exportselection=FALSE)
-+ self.listFontName=Listbox(frameFontName,height=5,takefocus=False,
-+ exportselection=False)
- self.listFontName.bind('<ButtonRelease-1>',self.OnListFontButtonRelease)
- scrollFont=Scrollbar(frameFontName)
- scrollFont.config(command=self.listFontName.yview)
-@@ -127,122 +159,143 @@
- frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1)
- self.labelFontSample=Label(frameFontSample,
- text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]',
-- justify=LEFT,font=self.editFont)
-+ justify=LEFT, font=self.editFont)
- #frameIndent
- frameIndentSize=Frame(frameIndent)
- labelSpaceNumTitle=Label(frameIndentSize, justify=LEFT,
- text='Python Standard: 4 Spaces!')
-- self.scaleSpaceNum=Scale(frameIndentSize, variable=self.spaceNum,
-- orient='horizontal',
-- tickinterval=2, from_=2, to=16)
- #widget packing
- #body
-- frameFont.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH)
-+ frameFont.pack(side=LEFT,padx=5,pady=5,expand=True,fill=BOTH)
- frameIndent.pack(side=LEFT,padx=5,pady=5,fill=Y)
- #frameFont
- frameFontName.pack(side=TOP,padx=5,pady=5,fill=X)
- frameFontParam.pack(side=TOP,padx=5,pady=5,fill=X)
- labelFontNameTitle.pack(side=TOP,anchor=W)
-- self.listFontName.pack(side=LEFT,expand=TRUE,fill=X)
-+ self.listFontName.pack(side=LEFT,expand=True,fill=X)
- scrollFont.pack(side=LEFT,fill=Y)
- labelFontSizeTitle.pack(side=LEFT,anchor=W)
- 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)
-- self.labelFontSample.pack(expand=TRUE,fill=BOTH)
-+ frameFontSample.pack(side=TOP,padx=5,pady=5,expand=True,fill=BOTH)
-+ self.labelFontSample.pack(expand=1, fill=Y)
- #frameIndent
- frameIndentSize.pack(side=TOP,fill=X)
-- labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5)
-- self.scaleSpaceNum.pack(side=TOP,padx=5,fill=X)
-+ labelSpaceNumTitle.pack(side=TOP, anchor=W, padx=5, pady=6)
-+
-+ if TTK:
-+ self.scaleSpaceNum = LabeledScale(frameIndentSize, self.spaceNum,
-+ from_=2, to=16, padding=2)
-+ else:
-+ self.scaleSpaceNum=Scale(frameIndentSize, variable=self.spaceNum,
-+ orient='horizontal', from_=2, to=16, tickinterval=2)
-+
-+ self.scaleSpaceNum.pack(side=TOP, padx=5, fill=X)
-+
- return frame
-
- def CreatePageHighlight(self):
-- self.builtinTheme=StringVar(self)
-- self.customTheme=StringVar(self)
-- self.fgHilite=BooleanVar(self)
-- self.colour=StringVar(self)
-- self.fontName=StringVar(self)
-- self.themeIsBuiltin=BooleanVar(self)
-- self.highlightTarget=StringVar(self)
-+ self.builtinTheme = StringVar(self)
-+ self.customTheme = StringVar(self)
-+ self.fgHilite = BooleanVar(self)
-+ self.colour = StringVar(self)
-+ self.fontName = StringVar(self)
-+ self.themeIsBuiltin = BooleanVar(self)
-+ self.highlightTarget = StringVar(self)
-+ #self.themeFontBold = BooleanVar(self)
- ##widget creation
- #body frame
-- frame=self.tabPages.pages['Highlighting'].frame
-+ frame = self.tabPages.pages['Highlighting'].frame
- #body section frames
-- frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE,
-- text=' Custom Highlighting ')
-- frameTheme=LabelFrame(frame,borderwidth=2,relief=GROOVE,
-- text=' Highlighting Theme ')
-+ frameCustom = LabelFrame(frame, borderwidth=2, relief=GROOVE,
-+ text=' Custom Highlighting ')
-+ frameTheme = LabelFrame(frame, borderwidth=2, relief=GROOVE,
-+ text=' Highlighting Theme ')
- #frameCustom
-- self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1,
-- font=('courier',12,''),cursor='hand2',width=21,height=10,
-- takefocus=FALSE,highlightthickness=0,wrap=NONE)
-- text=self.textHighlightSample
-- text.bind('<Double-Button-1>',lambda e: 'break')
-- text.bind('<B1-Motion>',lambda e: 'break')
-- textAndTags=(('#you can click here','comment'),('\n','normal'),
-- ('#to choose items','comment'),('\n','normal'),('def','keyword'),
-- (' ','normal'),('func','definition'),('(param):','normal'),
-- ('\n ','normal'),('"""string"""','string'),('\n var0 = ','normal'),
-- ("'string'",'string'),('\n var1 = ','normal'),("'selected'",'hilite'),
-- ('\n var2 = ','normal'),("'found'",'hit'),
-- ('\n var3 = ','normal'),('list', 'builtin'), ('(','normal'),
-- ('None', 'builtin'),(')\n\n','normal'),
-- (' error ','error'),(' ','normal'),('cursor |','cursor'),
-- ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'),
-- (' ','normal'),('stderr','stderr'),('\n','normal'))
-+ self.textHighlightSample = Text(frameCustom, relief=SOLID,
-+ borderwidth=1, font=('courier', 12, ''), cursor='hand2', width=21,
-+ height=11, takefocus=False, highlightthickness=0, wrap=NONE)
-+ text = self.textHighlightSample
-+ text.bind('<Double-Button-1>', lambda e: 'break')
-+ text.bind('<B1-Motion>', lambda e: 'break')
-+ textAndTags = (
-+ ('#you can click here','comment'), ('\n','normal'),
-+ ('#to choose items', 'comment'), ('\n', 'normal'),
-+ ('def', 'keyword'), (' ', 'normal'), ('func', 'definition'),
-+ ('(param):', 'normal'), ('\n ', 'normal'),
-+ ('"""string"""', 'string'),
-+ ('\n var0 = ','normal'), ("'string'", 'string'),
-+ ('\n var1 = ', 'normal'), ("'selected'", 'hilite'),
-+ ('\n var2 = ', 'normal'), ("'found'", 'hit'),
-+ ('\n var3 = ', 'normal'), ('list', 'builtin'), ('(', 'normal'),
-+ ('None', 'builtin'), (')\n\n', 'normal'),
-+ (' error ', 'error'), (' ', 'normal'), ('cursor |', 'cursor'),
-+ ('\n ', 'normal'), ('shell', 'console'), (' ', 'normal'),
-+ ('stdout', 'stdout'), (' ', 'normal'), ('stderr', 'stderr'),
-+ ('\n', 'normal')
-+ )
- for txTa in textAndTags:
-- text.insert(END,txTa[0],txTa[1])
-+ text.insert(END, txTa[0], txTa[1])
- for element in self.themeElements.keys():
-- text.tag_bind(self.themeElements[element][0],'<ButtonPress-1>',
-- lambda event,elem=element: event.widget.winfo_toplevel()
-- .highlightTarget.set(elem))
-+ text.tag_bind(self.themeElements[element][0], '<ButtonPress-1>',
-+ lambda event, elem=element:
-+ event.widget.winfo_toplevel().highlightTarget.set(elem))
- text.config(state=DISABLED)
-- self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1)
-- frameFgBg=Frame(frameCustom)
-- buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :',
-- command=self.GetColour,highlightthickness=0)
-- self.optMenuHighlightTarget=DynOptionMenu(self.frameColourSet,
-- self.highlightTarget,None,highlightthickness=0)#,command=self.SetHighlightTargetBinding
-- self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite,
-- value=1,text='Foreground',command=self.SetColourSampleBinding)
-- self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite,
-- value=0,text='Background',command=self.SetColourSampleBinding)
-+
-+ 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)
-+ self.optMenuHighlightTarget = DynOptionMenu(self.frameColourSet,
-+ self.highlightTarget, None)
-+ #self.optBoldText = Checkbutton(self.frameColourSet, text="Bold",
-+ # variable=self.themeFontBold)
-+ self.radioFg = Radiobutton(frameFgBg, variable=self.fgHilite,
-+ value=1, text='Foreground', command=self.SetColourSampleBinding)
-+ self.radioBg = Radiobutton(frameFgBg, variable=self.fgHilite,
-+ value=0, text='Background', command=self.SetColourSampleBinding)
- self.fgHilite.set(1)
-- buttonSaveCustomTheme=Button(frameCustom,
-- text='Save as New Custom Theme',command=self.SaveAsNewTheme)
-+ buttonSaveCustomTheme = Button(frameCustom,
-+ text='Save as New Custom Theme', command=self.SaveAsNewTheme)
- #frameTheme
-- labelTypeTitle=Label(frameTheme,text='Select : ')
-- self.radioThemeBuiltin=Radiobutton(frameTheme,variable=self.themeIsBuiltin,
-- value=1,command=self.SetThemeType,text='a Built-in Theme')
-- self.radioThemeCustom=Radiobutton(frameTheme,variable=self.themeIsBuiltin,
-- value=0,command=self.SetThemeType,text='a Custom Theme')
-- self.optMenuThemeBuiltin=DynOptionMenu(frameTheme,
-- self.builtinTheme,None,command=None)
-- self.optMenuThemeCustom=DynOptionMenu(frameTheme,
-- self.customTheme,None,command=None)
-- self.buttonDeleteCustomTheme=Button(frameTheme,text='Delete Custom Theme',
-- command=self.DeleteCustomTheme)
-+ labelTypeTitle = Label(frameTheme, text='Select : ')
-+ self.radioThemeBuiltin = Radiobutton(frameTheme,
-+ variable=self.themeIsBuiltin, value=1,
-+ command=self.SetThemeType, text='a Built-in Theme')
-+ self.radioThemeCustom = Radiobutton(frameTheme,
-+ variable=self.themeIsBuiltin, value=0,
-+ command=self.SetThemeType, text='a Custom Theme')
-+ self.optMenuThemeBuiltin = DynOptionMenu(frameTheme,
-+ self.builtinTheme, None, command=None)
-+ self.optMenuThemeCustom = DynOptionMenu(frameTheme,
-+ self.customTheme, None, command=None)
-+ self.buttonDeleteCustomTheme = Button(frameTheme,
-+ text='Delete Custom Theme', command=self.DeleteCustomTheme)
- ##widget packing
- #body
-- frameCustom.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH)
-- frameTheme.pack(side=LEFT,padx=5,pady=5,fill=Y)
-+ frameCustom.pack(side=LEFT, padx=5, pady=5, expand=True, fill=BOTH)
-+ frameTheme.pack(side=LEFT, padx=5, pady=5, fill=Y)
- #frameCustom
-- self.frameColourSet.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=X)
-- frameFgBg.pack(side=TOP,padx=5,pady=0)
-- self.textHighlightSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,
-+ self.frameColourSet.pack(side=TOP, padx=5, pady=5, expand=True, fill=X)
-+ frameFgBg.pack(side=TOP, padx=5, pady=0)
-+ self.textHighlightSample.pack(side=TOP, padx=5, pady=5, expand=True,
- fill=BOTH)
-- buttonSetColour.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=4)
-- self.optMenuHighlightTarget.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=3)
-- self.radioFg.pack(side=LEFT,anchor=E)
-- self.radioBg.pack(side=RIGHT,anchor=W)
-- buttonSaveCustomTheme.pack(side=BOTTOM,fill=X,padx=5,pady=5)
-+ buttonSetColour.pack(side=TOP, expand=True, fill=X, padx=8, pady=4)
-+ self.optMenuHighlightTarget.pack(side=LEFT, anchor=N, expand=True,
-+ fill=X, padx=8, pady=3)
-+ #self.optBoldText.pack(side=RIGHT, anchor=N, padx=8, pady=3)
-+ self.radioFg.pack(side=LEFT, anchor=E)
-+ self.radioBg.pack(side=RIGHT, anchor=W)
-+ buttonSaveCustomTheme.pack(side=BOTTOM, fill=X, padx=5, pady=5)
- #frameTheme
-- labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
-- self.radioThemeBuiltin.pack(side=TOP,anchor=W,padx=5)
-- self.radioThemeCustom.pack(side=TOP,anchor=W,padx=5,pady=2)
-- self.optMenuThemeBuiltin.pack(side=TOP,fill=X,padx=5,pady=5)
-- self.optMenuThemeCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5)
-- self.buttonDeleteCustomTheme.pack(side=TOP,fill=X,padx=5,pady=5)
-+ labelTypeTitle.pack(side=TOP, anchor=W, padx=5, pady=5)
-+ self.radioThemeBuiltin.pack(side=TOP, anchor=W, padx=5)
-+ self.radioThemeCustom.pack(side=TOP, anchor=W, padx=5, pady=2)
-+ self.optMenuThemeBuiltin.pack(side=TOP, fill=X, padx=5, pady=5)
-+ self.optMenuThemeCustom.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5)
-+ self.buttonDeleteCustomTheme.pack(side=TOP, fill=X, padx=5, pady=5)
- return frame
-
- def CreatePageKeys(self):
-@@ -265,8 +318,8 @@
- labelTargetTitle=Label(frameTarget,text='Action - Key(s)')
- scrollTargetY=Scrollbar(frameTarget)
- scrollTargetX=Scrollbar(frameTarget,orient=HORIZONTAL)
-- self.listBindings=Listbox(frameTarget,takefocus=FALSE,
-- exportselection=FALSE)
-+ self.listBindings=Listbox(frameTarget,takefocus=False,
-+ exportselection=False)
- self.listBindings.bind('<ButtonRelease-1>',self.KeyBindingSelected)
- scrollTargetY.config(command=self.listBindings.yview)
- scrollTargetX.config(command=self.listBindings.xview)
-@@ -275,8 +328,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)
-- 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')
- self.radioKeysCustom=Radiobutton(frames[0],variable=self.keysAreBuiltin,
-@@ -291,11 +347,11 @@
- text='Save as New Custom Key Set',command=self.SaveAsNewKeySet)
- ##widget packing
- #body
-- frameCustom.pack(side=BOTTOM,padx=5,pady=5,expand=TRUE,fill=BOTH)
-+ frameCustom.pack(side=BOTTOM,padx=5,pady=5,expand=True,fill=BOTH)
- frameKeySets.pack(side=BOTTOM,padx=5,pady=5,fill=BOTH)
- #frameCustom
- self.buttonNewKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5)
-- frameTarget.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH)
-+ frameTarget.pack(side=LEFT,padx=5,pady=5,expand=True,fill=BOTH)
- #frame target
- frameTarget.columnconfigure(0,weight=1)
- frameTarget.rowconfigure(1,weight=1)
-@@ -316,14 +372,16 @@
-
- def CreatePageGeneral(self):
- #tkVars
-- self.winWidth=StringVar(self)
-- self.winHeight=StringVar(self)
-- self.paraWidth=StringVar(self)
-- self.startupEdit=IntVar(self)
-- self.autoSave=IntVar(self)
-- self.encoding=StringVar(self)
-- self.userHelpBrowser=BooleanVar(self)
-- self.helpBrowser=StringVar(self)
-+ self.winWidth = StringVar(self)
-+ self.winHeight = StringVar(self)
-+ self.paraWidth = StringVar(self)
-+ self.startupEdit = IntVar(self)
-+ self.autoSave = IntVar(self)
-+ self.encoding = StringVar(self)
-+ self.themename = StringVar(self)
-+ self.fileintab = BooleanVar(self)
-+ self.userHelpBrowser = BooleanVar(self)
-+ self.helpBrowser = StringVar(self)
- #widget creation
- #body
- frame=self.tabPages.pages['General'].frame
-@@ -335,6 +393,9 @@
- frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE)
- frameParaSize=Frame(frame,borderwidth=2,relief=GROOVE)
- frameEncoding=Frame(frame,borderwidth=2,relief=GROOVE)
-+ frameModTab = Frame(frame, borderwidth=2, relief=GROOVE)
-+ if TTK:
-+ frameTheme = Frame(frame, borderwidth=2, relief=GROOVE)
- frameHelp=LabelFrame(frame,borderwidth=2,relief=GROOVE,
- text=' Additional Help Sources ')
- #frameRun
-@@ -371,12 +432,21 @@
- value="utf-8",text="UTF-8")
- radioEncNone=Radiobutton(frameEncoding,variable=self.encoding,
- value="none",text="None")
-+ # frameModTab
-+ labelMTab = Label(frameModTab, text="Open files and modules in tabs")
-+ checkMTab = Checkbutton(frameModTab, variable=self.fileintab,
-+ text="Yes")
-+ #frameTheme
-+ if TTK:
-+ labelTheme = Label(frameTheme, text="Display Theme")
-+ comboTheme = Combobox(frameTheme, textvariable=self.themename,
-+ values=self.ttkstyle.theme_names(), state='readonly')
- #frameHelp
- frameHelpList=Frame(frameHelp)
- frameHelpListButtons=Frame(frameHelpList)
- scrollHelpList=Scrollbar(frameHelpList)
-- self.listHelp=Listbox(frameHelpList,height=5,takefocus=FALSE,
-- exportselection=FALSE)
-+ self.listHelp=Listbox(frameHelpList, height=4, takefocus=False,
-+ exportselection=False)
- scrollHelpList.config(command=self.listHelp.yview)
- self.listHelp.config(yscrollcommand=scrollHelpList.set)
- self.listHelp.bind('<ButtonRelease-1>',self.HelpSourceSelected)
-@@ -393,7 +463,10 @@
- frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X)
- frameParaSize.pack(side=TOP,padx=5,pady=5,fill=X)
- frameEncoding.pack(side=TOP,padx=5,pady=5,fill=X)
-- frameHelp.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
-+ frameModTab.pack(side=TOP, padx=5, pady=5, fill=X)
-+ if TTK:
-+ frameTheme.pack(side=TOP, padx=5, pady=5, fill=X)
-+ frameHelp.pack(side=TOP,padx=5,pady=5,expand=True,fill=BOTH)
- #frameRun
- labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
- radioStartupShell.pack(side=RIGHT,anchor=W,padx=5,pady=5)
-@@ -416,14 +489,22 @@
- radioEncNone.pack(side=RIGHT,anchor=E,pady=5)
- radioEncUTF8.pack(side=RIGHT,anchor=E,pady=5)
- radioEncLocale.pack(side=RIGHT,anchor=E,pady=5)
-+ #frameModTab
-+ labelMTab.pack(side=LEFT, anchor=W, padx=5, pady=5)
-+ checkMTab.pack(side=RIGHT, anchor=E, padx=5, pady=5)
-+ #frameTheme
-+ if TTK:
-+ labelTheme.pack(side=LEFT, anchor=W, padx=5, pady=5)
-+ comboTheme.pack(side=RIGHT, anchor=E, padx=5, pady=5)
- #frameHelp
- frameHelpListButtons.pack(side=RIGHT,padx=5,pady=5,fill=Y)
-- frameHelpList.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
-+ frameHelpList.pack(side=TOP,padx=5,pady=5,expand=True,fill=BOTH)
- scrollHelpList.pack(side=RIGHT,anchor=W,fill=Y)
-- self.listHelp.pack(side=LEFT,anchor=E,expand=TRUE,fill=BOTH)
-+ self.listHelp.pack(side=LEFT,anchor=E,expand=True,fill=BOTH)
- self.buttonHelpListEdit.pack(side=TOP,anchor=W,pady=5)
- self.buttonHelpListAdd.pack(side=TOP,anchor=W)
- self.buttonHelpListRemove.pack(side=TOP,anchor=W,pady=5)
-+
- return frame
-
- def AttachVarCallbacks(self):
-@@ -432,6 +513,7 @@
- self.fontBold.trace_variable('w',self.VarChanged_fontBold)
- self.spaceNum.trace_variable('w',self.VarChanged_spaceNum)
- self.colour.trace_variable('w',self.VarChanged_colour)
-+ #self.themeFontBold.trace_variable('w', self.VarChanged_themeFontBold)
- self.builtinTheme.trace_variable('w',self.VarChanged_builtinTheme)
- self.customTheme.trace_variable('w',self.VarChanged_customTheme)
- self.themeIsBuiltin.trace_variable('w',self.VarChanged_themeIsBuiltin)
-@@ -446,18 +528,20 @@
- self.startupEdit.trace_variable('w',self.VarChanged_startupEdit)
- self.autoSave.trace_variable('w',self.VarChanged_autoSave)
- self.encoding.trace_variable('w',self.VarChanged_encoding)
-+ self.themename.trace_variable('w', self.VarChanged_themename)
-+ self.fileintab.trace_variable('w', self.VarChanged_fileintab)
-
- def VarChanged_fontSize(self,*params):
- value=self.fontSize.get()
-- self.AddChangedItem('main','EditorWindow','font-size',value)
-+ self.AddChangedItem('main','EditorPage','font-size',value)
-
- def VarChanged_fontName(self,*params):
- value=self.fontName.get()
-- self.AddChangedItem('main','EditorWindow','font',value)
-+ self.AddChangedItem('main','EditorPage','font',value)
-
- def VarChanged_fontBold(self,*params):
- value=self.fontBold.get()
-- self.AddChangedItem('main','EditorWindow','font-bold',value)
-+ self.AddChangedItem('main','EditorPage','font-bold',value)
-
- def VarChanged_spaceNum(self,*params):
- value=self.spaceNum.get()
-@@ -466,6 +550,9 @@
- def VarChanged_colour(self,*params):
- self.OnNewColourSet()
-
-+ #def VarChanged_themeFontBold(self, *params):
-+ # self.OnBoldChanged()
-+
- def VarChanged_builtinTheme(self,*params):
- value=self.builtinTheme.get()
- self.AddChangedItem('main','Theme','name',value)
-@@ -521,11 +608,11 @@
-
- def VarChanged_winWidth(self,*params):
- value=self.winWidth.get()
-- self.AddChangedItem('main','EditorWindow','width',value)
-+ self.AddChangedItem('main', 'EditorWindow', 'width', value)
-
- def VarChanged_winHeight(self,*params):
- value=self.winHeight.get()
-- self.AddChangedItem('main','EditorWindow','height',value)
-+ self.AddChangedItem('main', 'EditorWindow', 'height', value)
-
- def VarChanged_paraWidth(self,*params):
- value=self.paraWidth.get()
-@@ -541,8 +628,16 @@
-
- def VarChanged_encoding(self,*params):
- value=self.encoding.get()
-- self.AddChangedItem('main','EditorWindow','encoding',value)
-+ self.AddChangedItem('main','EditorPage','encoding',value)
-
-+ def VarChanged_themename(self, *params):
-+ value = self.themename.get()
-+ self.AddChangedItem('main', 'Theme', 'displaytheme', value)
-+
-+ def VarChanged_fileintab(self, *params):
-+ value = self.fileintab.get()
-+ self.AddChangedItem('main', 'EditorWindow', 'file-in-tab', value)
-+
- def ResetChangedItems(self):
- #When any config item is changed in this dialog, an entry
- #should be made in the relevant section (config type) of this
-@@ -552,10 +647,10 @@
- self.changedItems={'main':{},'highlight':{},'keys':{},'extensions':{}}
-
- def AddChangedItem(self,type,section,item,value):
-- value=str(value) #make sure we use a string
-+ value = str(value) #make sure we use a string
- if not self.changedItems[type].has_key(section):
-- self.changedItems[type][section]={}
-- self.changedItems[type][section][item]=value
-+ self.changedItems[type][section] = {}
-+ self.changedItems[type][section][item] = value
-
- def GetDefaultItems(self):
- dItems={'main':{},'highlight':{},'keys':{},'extensions':{}}
-@@ -653,7 +748,7 @@
- newKeys={}
- for event in prevKeys.keys(): #add key set to changed items
- eventName=event[2:-2] #trim off the angle brackets
-- binding=string.join(prevKeys[event])
-+ binding=' '.join(prevKeys[event])
- newKeys[eventName]=binding
- #handle any unsaved changes to prev key set
- if prevKeySetName in self.changedItems['keys'].keys():
-@@ -680,7 +775,7 @@
- bindNames.sort()
- self.listBindings.delete(0,END)
- for bindName in bindNames:
-- key=string.join(keySet[bindName]) #make key(s) into a string
-+ key=' '.join(keySet[bindName]) #make key(s) into a string
- bindName=bindName[2:-2] #trim off the angle brackets
- if keySetName in self.changedItems['keys'].keys():
- #handle any unsaved changes to this key set
-@@ -694,9 +789,9 @@
-
- def DeleteCustomKeys(self):
- keySetName=self.customKeys.get()
-- if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+
-- 'to delete the key set %r ?' % (keySetName),
-- parent=self):
-+ if not tkMessageBox.askyesno("Delete Key Set",
-+ "Are you sure you wish to delete the key set %r ?" % keySetName,
-+ parent=self):
- return
- #remove key set from config
- idleConf.userCfg['keys'].remove_section(keySetName)
-@@ -705,25 +800,26 @@
- #write changes
- idleConf.userCfg['keys'].Save()
- #reload user key set list
-- itemList=idleConf.GetSectionList('user','keys')
-+ itemList = idleConf.GetSectionList('user', 'keys')
- itemList.sort()
- if not itemList:
- self.radioKeysCustom.config(state=DISABLED)
-- self.optMenuKeysCustom.SetMenu(itemList,'- no custom keys -')
-+ self.optMenuKeysCustom.SetMenu(itemList, "- no custom keys -")
- else:
- self.optMenuKeysCustom.SetMenu(itemList,itemList[0])
- #revert to default key set
-- self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys','default'))
-- self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys','name'))
-+ self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys',
-+ 'default'))
-+ self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys', 'name'))
- #user can't back out of these changes, they must be applied now
- self.Apply()
- self.SetKeysType()
-
- def DeleteCustomTheme(self):
-- themeName=self.customTheme.get()
-- if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+
-- 'to delete the theme %r ?' % (themeName,),
-- parent=self):
-+ themeName = self.customTheme.get()
-+ if not tkMessageBox.askyesno("Delete Theme",
-+ "Are you sure you wish to delete the theme %r ?" % themeName,
-+ parent=self):
- return
- #remove theme from config
- idleConf.userCfg['highlight'].remove_section(themeName)
-@@ -732,30 +828,31 @@
- #write changes
- idleConf.userCfg['highlight'].Save()
- #reload user theme list
-- itemList=idleConf.GetSectionList('user','highlight')
-+ itemList = idleConf.GetSectionList('user', 'highlight')
- itemList.sort()
- if not itemList:
- self.radioThemeCustom.config(state=DISABLED)
-- self.optMenuThemeCustom.SetMenu(itemList,'- no custom themes -')
-+ self.optMenuThemeCustom.SetMenu(itemList, "- no custom themes -")
- else:
-- self.optMenuThemeCustom.SetMenu(itemList,itemList[0])
-+ self.optMenuThemeCustom.SetMenu(itemList, itemList[0])
- #revert to default theme
-- self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme','default'))
-- self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme','name'))
-+ self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme',
-+ 'default'))
-+ self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme', 'name'))
- #user can't back out of these changes, they must be applied now
- self.Apply()
- self.SetThemeType()
-
- def GetColour(self):
- target=self.highlightTarget.get()
-- prevColour=self.frameColourSet.cget('bg')
-+ prevColour = self.ttkstyle.configure('Color.TFrame', 'background')
- rgbTuplet, colourString = tkColorChooser.askcolor(parent=self,
- title='Pick new colour for : '+target,initialcolor=prevColour)
- if colourString and (colourString!=prevColour):
- #user didn't cancel, and they chose a new colour
- if self.themeIsBuiltin.get(): #current theme is a built-in
-- message=('Your changes will be saved as a new Custom Theme. '+
-- 'Enter a name for your new Custom Theme below.')
-+ message=("Your changes will be saved as a new Custom Theme. "
-+ "Enter a name for your new Custom Theme below.")
- newTheme=self.GetNewThemeName(message)
- if not newTheme: #user cancelled custom theme creation
- return
-@@ -767,16 +864,33 @@
-
- def OnNewColourSet(self):
- newColour=self.colour.get()
-- self.frameColourSet.config(bg=newColour)#set sample
-+ self.ttkstyle.configure('Color.TFrame', background=newColour)
- if self.fgHilite.get(): plane='foreground'
- else: plane='background'
- sampleElement=self.themeElements[self.highlightTarget.get()][0]
-- self.textHighlightSample.tag_config(sampleElement, **{plane:newColour})
-+ self.textHighlightSample.tag_config(sampleElement, **{plane: newColour})
- theme=self.customTheme.get()
- themeElement=sampleElement+'-'+plane
- self.AddChangedItem('highlight',theme,themeElement,newColour)
-
-+ #def OnBoldChanged(self):
-+ # bold = self.themeFontBold.get() and tkFont.BOLD or tkFont.NORMAL
-+ # sampleElement = self.themeElements[self.highlightTarget.get()][0]
-+
-+ # #fontName = self.fontName.get()
-+ # #self.textHighlightSample.tag_config(sampleElement,
-+ # # font=(fontName, self.fontSize.get(), bold))
-+
-+ # self.textHighlightSample.tag_config(sampleElement,
-+ # font=('courier', 12, bold))
-+
-+ # theme = self.customTheme.get()
-+ # themeElement = "%s-%s" % (sampleElement, 'bold')
-+ # self.AddChangedItem('highlight', theme, themeElement,
-+ # (bold == tkFont.BOLD) and 1 or 0)
-+
- def GetNewThemeName(self,message):
-+ # XXX idle bug here
- usedNames=(idleConf.GetSectionList('user','highlight')+
- idleConf.GetSectionList('default','highlight'))
- newTheme=GetCfgSectionNameDialog(self,'New Custom Theme',
-@@ -835,37 +949,45 @@
- self.radioFg.config(state=NORMAL)
- self.radioBg.config(state=NORMAL)
- self.fgHilite.set(1)
-+ #tag = self.themeElements[self.highlightTarget.get()][0]
-+ #font = self.textHighlightSample.tag_cget(tag, 'font')
-+ #if font:
-+ # self.themeFontBold.set(font.split()[2] == tkFont.BOLD)
-+ #else:
-+ # self.themeFontBold.set(0)
- self.SetColourSample()
-
- def SetColourSampleBinding(self,*args):
- self.SetColourSample()
-
- def SetColourSample(self):
-- #set the colour smaple area
-- tag=self.themeElements[self.highlightTarget.get()][0]
-- if self.fgHilite.get(): plane='foreground'
-- else: plane='background'
-- colour=self.textHighlightSample.tag_cget(tag,plane)
-- self.frameColourSet.config(bg=colour)
-+ # set the colour sample area
-+ tag = self.themeElements[self.highlightTarget.get()][0]
-+ if self.fgHilite.get():
-+ plane = 'foreground'
-+ else:
-+ plane = 'background'
-+ colour = self.textHighlightSample.tag_cget(tag, plane)
-+ self.ttkstyle.configure('Color.TFrame', background=colour)
-
- def PaintThemeSample(self):
- if self.themeIsBuiltin.get(): #a default theme
-- theme=self.builtinTheme.get()
-+ theme = self.builtinTheme.get()
- else: #a user theme
-- theme=self.customTheme.get()
-+ theme = self.customTheme.get()
- for elementTitle in self.themeElements.keys():
-- element=self.themeElements[elementTitle][0]
-- colours=idleConf.GetHighlight(theme,element)
-- if element=='cursor': #cursor sample needs special painting
-- colours['background']=idleConf.GetHighlight(theme,
-- 'normal', fgBg='bg')
-+ element = self.themeElements[elementTitle][0]
-+ colours = idleConf.GetHighlight(theme, element)
-+ if element == 'cursor': #cursor sample needs special painting
-+ colours['background'] = idleConf.GetHighlight(theme,
-+ 'normal', fgBg='bg')
- #handle any unsaved changes to this theme
- if theme in self.changedItems['highlight'].keys():
-- themeDict=self.changedItems['highlight'][theme]
-- if themeDict.has_key(element+'-foreground'):
-- colours['foreground']=themeDict[element+'-foreground']
-- if themeDict.has_key(element+'-background'):
-- colours['background']=themeDict[element+'-background']
-+ themeDict = self.changedItems['highlight'][theme]
-+ if themeDict.has_key(element + '-foreground'):
-+ colours['foreground'] = themeDict[element + '-foreground']
-+ if themeDict.has_key(element + '-background'):
-+ colours['background'] = themeDict[element + '-background']
- self.textHighlightSample.tag_config(element, **colours)
- self.SetColourSample()
-
-@@ -917,7 +1039,7 @@
- self.changedItems['main']['HelpFiles'] = {}
- for num in range(1,len(self.userHelpList)+1):
- self.AddChangedItem('main','HelpFiles',str(num),
-- string.join(self.userHelpList[num-1][:2],';'))
-+ ';'.join(self.userHelpList[num - 1][:2]))
-
- def LoadFontCfg(self):
- ##base editor font selection list
-@@ -925,7 +1047,7 @@
- fonts.sort()
- for font in fonts:
- self.listFontName.insert(END,font)
-- configuredFont=idleConf.GetOption('main','EditorWindow','font',
-+ configuredFont=idleConf.GetOption('main','EditorPage','font',
- default='courier')
- lc_configuredFont = configuredFont.lower()
- self.fontName.set(lc_configuredFont)
-@@ -936,13 +1058,13 @@
- self.listFontName.select_set(currentFontIndex)
- self.listFontName.select_anchor(currentFontIndex)
- ##font size dropdown
-- fontSize=idleConf.GetOption('main','EditorWindow','font-size',
-+ fontSize=idleConf.GetOption('main', 'EditorPage', 'font-size',
- default='10')
- self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14',
- '16','18','20','22'),fontSize )
- ##fontWeight
-- self.fontBold.set(idleConf.GetOption('main','EditorWindow',
-- 'font-bold',default=0,type='bool'))
-+ self.fontBold.set(idleConf.GetOption('main', 'EditorPage',
-+ 'font-bold', default=0, type='bool'))
- ##font sample
- self.SetFontSample()
-
-@@ -954,37 +1076,41 @@
-
- def LoadThemeCfg(self):
- ##current theme type radiobutton
-- self.themeIsBuiltin.set(idleConf.GetOption('main','Theme','default',
-- type='bool',default=1))
-+ self.themeIsBuiltin.set(idleConf.GetOption('main', 'Theme', 'default',
-+ type='bool', default=1))
- ##currently set theme
-- currentOption=idleConf.CurrentTheme()
-+ currentOption = idleConf.CurrentTheme()
- ##load available theme option menus
- if self.themeIsBuiltin.get(): #default theme selected
-- itemList=idleConf.GetSectionList('default','highlight')
-+ itemList = idleConf.GetSectionList('default', 'highlight')
- itemList.sort()
-- self.optMenuThemeBuiltin.SetMenu(itemList,currentOption)
-- itemList=idleConf.GetSectionList('user','highlight')
-+ self.optMenuThemeBuiltin.SetMenu(itemList, currentOption)
-+ itemList = idleConf.GetSectionList('user', 'highlight')
- itemList.sort()
- if not itemList:
- self.radioThemeCustom.config(state=DISABLED)
-- self.customTheme.set('- no custom themes -')
-+ self.customTheme.set("- no custom themes -")
- else:
- self.optMenuThemeCustom.SetMenu(itemList,itemList[0])
- else: #user theme selected
-- itemList=idleConf.GetSectionList('user','highlight')
-+ itemList = idleConf.GetSectionList('user', 'highlight')
- itemList.sort()
-- self.optMenuThemeCustom.SetMenu(itemList,currentOption)
-- itemList=idleConf.GetSectionList('default','highlight')
-+ self.optMenuThemeCustom.SetMenu(itemList, currentOption)
-+ itemList = idleConf.GetSectionList('default', 'highlight')
- itemList.sort()
-- self.optMenuThemeBuiltin.SetMenu(itemList,itemList[0])
-+ self.optMenuThemeBuiltin.SetMenu(itemList, itemList[0])
- self.SetThemeType()
- ##load theme element option menu
-- themeNames=self.themeElements.keys()
-+ themeNames = self.themeElements.keys()
- themeNames.sort(self.__ThemeNameIndexCompare)
-- self.optMenuHighlightTarget.SetMenu(themeNames,themeNames[0])
-+ self.optMenuHighlightTarget.SetMenu(themeNames, themeNames[0])
- self.PaintThemeSample()
- self.SetHighlightTarget()
-
-+ if TTK:
-+ displaytheme = idleConf.GetOption('main', 'Theme', 'displaytheme')
-+ self.themename.set(displaytheme)
-+
- def __ThemeNameIndexCompare(self,a,b):
- if self.themeElements[a][1]<self.themeElements[b][1]: return -1
- elif self.themeElements[a][1]==self.themeElements[b][1]: return 0
-@@ -1028,13 +1154,17 @@
- self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave',
- default=0, type='bool'))
- #initial window size
-- self.winWidth.set(idleConf.GetOption('main','EditorWindow','width'))
-- self.winHeight.set(idleConf.GetOption('main','EditorWindow','height'))
-+ self.winWidth.set(idleConf.GetOption('main', 'EditorWindow', 'width'))
-+ self.winHeight.set(idleConf.GetOption('main', 'EditorWindow', 'height'))
- #initial paragraph reformat size
-- self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph'))
-+ self.paraWidth.set(idleConf.GetOption('main','FormatParagraph',
-+ 'paragraph'))
- # default source encoding
-- self.encoding.set(idleConf.GetOption('main', 'EditorWindow',
-- 'encoding', default='none'))
-+ self.encoding.set(idleConf.GetOption('main', 'EditorPage',
-+ 'encoding', default='none'))
-+ # open files/modules in tabs
-+ self.fileintab.set(idleConf.GetOption('main', 'EditorWindow',
-+ 'file-in-tab', default=1, type='bool'))
- # additional help sources
- self.userHelpList = idleConf.GetAllExtraHelpSourcesList()
- for helpItem in self.userHelpList:
-@@ -1125,6 +1255,8 @@
- instance.set_notabs_indentwidth()
- instance.ApplyKeybindings()
- instance.reset_help_menu_entries()
-+ if TTK:
-+ instance.set_theme(self.ttkstyle)
-
- def Cancel(self):
- self.destroy()
-@@ -1142,6 +1274,7 @@
- pass
-
- if __name__ == '__main__':
-+ from Tkinter import Tk
- #test the dialog
- root=Tk()
- Button(root,text='Dialog',
-Index: SearchEngine.py
-===================================================================
---- SearchEngine.py (revision 63995)
-+++ SearchEngine.py (revision 65541)
-@@ -1,5 +1,5 @@
- import re
--from Tkinter import *
-+from Tkinter import StringVar, BooleanVar, TclError
- import tkMessageBox
-
- def get(root):
-Index: ReplaceDialog.py
-===================================================================
---- ReplaceDialog.py (revision 63995)
-+++ ReplaceDialog.py (revision 65541)
-@@ -1,4 +1,5 @@
--from Tkinter import *
-+from Tkinter import StringVar, TclError
-+
- import SearchEngine
- from SearchDialogBase import SearchDialogBase
-
-@@ -11,9 +12,12 @@
- dialog.open(text)
-
- class ReplaceDialog(SearchDialogBase):
--
- title = "Replace Dialog"
- icon = "Replace"
-+ bottom_btns = [("Find", 'find_it'),
-+ ("Replace", 'replace_it'),
-+ ("Replace+Find", 'default_command', 1),
-+ ("Replace All", 'replace_all')]
-
- def __init__(self, root, engine):
- SearchDialogBase.__init__(self, root, engine)
-@@ -36,14 +40,10 @@
-
- def create_entries(self):
- SearchDialogBase.create_entries(self)
-- self.replent = self.make_entry("Replace with:", self.replvar)
-+ self.replent = self.make_entry("Replace with", self.replvar)
-
- def create_command_buttons(self):
- SearchDialogBase.create_command_buttons(self)
-- self.make_button("Find", self.find_it)
-- self.make_button("Replace", self.replace_it)
-- self.make_button("Replace+Find", self.default_command, 1)
-- self.make_button("Replace All", self.replace_all)
-
- def find_it(self, event=None):
- self.do_find(0)
-Index: ScriptBinding.py
-===================================================================
---- ScriptBinding.py (revision 63995)
-+++ ScriptBinding.py (revision 65541)
-@@ -46,8 +46,9 @@
- ('Check Module', '<<check-module>>'),
- ('Run Module', '<<run-module>>'), ]), ]
-
-- def __init__(self, editwin):
-- self.editwin = editwin
-+ def __init__(self, editpage):
-+ self.editpage = editpage
-+ self.editwin = editpage.editwin
- # Provide instance variables referenced by Debugger
- # XXX This should be done differently
- self.flist = self.editwin.flist
-@@ -70,7 +71,7 @@
- msgtxt, (lineno, start) = msg
- self.editwin.gotoline(lineno)
- self.errorbox("Tabnanny Tokenizing Error",
-- "Token Error: %s" % msgtxt)
-+ "Token Error: %s" % msgtxt)
- return False
- except tabnanny.NannyNag, nag:
- # The error messages from tabnanny are too confusing...
-@@ -91,7 +92,7 @@
- source = re.sub(r"\r", "\n", source)
- if source and source[-1] != '\n':
- source = source + '\n'
-- text = self.editwin.text
-+ text = self.editpage.text
- text.tag_remove("ERROR", "1.0", "end")
- try:
- try:
-@@ -113,7 +114,7 @@
- shell.set_warning_stream(saved_stream)
-
- def colorize_syntax_error(self, msg, lineno, offset):
-- text = self.editwin.text
-+ text = self.editpage.text
- pos = "0.0 + %d lines + %d chars" % (lineno-1, offset-1)
- text.tag_add("ERROR", pos)
- char = text.get(pos)
-@@ -175,20 +176,20 @@
-
- If the user has configured IDLE for Autosave, the file will be
- silently saved if it already exists and is dirty.
--
- """
-- filename = self.editwin.io.filename
-- if not self.editwin.get_saved():
-+ page = self.editpage
-+ filename = page.io.filename
-+ if not page.get_saved():
- autosave = idleConf.GetOption('main', 'General',
- 'autosave', type='bool')
- if autosave and filename:
-- self.editwin.io.save(None)
-+ page.io.save(None)
- else:
- reply = self.ask_save_dialog()
-- self.editwin.text.focus_set()
-+ page.text.focus_set()
- if reply == "ok":
-- self.editwin.io.save(None)
-- filename = self.editwin.io.filename
-+ page.io.save(None)
-+ filename = page.io.filename
- else:
- filename = None
- return filename
-@@ -196,14 +197,12 @@
- def ask_save_dialog(self):
- msg = "Source Must Be Saved\n" + 5*' ' + "OK to Save?"
- mb = tkMessageBox.Message(title="Save Before Run or Check",
-- message=msg,
-- icon=tkMessageBox.QUESTION,
-- type=tkMessageBox.OKCANCEL,
-- default=tkMessageBox.OK,
-- master=self.editwin.text)
-+ message=msg, icon=tkMessageBox.QUESTION,
-+ type=tkMessageBox.OKCANCEL, default=tkMessageBox.OK,
-+ master=self.editpage.text)
- return mb.show()
-
- def errorbox(self, title, message):
- # XXX This should really be a function of EditorWindow...
-- tkMessageBox.showerror(title, message, master=self.editwin.text)
-- self.editwin.text.focus_set()
-+ tkMessageBox.showerror(title, message, master=self.editpage.text)
-+ self.editpage.text.focus_set()
-Index: tabbedpages.py
-===================================================================
---- tabbedpages.py (revision 63995)
-+++ tabbedpages.py (revision 65541)
-@@ -1,490 +1,12 @@
--"""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 *
--
-+# Exceptions used on both versions of tabbedpages
- class InvalidNameError(Exception): pass
- class AlreadyExistsError(Exception): pass
-
-+def get_tabbedpage():
-+ """Returns the TabbedPageSet available for use."""
-+ try:
-+ from tabbedpages_new import TabbedPageSet
-+ except ImportError:
-+ from tabbedpages_old import TabbedPageSet
-
--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
-- for tab_name in self._tabs.keys():
-- self._tabs.pop(tab_name).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 xrange(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()
-+ return TabbedPageSet
-Index: keybindingDialog.py
-===================================================================
---- keybindingDialog.py (revision 63995)
-+++ keybindingDialog.py (revision 65541)
-@@ -1,10 +1,18 @@
- """
- Dialog for building Tkinter accelerator key bindings
- """
--from Tkinter import *
-+from Tkinter import Toplevel, Frame, Entry, Button, Checkbutton, Label, \
-+ Listbox, Scrollbar, StringVar
-+from Tkconstants import TOP, BOTH, BOTTOM, X, NSEW, SUNKEN, LEFT, GROOVE, W, \
-+ END, EW, NS, SINGLE, VERTICAL, ANCHOR, MOVETO
- import tkMessageBox
- import string
-
-+from idlelib.configHandler import idleConf
-+TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
-+if TTK:
-+ from ttk import Frame, Entry, Button, Checkbutton, Label, Scrollbar
-+
- class GetKeysDialog(Toplevel):
- def __init__(self,parent,title,action,currentKeySequences):
- """
-@@ -15,7 +23,7 @@
- """
- Toplevel.__init__(self, parent)
- self.configure(borderwidth=5)
-- self.resizable(height=FALSE,width=FALSE)
-+ self.resizable(height=False, width=False)
- self.title(title)
- self.transient(parent)
- self.grab_set()
-@@ -46,10 +54,10 @@
- self.wait_window()
-
- def CreateWidgets(self):
-- frameMain = Frame(self,borderwidth=2,relief=SUNKEN)
-- frameMain.pack(side=TOP,expand=TRUE,fill=BOTH)
-+ frameMain = Frame(self, borderwidth=2, relief=SUNKEN)
-+ frameMain.pack(side=TOP, expand=True, fill=BOTH)
- frameButtons=Frame(self)
-- frameButtons.pack(side=BOTTOM,fill=X)
-+ frameButtons.pack(side=BOTTOM, fill=X)
- self.buttonOK = Button(frameButtons,text='OK',
- width=8,command=self.OK)
- self.buttonOK.grid(row=0,column=0,padx=5,pady=5)
-@@ -124,6 +132,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.
-
-@@ -163,7 +174,7 @@
- if finalKey:
- finalKey = self.TranslateKey(finalKey, modifiers)
- keyList.append(finalKey)
-- self.keyString.set('<' + string.join(keyList,'-') + '>')
-+ self.keyString.set('<%s>' % '-'.join(keyList))
-
- def GetModifiers(self):
- modList = [variable.get() for variable in self.modifier_vars]
-@@ -258,6 +269,7 @@
- return keysOK
-
- if __name__ == '__main__':
-+ from Tkinter import Tk
- #test the dialog
- root=Tk()
- def run():
-Index: configHelpSourceEdit.py
-===================================================================
---- configHelpSourceEdit.py (revision 63995)
-+++ configHelpSourceEdit.py (revision 65541)
-@@ -1,12 +1,17 @@
- "Dialog to specify or edit the parameters for a user configured help source."
--
- import os
- import sys
--
--from Tkinter import *
-+from Tkinter import Toplevel, Frame, Entry, Button, Label, StringVar
-+from Tkconstants import GROOVE, LEFT, RIGHT, W, ACTIVE, X, BOTH, TOP, BOTTOM
- import tkMessageBox
- import tkFileDialog
-
-+from configHandler import idleConf
-+
-+TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
-+if TTK:
-+ from ttk import Frame, Entry, Button, Label
-+
- class GetHelpSourceDialog(Toplevel):
- def __init__(self, parent, title, menuItem='', filePath=''):
- """Get menu entry and url/ local file location for Additional Help
-@@ -18,13 +23,14 @@
- """
- Toplevel.__init__(self, parent)
- self.configure(borderwidth=5)
-- self.resizable(height=FALSE, width=FALSE)
-+ self.resizable(height=False, width=False)
- self.title(title)
- self.transient(parent)
- self.grab_set()
- self.protocol("WM_DELETE_WINDOW", self.Cancel)
- self.parent = parent
- self.result = None
-+
- self.CreateWidgets()
- self.menu.set(menuItem)
- self.path.set(filePath)
-@@ -46,33 +52,36 @@
- self.path = StringVar(self)
- self.fontSize = StringVar(self)
- self.frameMain = Frame(self, borderwidth=2, relief=GROOVE)
-- self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH)
- labelMenu = Label(self.frameMain, anchor=W, justify=LEFT,
-- text='Menu Item:')
-- self.entryMenu = Entry(self.frameMain, textvariable=self.menu,
-- width=30)
-- self.entryMenu.focus_set()
-+ text='Menu Item:')
-+ self.entryMenu = Entry(self.frameMain, textvariable=self.menu)
- labelPath = Label(self.frameMain, anchor=W, justify=LEFT,
-- text='Help File Path: Enter URL or browse for file')
-+ text='Help File Path: Enter URL or browse for file')
- self.entryPath = Entry(self.frameMain, textvariable=self.path,
-- width=40)
-+ width=30)
-+ browseButton = Button(self.frameMain, text='Browse', width=8,
-+ command=self.browseFile)
-+ frameButtons = Frame(self)
-+ self.buttonOk = Button(frameButtons, text='OK', width=8,
-+ default=ACTIVE, command=self.Ok)
-+ self.buttonCancel = Button(frameButtons, text='Cancel', width=8,
-+ command=self.Cancel)
-+
- self.entryMenu.focus_set()
-+
-+ self.frameMain.pack(side=TOP, expand=True, fill=BOTH)
- labelMenu.pack(anchor=W, padx=5, pady=3)
-- self.entryMenu.pack(anchor=W, padx=5, pady=3)
-+ self.entryMenu.pack(anchor=W, padx=5, pady=3, fill=X)
- labelPath.pack(anchor=W, padx=5, pady=3)
-- self.entryPath.pack(anchor=W, padx=5, pady=3)
-- browseButton = Button(self.frameMain, text='Browse', width=8,
-- command=self.browseFile)
-- browseButton.pack(pady=3)
-- frameButtons = Frame(self)
-+ self.entryPath.pack(anchor=W, padx=5, pady=3, side=LEFT, fill=X)
-+ browseButton.pack(pady=3, padx=5, side=RIGHT)
- frameButtons.pack(side=BOTTOM, fill=X)
-- self.buttonOk = Button(frameButtons, text='OK',
-- width=8, default=ACTIVE, command=self.Ok)
-- self.buttonOk.grid(row=0, column=0, padx=5,pady=5)
-- self.buttonCancel = Button(frameButtons, text='Cancel',
-- width=8, command=self.Cancel)
-- self.buttonCancel.grid(row=0, column=1, padx=5, pady=5)
-+ self.buttonOk.pack(pady=5, side=RIGHT)
-+ self.buttonCancel.pack(padx=5, pady=5, side=RIGHT)
-
-+ if TTK:
-+ frameButtons['style'] = 'RootColor.TFrame'
-+
- def browseFile(self):
- filetypes = [
- ("HTML Files", "*.htm *.html", "TEXT"),
-@@ -159,6 +168,7 @@
- self.destroy()
-
- if __name__ == '__main__':
-+ from Tkinter import Tk
- #test the dialog
- root = Tk()
- def run():
-Index: WidgetRedirector.py
-===================================================================
---- WidgetRedirector.py (revision 63995)
-+++ WidgetRedirector.py (revision 65541)
-@@ -1,4 +1,4 @@
--from Tkinter import *
-+from Tkinter import TclError
-
- class WidgetRedirector:
-
-@@ -105,6 +105,7 @@
-
-
- def main():
-+ from Tkinter import Tk, Text
- root = Tk()
- root.wm_protocol("WM_DELETE_WINDOW", root.quit)
- text = Text()
-Index: GrepDialog.py
-===================================================================
---- GrepDialog.py (revision 63995)
-+++ GrepDialog.py (revision 65541)
-@@ -1,10 +1,15 @@
- import os
--import fnmatch
- import sys
--from Tkinter import *
-+import fnmatch
-+from Tkinter import StringVar, BooleanVar, Checkbutton
-+
- import SearchEngine
- from SearchDialogBase import SearchDialogBase
-+from configHandler import idleConf
-
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
-+ from ttk import Checkbutton
-+
- def grep(text, io=None, flist=None):
- root = text._root()
- engine = SearchEngine.get(root)
-@@ -15,10 +20,10 @@
- dialog.open(text, searchphrase, io)
-
- class GrepDialog(SearchDialogBase):
--
- title = "Find in Files Dialog"
- icon = "Grep"
- needwrapbutton = 0
-+ bottom_btns = [("Search Files", 'default_command', 1)]
-
- def __init__(self, root, engine, flist):
- SearchDialogBase.__init__(self, root, engine)
-@@ -40,20 +45,18 @@
-
- def create_entries(self):
- SearchDialogBase.create_entries(self)
-- self.globent = self.make_entry("In files:", self.globvar)
-+ self.globent = self.make_entry("In files", self.globvar)
-
- def create_other_buttons(self):
- f = self.make_frame()
-
-- btn = Checkbutton(f, anchor="w",
-- variable=self.recvar,
-+ btn = Checkbutton(f, variable=self.recvar,
- text="Recurse down subdirectories")
- btn.pack(side="top", fill="both")
-- btn.select()
-+ btn.invoke()
-
- def create_command_buttons(self):
- SearchDialogBase.create_command_buttons(self)
-- self.make_button("Search Files", self.default_command, 1)
-
- def default_command(self, event=None):
- prog = self.engine.getprog()
-@@ -126,8 +129,3 @@
- for subdir in subdirs:
- list.extend(self.findfiles(subdir, base, rec))
- return list
--
-- def close(self, event=None):
-- if self.top:
-- self.top.grab_release()
-- self.top.withdraw()
-Index: FormatParagraph.py
-===================================================================
---- FormatParagraph.py (revision 63995)
-+++ FormatParagraph.py (revision 65541)
-@@ -25,28 +25,30 @@
- ])
- ]
-
-- def __init__(self, editwin):
-- self.editwin = editwin
-+ def __init__(self, editpage):
-+ self.editpage = editpage
-
- def close(self):
-- self.editwin = None
-+ self.editpage = None
-
- def format_paragraph_event(self, event):
-- maxformatwidth = int(idleConf.GetOption('main','FormatParagraph','paragraph'))
-- text = self.editwin.text
-- first, last = self.editwin.get_selection_indices()
-+ maxformatwidth = int(idleConf.GetOption('main', 'FormatParagraph',
-+ 'paragraph'))
-+ text = self.editpage.text
-+ first, last = self.editpage.get_selection_indices()
- if first and last:
- data = text.get(first, last)
- comment_header = ''
- else:
-- first, last, comment_header, data = \
-- find_paragraph(text, text.index("insert"))
-+ first, last, comment_header, data = find_paragraph(text,
-+ text.index("insert"))
- if comment_header:
- # Reformat the comment lines - convert to text sans header.
- lines = data.split("\n")
- lines = map(lambda st, l=len(comment_header): st[l:], lines)
- data = "\n".join(lines)
-- # Reformat to maxformatwidth chars or a 20 char width, whichever is greater.
-+ # Reformat to maxformatwidth chars or a 20 char width, whichever is
-+ # greater.
- format_width = max(maxformatwidth - len(comment_header), 20)
- newdata = reformat_paragraph(data, format_width)
- # re-split and re-insert the comment header.
-Index: EditorWindow.py
-===================================================================
---- EditorWindow.py (revision 63995)
-+++ EditorWindow.py (revision 65541)
-@@ -1,55 +1,54 @@
--import sys
- import os
- import re
--import imp
--from itertools import count
--from Tkinter import *
--import tkSimpleDialog
-+import sys
-+import traceback
-+import webbrowser
- import tkMessageBox
--from MultiCall import MultiCallCreator
-+import tkSimpleDialog
-+from Tkinter import Menu, Scrollbar, TclError, BooleanVar
-+from Tkconstants import INSERT, END, RIGHT, BOTTOM, TOP, X, Y, BOTH
-
--import webbrowser
--import idlever
-+import macosxSupport
-+import Bindings
- import WindowList
--import SearchDialog
--import GrepDialog
--import ReplaceDialog
--import PyParse
-+from editorpage import EditorPage, classifyws, filename_to_unicode
-+from tabbedpages import get_tabbedpage
- from configHandler import idleConf
--import aboutDialog, textView, configDialog
--import macosxSupport
-+from MultiStatusBar import MultiStatusBar
-
-+TabbedPageSet = get_tabbedpage()
-+
-+TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
-+if TTK:
-+ from ttk import Scrollbar
-+
- # The default tab setting for a Text widget, in average-width characters.
- TK_TABWIDTH_DEFAULT = 8
-
--def _find_module(fullname, path=None):
-- """Version of imp.find_module() that handles hierarchical module names"""
--
-- file = None
-- for tgt in fullname.split('.'):
-- if file is not None:
-- file.close() # close intermediate files
-- (file, filename, descr) = imp.find_module(tgt, path)
-- if descr[2] == imp.PY_SOURCE:
-- break # find but not load the source file
-- module = imp.load_module(tgt, file, filename, descr)
-- try:
-- path = module.__path__
-- except AttributeError:
-- raise ImportError, 'No source for module ' + module.__name__
-- return file, filename, descr
--
- class EditorWindow(object):
-- from Percolator import Percolator
-- from ColorDelegator import ColorDelegator
-- from UndoDelegator import UndoDelegator
-- from IOBinding import IOBinding, filesystemencoding, encoding
-- import Bindings
-- from Tkinter import Toplevel
-- from MultiStatusBar import MultiStatusBar
-+ from ColorDelegator import ColorDelegator # overridden by PyShell
-+ from UndoDelegator import UndoDelegator # overridden by PyShell
-
- help_url = None
-+ rmenu = None
-+ rmenu_specs = [
-+ # ("Label", "<<virtual-event>>"), ...
-+ ("Close", "<<close-window>>"), # Example
-+ ]
-+ menu_specs = [
-+ ("file", "_File"),
-+ ("edit", "_Edit"),
-+ ("format", "F_ormat"),
-+ ("run", "_Run"),
-+ ("options", "_Options"),
-+ ("windows", "_Windows"),
-+ ("help", "_Help"),
-+ ]
-
-+ if macosxSupport.runningAsOSXApp():
-+ del menu_specs[-3]
-+ menu_specs[-2] = ("windows", "_Window")
-+
- def __init__(self, flist=None, filename=None, key=None, root=None):
- if EditorWindow.help_url is None:
- dochome = os.path.join(sys.prefix, 'Doc', 'index.html')
-@@ -81,7 +80,7 @@
- EditorWindow.help_url = 'file://' + EditorWindow.help_url
- else:
- EditorWindow.help_url = "http://www.python.org/doc/current"
-- currentTheme=idleConf.CurrentTheme()
-+
- self.flist = flist
- root = root or flist.root
- self.root = root
-@@ -90,94 +89,45 @@
- except AttributeError:
- sys.ps1 = '>>> '
- self.menubar = Menu(root)
-- self.top = top = WindowList.ListedToplevel(root, menu=self.menubar)
-+ self.top = WindowList.ListedToplevel(root, menu=self.menubar)
- if flist:
- self.tkinter_vars = flist.vars
-- #self.top.instance_dict makes flist.inversedict avalable to
-- #configDialog.py so it can access all EditorWindow instaces
-+ # self.top.instance_dict makes flist.inversedict avalable to
-+ # configDialog.py so it can access all EditorWindow instaces
- self.top.instance_dict = flist.inversedict
- else:
- self.tkinter_vars = {} # keys: Tkinter event names
- # values: Tkinter variable instances
- self.top.instance_dict = {}
- self.recent_files_path = os.path.join(idleConf.GetUserCfgDir(),
-- 'recent-files.lst')
-- self.text_frame = text_frame = Frame(top)
-- self.vbar = vbar = Scrollbar(text_frame, name='vbar')
-- self.width = idleConf.GetOption('main','EditorWindow','width')
-- self.text = text = MultiCallCreator(Text)(
-- text_frame, name='text', padx=5, wrap='none',
-- width=self.width,
-- height=idleConf.GetOption('main','EditorWindow','height') )
-- self.top.focused_widget = self.text
-+ 'recent-files.lst')
-
-- self.createmenubar()
-- self.apply_bindings()
--
-- self.top.protocol("WM_DELETE_WINDOW", self.close)
-- self.top.bind("<<close-window>>", self.close_event)
-- if macosxSupport.runningAsOSXApp():
-- # Command-W on editorwindows doesn't work without this.
-- text.bind('<<close-window>>', self.close_event)
-- text.bind("<<cut>>", self.cut)
-- text.bind("<<copy>>", self.copy)
-- text.bind("<<paste>>", self.paste)
-- text.bind("<<center-insert>>", self.center_insert_event)
-- text.bind("<<help>>", self.help_dialog)
-- text.bind("<<python-docs>>", self.python_docs)
-- text.bind("<<about-idle>>", self.about_dialog)
-- text.bind("<<open-config-dialog>>", self.config_dialog)
-- text.bind("<<open-module>>", self.open_module)
-- text.bind("<<do-nothing>>", lambda event: "break")
-- text.bind("<<select-all>>", self.select_all)
-- text.bind("<<remove-selection>>", self.remove_selection)
-- text.bind("<<find>>", self.find_event)
-- text.bind("<<find-again>>", self.find_again_event)
-- text.bind("<<find-in-files>>", self.find_in_files_event)
-- text.bind("<<find-selection>>", self.find_selection_event)
-- text.bind("<<replace>>", self.replace_event)
-- text.bind("<<goto-line>>", self.goto_line_event)
-- text.bind("<3>", self.right_menu_event)
-- text.bind("<<smart-backspace>>",self.smart_backspace_event)
-- text.bind("<<newline-and-indent>>",self.newline_and_indent_event)
-- text.bind("<<smart-indent>>",self.smart_indent_event)
-- text.bind("<<indent-region>>",self.indent_region_event)
-- text.bind("<<dedent-region>>",self.dedent_region_event)
-- text.bind("<<comment-region>>",self.comment_region_event)
-- text.bind("<<uncomment-region>>",self.uncomment_region_event)
-- text.bind("<<tabify-region>>",self.tabify_region_event)
-- text.bind("<<untabify-region>>",self.untabify_region_event)
-- text.bind("<<toggle-tabs>>",self.toggle_tabs_event)
-- text.bind("<<change-indentwidth>>",self.change_indentwidth_event)
-- text.bind("<Left>", self.move_at_edge_if_selection(0))
-- text.bind("<Right>", self.move_at_edge_if_selection(1))
-- text.bind("<<del-word-left>>", self.del_word_left)
-- text.bind("<<del-word-right>>", self.del_word_right)
-- text.bind("<<beginning-of-line>>", self.home_callback)
--
- if flist:
- flist.inversedict[self] = key
- if key:
- flist.dict[key] = self
-- text.bind("<<open-new-window>>", self.new_callback)
-- text.bind("<<close-all-windows>>", self.flist.close_all_callback)
-- text.bind("<<open-class-browser>>", self.open_class_browser)
-- text.bind("<<open-path-browser>>", self.open_path_browser)
-
-- self.set_status_bar()
-- vbar['command'] = text.yview
-- vbar.pack(side=RIGHT, fill=Y)
-- text['yscrollcommand'] = vbar.set
-- fontWeight = 'normal'
-- if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'):
-- fontWeight='bold'
-- text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'),
-- idleConf.GetOption('main', 'EditorWindow', 'font-size'),
-- fontWeight))
-- text_frame.pack(side=LEFT, fill=BOTH, expand=1)
-- text.pack(side=TOP, fill=BOTH, expand=1)
-- text.focus_set()
-+ self.menudict = None
-
-+ # create a Notebook where the text pages for this EditorWindow will
-+ # reside
-+ self.text_notebook = TabbedPageSet(self.top)
-+ self.text_notebook.pack(fill=BOTH, expand=True)
-+ self.text_notebook.bind('<<NotebookTabChanged>>', self._update_controls)
-+ self.new_tab(filename=filename, load_ext=False)
-+ self.text = self.current_page.text # XXX
-+ self.top.focused_widget = self.text
-+ self.top.bind('<<tab-closed>>', self._post_tab_close)
-+
-+ # The following "width" attribute is used by PyShell, so keep it here
-+ self.width = idleConf.GetOption('main', 'EditorPage', 'width')
-+
-+ self.top.protocol("WM_DELETE_WINDOW", self.close)
-+ self.top.bind("<<close-window>>", self.close_event)
-+
-+ self._create_statusbar()
-+ self.top.after_idle(self.set_line_and_column)
-+
- # usetabs true -> literal tab characters are used by indent and
- # dedent cmds, possibly mixed with spaces if
- # indentwidth is not a multiple of tabwidth,
-@@ -187,7 +137,8 @@
- # Although use-spaces=0 can be configured manually in config-main.def,
- # configuration of tabs v. spaces is not supported in the configuration
- # dialog. IDLE promotes the preferred Python indentation: use spaces!
-- usespaces = idleConf.GetOption('main', 'Indent', 'use-spaces', type='bool')
-+ usespaces = idleConf.GetOption('main', 'Indent', 'use-spaces',
-+ type='bool')
- self.usetabs = not usespaces
-
- # tabwidth is the display width of a literal tab character.
-@@ -214,37 +165,10 @@
- # Making the initial values larger slows things down more often.
- self.num_context_lines = 50, 500, 5000000
-
-- self.per = per = self.Percolator(text)
--
-- self.undo = undo = self.UndoDelegator()
-- per.insertfilter(undo)
-- text.undo_block_start = undo.undo_block_start
-- text.undo_block_stop = undo.undo_block_stop
-- undo.set_saved_change_hook(self.saved_change_hook)
--
-- # IOBinding implements file I/O and printing functionality
-- self.io = io = self.IOBinding(self)
-- io.set_filename_change_hook(self.filename_change_hook)
--
-- # Create the recent files submenu
-- self.recent_files_menu = Menu(self.menubar)
-- self.menudict['file'].insert_cascade(3, label='Recent Files',
-- underline=0,
-- menu=self.recent_files_menu)
-- self.update_recent_files_list()
--
-- self.color = None # initialized below in self.ResetColorizer
-- if filename:
-- if os.path.exists(filename) and not os.path.isdir(filename):
-- io.loadfile(filename)
-- else:
-- io.set_filename(filename)
-- self.ResetColorizer()
-- self.saved_change_hook()
--
- self.set_indentation_params(self.ispythonsource(filename))
-
-- self.load_extensions()
-+ self.extensions = {}
-+ self._load_extensions()
-
- menu = self.menudict.get('windows')
- if menu:
-@@ -262,121 +186,96 @@
- self.askinteger = tkSimpleDialog.askinteger
- self.showerror = tkMessageBox.showerror
-
-- def _filename_to_unicode(self, filename):
-- """convert filename to unicode in order to display it in Tk"""
-- if isinstance(filename, unicode) or not filename:
-- return filename
-+ @property
-+ def current_page(self):
-+ """Return the active EditorPage in EditorWindow."""
-+ curr_tab = self.text_notebook.select()
-+ if not curr_tab:
-+ return None
-+
-+ if TTK:
-+ page = self.text_notebook.pages[self.text_notebook.tab(
-+ curr_tab)['text']].editpage
- else:
-- try:
-- return filename.decode(self.filesystemencoding)
-- except UnicodeDecodeError:
-- # XXX
-- try:
-- return filename.decode(self.encoding)
-- except UnicodeDecodeError:
-- # byte-to-byte conversion
-- return filename.decode('iso8859-1')
-+ page = self.text_notebook.pages[curr_tab].editpage
-+ return page
-
-- def new_callback(self, event):
-- dirname, basename = self.io.defaultfilename()
-- self.flist.new(dirname)
-- return "break"
-+ def short_title(self):
-+ # overriden by PyShell
-+ self.current_page.short_title()
-
-- def home_callback(self, event):
-- if (event.state & 12) != 0 and event.keysym == "Home":
-- # state&1==shift, state&4==control, state&8==alt
-- return # <Modifier-Home>; fall back to class binding
-+ def next_tab(self, event):
-+ """Show next tab if not in the last tab already."""
-+ index = self.text_notebook.index(self.text_notebook.select())
-+ if index == len(self.text_notebook.tabs()) - 1:
-+ return
-+ self.text_notebook.select(index + 1)
-
-- if self.text.index("iomark") and \
-- self.text.compare("iomark", "<=", "insert lineend") and \
-- self.text.compare("insert linestart", "<=", "iomark"):
-- insertpt = int(self.text.index("iomark").split(".")[1])
-- else:
-- line = self.text.get("insert linestart", "insert lineend")
-- for insertpt in xrange(len(line)):
-- if line[insertpt] not in (' ','\t'):
-- break
-- else:
-- insertpt=len(line)
-+ def prev_tab(self, event):
-+ """Show the previous tab if not in the first tab already."""
-+ index = self.text_notebook.index(self.text_notebook.select())
-+ if index == 0:
-+ return
-+ self.text_notebook.select(index - 1)
-
-- lineat = int(self.text.index("insert").split('.')[1])
-+ def new_tab(self, event=None, filename=None, load_ext=True):
-+ """Create a new EditorPage and insert it into the notebook."""
-+ page_title = "#%d" % (len(self.text_notebook.pages) + 1)
-+ page = self.text_notebook.add_page(page_title)
-
-- if insertpt == lineat:
-- insertpt = 0
-+ vbar = Scrollbar(page.frame, name='vbar')
-+ page.editpage = EditorPage(page.frame, self, title=page_title,
-+ name='text', padx=5, wrap='none')
-
-- dest = "insert linestart+"+str(insertpt)+"c"
-+ firstpage = False # don't update window's title
-+ if self.menudict is None:
-+ # This EditorWindow is being created now, perform the following
-+ # tasks before.
-+ firstpage = True # will cause window's title to be updated
-+ self.menudict = {}
-+ self._createmenubar(page.editpage.text)
-+ # Create the recent files submenu
-+ self.recent_files_menu = Menu(self.menubar)
-+ self.menudict['file'].insert_cascade(3, label='Recent Files',
-+ underline=0, menu=self.recent_files_menu)
-+ self.update_recent_files_list()
-
-- if (event.state&1) == 0:
-- # shift not pressed
-- self.text.tag_remove("sel", "1.0", "end")
-- else:
-- if not self.text.index("sel.first"):
-- self.text.mark_set("anchor","insert")
-+ page.editpage.post_init(filename=filename, update_window_title=firstpage)
-
-- first = self.text.index(dest)
-- last = self.text.index("anchor")
-+ text = page.editpage.text
-+ vbar['command'] = text.yview
-+ vbar.pack(side=RIGHT, fill=Y)
-+ text['yscrollcommand'] = vbar.set
-+ fontWeight = 'normal'
-+ if idleConf.GetOption('main', 'EditorPage', 'font-bold', type='bool'):
-+ fontWeight = 'bold'
-+ text.config(font=(idleConf.GetOption('main', 'EditorPage', 'font'),
-+ idleConf.GetOption('main', 'EditorPage', 'font-size'),
-+ fontWeight))
-+ text.pack(side=TOP, fill=BOTH, expand=1)
-+ text.focus_set()
-
-- if self.text.compare(first,">",last):
-- first,last = last,first
-+ self.apply_bindings(tab=page)
-+ if load_ext:
-+ self._load_extensions()
-+ self.top.event_generate('<<tab-created>>')
-+ return "break"
-
-- self.text.tag_remove("sel", "1.0", "end")
-- self.text.tag_add("sel", first, last)
--
-- self.text.mark_set("insert", dest)
-- self.text.see("insert")
-+ def new_callback(self, event, page):
-+ dirname, basename = page.io.defaultfilename()
-+ self.flist.new(dirname)
- return "break"
-
-- def set_status_bar(self):
-- self.status_bar = self.MultiStatusBar(self.top)
-- if macosxSupport.runningAsOSXApp():
-- # Insert some padding to avoid obscuring some of the statusbar
-- # by the resize widget.
-- self.status_bar.set_label('_padding1', ' ', side=RIGHT)
-- self.status_bar.set_label('column', 'Col: ?', side=RIGHT)
-- self.status_bar.set_label('line', 'Ln: ?', side=RIGHT)
-- self.status_bar.pack(side=BOTTOM, fill=X)
-- self.text.bind("<<set-line-and-column>>", self.set_line_and_column)
-- self.text.event_add("<<set-line-and-column>>",
-- "<KeyRelease>", "<ButtonRelease>")
-- self.text.after_idle(self.set_line_and_column)
--
- def set_line_and_column(self, event=None):
-- line, column = self.text.index(INSERT).split('.')
-+ # Used by PyShell too
-+ curr_page = self.current_page
-+ if not curr_page:
-+ return
-+
-+ line, column = curr_page.text.index(INSERT).split('.')
- self.status_bar.set_label('column', 'Col: %s' % column)
- self.status_bar.set_label('line', 'Ln: %s' % line)
-
-- menu_specs = [
-- ("file", "_File"),
-- ("edit", "_Edit"),
-- ("format", "F_ormat"),
-- ("run", "_Run"),
-- ("options", "_Options"),
-- ("windows", "_Windows"),
-- ("help", "_Help"),
-- ]
--
-- if macosxSupport.runningAsOSXApp():
-- del menu_specs[-3]
-- menu_specs[-2] = ("windows", "_Window")
--
--
-- def createmenubar(self):
-- mbar = self.menubar
-- self.menudict = menudict = {}
-- for name, label in self.menu_specs:
-- underline, label = prepstr(label)
-- menudict[name] = menu = Menu(mbar, name=name)
-- mbar.add_cascade(label=label, menu=menu, underline=underline)
--
-- if sys.platform == 'darwin' and '.framework' in sys.executable:
-- # Insert the application menu
-- menudict['application'] = menu = Menu(mbar, name='apple')
-- mbar.add_cascade(label='IDLE', menu=menu)
--
-- self.fill_menus()
-- self.base_helpmenu_length = self.menudict['help'].index(END)
-- self.reset_help_menu_entries()
--
- def postwindowsmenu(self):
- # Only called when Windows menu exists
- menu = self.menudict['windows']
-@@ -387,195 +286,27 @@
- menu.delete(self.wmenu_end+1, end)
- WindowList.add_windows_to_menu(menu)
-
-- rmenu = None
-+ def newline_and_indent_event(self, event):
-+ """Call newline_and_indent_event on current EditorPage."""
-+ self.current_page.newline_and_indent_event(event)
-
-- def right_menu_event(self, event):
-- self.text.tag_remove("sel", "1.0", "end")
-- self.text.mark_set("insert", "@%d,%d" % (event.x, event.y))
-- if not self.rmenu:
-- self.make_rmenu()
-- rmenu = self.rmenu
-- self.event = event
-- iswin = sys.platform[:3] == 'win'
-- if iswin:
-- self.text.config(cursor="arrow")
-- rmenu.tk_popup(event.x_root, event.y_root)
-- if iswin:
-- self.text.config(cursor="ibeam")
-+ def get_selection_indices(self):
-+ """Call get_selection_indices on current EditorPage."""
-+ return self.current_page.get_selection_indices()
-
-- rmenu_specs = [
-- # ("Label", "<<virtual-event>>"), ...
-- ("Close", "<<close-window>>"), # Example
-- ]
-+ def build_char_in_string_func(self, startindex):
-+ """Call build_char_in_string_func on current EditorPage."""
-+ return self.current_page.build_char_in_string_func(startindex)
-
-- def make_rmenu(self):
-- rmenu = Menu(self.text, tearoff=0)
-- for label, eventname in self.rmenu_specs:
-- def command(text=self.text, eventname=eventname):
-- text.event_generate(eventname)
-- rmenu.add_command(label=label, command=command)
-- self.rmenu = rmenu
--
-- def about_dialog(self, event=None):
-- aboutDialog.AboutDialog(self.top,'About IDLE')
--
-- def config_dialog(self, event=None):
-- configDialog.ConfigDialog(self.top,'Settings')
--
-- def help_dialog(self, event=None):
-- fn=os.path.join(os.path.abspath(os.path.dirname(__file__)),'help.txt')
-- textView.view_file(self.top,'Help',fn)
--
-- def python_docs(self, event=None):
-- if sys.platform[:3] == 'win':
-- os.startfile(self.help_url)
-- else:
-- webbrowser.open(self.help_url)
-- return "break"
--
-- def cut(self,event):
-- self.text.event_generate("<<Cut>>")
-- return "break"
--
-- def copy(self,event):
-- if not self.text.tag_ranges("sel"):
-- # There is no selection, so do nothing and maybe interrupt.
-- return
-- self.text.event_generate("<<Copy>>")
-- return "break"
--
-- def paste(self,event):
-- self.text.event_generate("<<Paste>>")
-- self.text.see("insert")
-- return "break"
--
-- def select_all(self, event=None):
-- self.text.tag_add("sel", "1.0", "end-1c")
-- self.text.mark_set("insert", "1.0")
-- self.text.see("insert")
-- return "break"
--
-- def remove_selection(self, event=None):
-- self.text.tag_remove("sel", "1.0", "end")
-- self.text.see("insert")
--
-- def move_at_edge_if_selection(self, edge_index):
-- """Cursor move begins at start or end of selection
--
-- When a left/right cursor key is pressed create and return to Tkinter a
-- function which causes a cursor move from the associated edge of the
-- selection.
--
-- """
-- self_text_index = self.text.index
-- self_text_mark_set = self.text.mark_set
-- edges_table = ("sel.first+1c", "sel.last-1c")
-- def move_at_edge(event):
-- if (event.state & 5) == 0: # no shift(==1) or control(==4) pressed
-- try:
-- self_text_index("sel.first")
-- self_text_mark_set("insert", edges_table[edge_index])
-- except TclError:
-- pass
-- return move_at_edge
--
-- def del_word_left(self, event):
-- self.text.event_generate('<Meta-Delete>')
-- return "break"
--
-- def del_word_right(self, event):
-- self.text.event_generate('<Meta-d>')
-- return "break"
--
-- def find_event(self, event):
-- SearchDialog.find(self.text)
-- return "break"
--
-- def find_again_event(self, event):
-- SearchDialog.find_again(self.text)
-- return "break"
--
-- def find_selection_event(self, event):
-- SearchDialog.find_selection(self.text)
-- return "break"
--
-- def find_in_files_event(self, event):
-- GrepDialog.grep(self.text, self.io, self.flist)
-- return "break"
--
-- def replace_event(self, event):
-- ReplaceDialog.replace(self.text)
-- return "break"
--
-- def goto_line_event(self, event):
-- text = self.text
-- lineno = tkSimpleDialog.askinteger("Goto",
-- "Go to line number:",parent=text)
-- if lineno is None:
-- return "break"
-- if lineno <= 0:
-- text.bell()
-- return "break"
-- text.mark_set("insert", "%d.0" % lineno)
-- text.see("insert")
--
-- def open_module(self, event=None):
-- # XXX Shouldn't this be in IOBinding or in FileList?
-- try:
-- name = self.text.get("sel.first", "sel.last")
-- except TclError:
-- name = ""
-- else:
-- name = name.strip()
-- name = tkSimpleDialog.askstring("Module",
-- "Enter the name of a Python module\n"
-- "to search on sys.path and open:",
-- parent=self.text, initialvalue=name)
-- if name:
-- name = name.strip()
-- if not name:
-- return
-- # XXX Ought to insert current file's directory in front of path
-- try:
-- (f, file, (suffix, mode, type)) = _find_module(name)
-- except (NameError, ImportError), msg:
-- tkMessageBox.showerror("Import error", str(msg), parent=self.text)
-- return
-- if type != imp.PY_SOURCE:
-- tkMessageBox.showerror("Unsupported type",
-- "%s is not a source module" % name, parent=self.text)
-- return
-- if f:
-- f.close()
-- if self.flist:
-- self.flist.open(file)
-- else:
-- self.io.loadfile(file)
--
-- def open_class_browser(self, event=None):
-- filename = self.io.filename
-- if not filename:
-- tkMessageBox.showerror(
-- "No filename",
-- "This buffer has no associated filename",
-- master=self.text)
-- self.text.focus_set()
-- return None
-- head, tail = os.path.split(filename)
-- base, ext = os.path.splitext(tail)
-- import ClassBrowser
-- ClassBrowser.ClassBrowser(self.flist, base, [head])
--
-- def open_path_browser(self, event=None):
-- import PathBrowser
-- PathBrowser.PathBrowser(self.flist)
--
- def gotoline(self, lineno):
-+ page = self.current_page
-+ text = page.text
-+
- if lineno is not None and lineno > 0:
-- self.text.mark_set("insert", "%d.0" % lineno)
-- self.text.tag_remove("sel", "1.0", "end")
-- self.text.tag_add("sel", "insert", "insert +1l")
-- self.center()
-+ text.mark_set("insert", "%d.0" % lineno)
-+ text.tag_remove("sel", "1.0", "end")
-+ text.tag_add("sel", "insert", "insert +1l")
-+ page.center()
-
- def ispythonsource(self, filename):
- if not filename or os.path.isdir(filename):
-@@ -599,82 +330,59 @@
- def set_close_hook(self, close_hook):
- self.close_hook = close_hook
-
-- def filename_change_hook(self):
-- if self.flist:
-- self.flist.filename_changed_edit(self)
-- self.saved_change_hook()
-- self.top.update_windowlist_registry(self)
-- self.ResetColorizer()
-+ def set_theme(self, ttkstyle):
-+ # called from configDialog.py
-+ ttkstyle.theme_use(idleConf.GetOption('main', 'Theme', 'displaytheme'))
-
-- def _addcolorizer(self):
-- if self.color:
-- return
-- if self.ispythonsource(self.io.filename):
-- self.color = self.ColorDelegator()
-- # can add more colorizers here...
-- if self.color:
-- self.per.removefilter(self.undo)
-- self.per.insertfilter(self.color)
-- self.per.insertfilter(self.undo)
--
-- def _rmcolorizer(self):
-- if not self.color:
-- return
-- self.color.removecolors()
-- self.per.removefilter(self.color)
-- self.color = None
--
- def ResetColorizer(self):
- "Update the colour theme"
- # Called from self.filename_change_hook and from configDialog.py
-- self._rmcolorizer()
-- self._addcolorizer()
-- theme = idleConf.GetOption('main','Theme','name')
-- normal_colors = idleConf.GetHighlight(theme, 'normal')
-- cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg')
-- select_colors = idleConf.GetHighlight(theme, 'hilite')
-- self.text.config(
-- foreground=normal_colors['foreground'],
-- background=normal_colors['background'],
-- insertbackground=cursor_color,
-- selectforeground=select_colors['foreground'],
-- selectbackground=select_colors['background'],
-- )
-+ for page in self.text_notebook.pages.itervalues():
-+ page.editpage.reset_colorizer()
-
- def ResetFont(self):
- "Update the text widgets' font if it is changed"
- # Called from configDialog.py
-- fontWeight='normal'
-- if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'):
-- fontWeight='bold'
-- self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'),
-- idleConf.GetOption('main','EditorWindow','font-size'),
-+ fontWeight = 'normal'
-+ if idleConf.GetOption('main', 'EditorPage', 'font-bold', type='bool'):
-+ fontWeight = 'bold'
-+
-+ for page in self.text_notebook.pages.itervalues():
-+ text = page.editpage.text
-+ text.config(font=(idleConf.GetOption('main', 'EditorPage', 'font'),
-+ idleConf.GetOption('main', 'EditorPage', 'font-size'),
- fontWeight))
-
- def RemoveKeybindings(self):
- "Remove the keybindings before they are changed."
- # Called from configDialog.py
-- self.Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet()
-- for event, keylist in keydefs.items():
-- self.text.event_delete(event, *keylist)
-- for extensionName in self.get_standard_extension_names():
-+ Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet()
-+
-+ for page in self.text_notebook.pages.itervalues():
-+ text = page.editpage.text
-+ for event, keylist in keydefs.items():
-+ text.event_delete(event, *keylist)
-+
-+ for extensionName in self._get_standard_extension_names():
- xkeydefs = idleConf.GetExtensionBindings(extensionName)
- if xkeydefs:
-- for event, keylist in xkeydefs.items():
-- self.text.event_delete(event, *keylist)
-+ for page in self.text_notebook.pages.itervalues():
-+ text = page.editpage.text
-+ for event, keylist in xkeydefs.items():
-+ text.event_delete(event, *keylist)
-
- def ApplyKeybindings(self):
- "Update the keybindings after they are changed"
- # Called from configDialog.py
-- self.Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet()
-+ Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet()
- self.apply_bindings()
-- for extensionName in self.get_standard_extension_names():
-+ for extensionName in self._get_standard_extension_names():
- xkeydefs = idleConf.GetExtensionBindings(extensionName)
- if xkeydefs:
- self.apply_bindings(xkeydefs)
- #update menu accelerators
- menuEventDict = {}
-- for menu in self.Bindings.menudefs:
-+ for menu in Bindings.menudefs:
- menuEventDict[menu[0]] = {}
- for item in menu[1]:
- if item:
-@@ -695,13 +403,6 @@
- accel = get_accelerator(keydefs, event)
- menu.entryconfig(index, accelerator=accel)
-
-- def set_notabs_indentwidth(self):
-- "Update the indentwidth if changed and not using tabs in this window"
-- # Called from configDialog.py
-- if not self.usetabs:
-- self.indentwidth = idleConf.GetOption('main', 'Indent','num-spaces',
-- type='int')
--
- def reset_help_menu_entries(self):
- "Update the additional help entries on the Help menu"
- help_list = idleConf.GetAllExtraHelpSourcesList()
-@@ -719,19 +420,16 @@
- # and update the menu dictionary
- self.menudict['help'] = helpmenu
-
-- def __extra_help_callback(self, helpfile):
-- "Create a callback with the helpfile value frozen at definition time"
-- def display_extra_help(helpfile=helpfile):
-- if not helpfile.startswith(('www', 'http')):
-- url = os.path.normpath(helpfile)
-- if sys.platform[:3] == 'win':
-- os.startfile(helpfile)
-- else:
-- webbrowser.open(helpfile)
-- return display_extra_help
-+ def set_notabs_indentwidth(self):
-+ "Update the indentwidth if changed and not using tabs in this window"
-+ # Called from configDialog.py
-+ if not self.usetabs:
-+ self.indentwidth = idleConf.GetOption('main', 'Indent','num-spaces',
-+ type='int')
-
- def update_recent_files_list(self, new_file=None):
- "Load and update the recent files list and menus"
-+ # IOBinding calls this
- rf_list = []
- if os.path.exists(self.recent_files_path):
- rf_list_file = open(self.recent_files_path,'r')
-@@ -761,83 +459,18 @@
- for instance in self.top.instance_dict.keys():
- menu = instance.recent_files_menu
- menu.delete(1, END) # clear, and rebuild:
-- for i, file in zip(count(), rf_list):
-+ for i, file in enumerate(rf_list):
- file_name = file[0:-1] # zap \n
- # make unicode string to display non-ASCII chars correctly
-- ufile_name = self._filename_to_unicode(file_name)
-+ ufile_name = filename_to_unicode(file_name)
- callback = instance.__recent_file_callback(file_name)
- menu.add_command(label=ulchars[i] + " " + ufile_name,
- command=callback,
- underline=0)
-
-- def __recent_file_callback(self, file_name):
-- def open_recent_file(fn_closure=file_name):
-- self.io.open(editFile=fn_closure)
-- return open_recent_file
--
-- def saved_change_hook(self):
-- short = self.short_title()
-- long = self.long_title()
-- if short and long:
-- title = short + " - " + long
-- elif short:
-- title = short
-- elif long:
-- title = long
-- else:
-- title = "Untitled"
-- icon = short or long or title
-- if not self.get_saved():
-- title = "*%s*" % title
-- icon = "*%s" % icon
-- self.top.wm_title(title)
-- self.top.wm_iconname(icon)
--
- def get_saved(self):
-- return self.undo.get_saved()
-+ return self.current_page.undo.get_saved() # XXX check this!
-
-- def set_saved(self, flag):
-- self.undo.set_saved(flag)
--
-- def reset_undo(self):
-- self.undo.reset_undo()
--
-- def short_title(self):
-- filename = self.io.filename
-- if filename:
-- filename = os.path.basename(filename)
-- # return unicode string to display non-ASCII chars correctly
-- return self._filename_to_unicode(filename)
--
-- def long_title(self):
-- # return unicode string to display non-ASCII chars correctly
-- return self._filename_to_unicode(self.io.filename or "")
--
-- def center_insert_event(self, event):
-- self.center()
--
-- def center(self, mark="insert"):
-- text = self.text
-- top, bot = self.getwindowlines()
-- lineno = self.getlineno(mark)
-- height = bot - top
-- newtop = max(1, lineno - height//2)
-- text.yview(float(newtop))
--
-- def getwindowlines(self):
-- text = self.text
-- top = self.getlineno("@0,0")
-- bot = self.getlineno("@0,65535")
-- if top == bot and text.winfo_height() == 1:
-- # Geometry manager hasn't run yet
-- height = int(text['height'])
-- bot = top + height - 1
-- return top, bot
--
-- def getlineno(self, mark="insert"):
-- text = self.text
-- return int(float(text.index(mark)))
--
- def get_geometry(self):
- "Return (width, height, x, y)"
- geom = self.top.wm_geometry()
-@@ -848,132 +481,49 @@
- def close_event(self, event):
- self.close()
-
-- def maybesave(self):
-- if self.io:
-- if not self.get_saved():
-- if self.top.state()!='normal':
-- self.top.deiconify()
-- self.top.lower()
-- self.top.lift()
-- return self.io.maybesave()
--
- def close(self):
-- reply = self.maybesave()
-- if str(reply) != "cancel":
-- self._close()
-- return reply
-+ to_check = self.text_notebook.pages.copy()
-
-+ while to_check:
-+ curr_tab = self.text_notebook.select()
-+ if TTK:
-+ page_name = self.text_notebook.tab(curr_tab)['text']
-+ else:
-+ page_name = curr_tab
-+ page = to_check.pop(page_name)
-+ editpage = page.editpage
-+ reply = editpage.close_tab()
-+ if reply == "cancel":
-+ break
-+
- def _close(self):
-- if self.io.filename:
-- self.update_recent_files_list(new_file=self.io.filename)
- WindowList.unregister_callback(self.postwindowsmenu)
-- self.unload_extensions()
-- self.io.close()
-- self.io = None
-- self.undo = None
-- if self.color:
-- self.color.close(False)
-- self.color = None
-- self.text = None
-+ self._unload_extensions()
- self.tkinter_vars = None
-- self.per.close()
-- self.per = None
-+
-+ for page in self.text_notebook.pages.itervalues():
-+ page.editpage.close()
-+
- self.top.destroy()
- if self.close_hook:
- # unless override: unregister from flist, terminate if last window
- self.close_hook()
-
-- def load_extensions(self):
-- self.extensions = {}
-- self.load_standard_extensions()
--
-- def unload_extensions(self):
-- for ins in self.extensions.values():
-- if hasattr(ins, "close"):
-- ins.close()
-- self.extensions = {}
--
-- def load_standard_extensions(self):
-- for name in self.get_standard_extension_names():
-- try:
-- self.load_extension(name)
-- except:
-- print "Failed to load extension", repr(name)
-- import traceback
-- traceback.print_exc()
--
-- def get_standard_extension_names(self):
-- return idleConf.GetExtensions(editor_only=True)
--
-- def load_extension(self, name):
-- try:
-- mod = __import__(name, globals(), locals(), [])
-- except ImportError:
-- print "\nFailed to import extension: ", name
-- return
-- cls = getattr(mod, name)
-- keydefs = idleConf.GetExtensionBindings(name)
-- if hasattr(cls, "menudefs"):
-- self.fill_menus(cls.menudefs, keydefs)
-- ins = cls(self)
-- self.extensions[name] = ins
-- if keydefs:
-- self.apply_bindings(keydefs)
-- for vevent in keydefs.keys():
-- methodname = vevent.replace("-", "_")
-- while methodname[:1] == '<':
-- methodname = methodname[1:]
-- while methodname[-1:] == '>':
-- methodname = methodname[:-1]
-- methodname = methodname + "_event"
-- if hasattr(ins, methodname):
-- self.text.bind(vevent, getattr(ins, methodname))
--
-- def apply_bindings(self, keydefs=None):
-+ def apply_bindings(self, keydefs=None, tab=None):
- if keydefs is None:
-- keydefs = self.Bindings.default_keydefs
-- text = self.text
-- text.keydefs = keydefs
-- for event, keylist in keydefs.items():
-- if keylist:
-- text.event_add(event, *keylist)
-+ keydefs = Bindings.default_keydefs
-
-- def fill_menus(self, menudefs=None, keydefs=None):
-- """Add appropriate entries to the menus and submenus
-+ if tab:
-+ iter_over = [tab]
-+ else:
-+ iter_over = self.text_notebook.pages.itervalues()
-
-- Menus that are absent or None in self.menudict are ignored.
-- """
-- if menudefs is None:
-- menudefs = self.Bindings.menudefs
-- if keydefs is None:
-- keydefs = self.Bindings.default_keydefs
-- menudict = self.menudict
-- text = self.text
-- for mname, entrylist in menudefs:
-- menu = menudict.get(mname)
-- if not menu:
-- continue
-- for entry in entrylist:
-- if not entry:
-- menu.add_separator()
-- else:
-- label, eventname = entry
-- checkbutton = (label[:1] == '!')
-- if checkbutton:
-- label = label[1:]
-- underline, label = prepstr(label)
-- accelerator = get_accelerator(keydefs, eventname)
-- def command(text=text, eventname=eventname):
-- text.event_generate(eventname)
-- if checkbutton:
-- var = self.get_var_obj(eventname, BooleanVar)
-- menu.add_checkbutton(label=label, underline=underline,
-- command=command, accelerator=accelerator,
-- variable=var)
-- else:
-- menu.add_command(label=label, underline=underline,
-- command=command,
-- accelerator=accelerator)
-+ for page in iter_over:
-+ text = page.editpage.text
-+ text.keydefs = keydefs
-+ for event, keylist in keydefs.items():
-+ if keylist:
-+ text.event_add(event, *keylist)
-
- def getvar(self, name):
- var = self.get_var_obj(name)
-@@ -990,52 +540,25 @@
- else:
- raise NameError, name
-
-- def get_var_obj(self, name, vartype=None):
-+ def get_var_obj(self, name, vartype=None, text=None):
- var = self.tkinter_vars.get(name)
- if not var and vartype:
- # create a Tkinter variable object with self.text as master:
-- self.tkinter_vars[name] = var = vartype(self.text)
-+ self.tkinter_vars[name] = var = vartype(text or self.text)
- return var
-
- # Tk implementations of "virtual text methods" -- each platform
- # reusing IDLE's support code needs to define these for its GUI's
- # flavor of widget.
-
-- # Is character at text_index in a Python string? Return 0 for
-- # "guaranteed no", true for anything else. This info is expensive
-- # to compute ab initio, but is probably already known by the
-- # platform's colorizer.
--
-- def is_char_in_string(self, text_index):
-- if self.color:
-- # Return true iff colorizer hasn't (re)gotten this far
-- # yet, or the character is tagged as being in a string
-- return self.text.tag_prevrange("TODO", text_index) or \
-- "STRING" in self.text.tag_names(text_index)
-- else:
-- # The colorizer is missing: assume the worst
-- return 1
--
-- # If a selection is defined in the text widget, return (start,
-- # end) as Tkinter text indices, otherwise return (None, None)
-- def get_selection_indices(self):
-- try:
-- first = self.text.index("sel.first")
-- last = self.text.index("sel.last")
-- return first, last
-- except TclError:
-- return None, None
--
- # Return the text widget's current view of what a tab stop means
- # (equivalent width in spaces).
--
-- def get_tabwidth(self):
-+ def get_tabwidth(self): # XXX depends on self.text
- current = self.text['tabs'] or TK_TABWIDTH_DEFAULT
- return int(current)
-
- # Set the text widget's current view of what a tab stop means.
--
-- def set_tabwidth(self, newtabwidth):
-+ def set_tabwidth(self, newtabwidth): # XXX depends on self.text
- text = self.text
- if self.get_tabwidth() != newtabwidth:
- pixels = text.tk.call("font", "measure", text["font"],
-@@ -1048,7 +571,6 @@
- # indentwidth != tabwidth set usetabs false.
- # In any case, adjust the Text widget's view of what a tab
- # character means.
--
- def set_indentation_params(self, ispythonsource, guess=True):
- if guess and ispythonsource:
- i = self.guess_indent()
-@@ -1058,386 +580,187 @@
- self.usetabs = False
- self.set_tabwidth(self.tabwidth)
-
-- def smart_backspace_event(self, event):
-- text = self.text
-- first, last = self.get_selection_indices()
-- if first and last:
-- text.delete(first, last)
-- text.mark_set("insert", first)
-- return "break"
-- # Delete whitespace left, until hitting a real char or closest
-- # preceding virtual tab stop.
-- chars = text.get("insert linestart", "insert")
-- if chars == '':
-- if text.compare("insert", ">", "1.0"):
-- # easy: delete preceding newline
-- text.delete("insert-1c")
-- else:
-- text.bell() # at start of buffer
-- return "break"
-- if chars[-1] not in " \t":
-- # easy: delete preceding real char
-- text.delete("insert-1c")
-- return "break"
-- # Ick. It may require *inserting* spaces if we back up over a
-- # tab character! This is written to be clear, not fast.
-- tabwidth = self.tabwidth
-- have = len(chars.expandtabs(tabwidth))
-- assert have > 0
-- want = ((have - 1) // self.indentwidth) * self.indentwidth
-- # Debug prompt is multilined....
-- last_line_of_prompt = sys.ps1.split('\n')[-1]
-- ncharsdeleted = 0
-- while 1:
-- if chars == last_line_of_prompt:
-- break
-- chars = chars[:-1]
-- ncharsdeleted = ncharsdeleted + 1
-- have = len(chars.expandtabs(tabwidth))
-- if have <= want or chars[-1] not in " \t":
-- break
-- text.undo_block_start()
-- text.delete("insert-%dc" % ncharsdeleted, "insert")
-- if have < want:
-- text.insert("insert", ' ' * (want - have))
-- text.undo_block_stop()
-- return "break"
-+ # Guess indentwidth from text content.
-+ # Return guessed indentwidth. This should not be believed unless
-+ # it's in a reasonable range (e.g., it will be 0 if no indented
-+ # blocks are found).
-+ def guess_indent(self): # XXX depends on self.text
-+ opener, indented = IndentSearcher(self.text, self.tabwidth).run()
-+ if opener and indented:
-+ raw, indentsmall = classifyws(opener, self.tabwidth)
-+ raw, indentlarge = classifyws(indented, self.tabwidth)
-+ else:
-+ indentsmall = indentlarge = 0
-+ return indentlarge - indentsmall
-
-- def smart_indent_event(self, event):
-- # if intraline selection:
-- # delete it
-- # elif multiline selection:
-- # do indent-region
-- # else:
-- # indent one level
-- text = self.text
-- first, last = self.get_selection_indices()
-- text.undo_block_start()
-- try:
-- if first and last:
-- if index2line(first) != index2line(last):
-- return self.indent_region_event(event)
-- text.delete(first, last)
-- text.mark_set("insert", first)
-- prefix = text.get("insert linestart", "insert")
-- raw, effective = classifyws(prefix, self.tabwidth)
-- if raw == len(prefix):
-- # only whitespace to the left
-- self.reindent_to(effective + self.indentwidth)
-- else:
-- # tab to the next 'stop' within or to right of line's text:
-- if self.usetabs:
-- pad = '\t'
-- else:
-- effective = len(prefix.expandtabs(self.tabwidth))
-- n = self.indentwidth
-- pad = ' ' * (n - effective % n)
-- text.insert("insert", pad)
-- text.see("insert")
-- return "break"
-- finally:
-- text.undo_block_stop()
-+ # Private methods/attributes
-
-- def newline_and_indent_event(self, event):
-- text = self.text
-- first, last = self.get_selection_indices()
-- text.undo_block_start()
-- try:
-- if first and last:
-- text.delete(first, last)
-- text.mark_set("insert", first)
-- line = text.get("insert linestart", "insert")
-- i, n = 0, len(line)
-- while i < n and line[i] in " \t":
-- i = i+1
-- if i == n:
-- # the cursor is in or at leading indentation in a continuation
-- # line; just inject an empty line at the start
-- text.insert("insert linestart", '\n')
-- return "break"
-- indent = line[:i]
-- # strip whitespace before insert point unless it's in the prompt
-- i = 0
-- last_line_of_prompt = sys.ps1.split('\n')[-1]
-- while line and line[-1] in " \t" and line != last_line_of_prompt:
-- line = line[:-1]
-- i = i+1
-- if i:
-- text.delete("insert - %d chars" % i, "insert")
-- # strip whitespace after insert point
-- while text.get("insert") in " \t":
-- text.delete("insert")
-- # start new line
-- text.insert("insert", '\n')
-+ # extensions won't have more than one instance per window
-+ _unique_extensions = ['CodeContext', 'ScriptBinding', 'FormatParagraph']
-
-- # adjust indentation for continuations and block
-- # open/close first need to find the last stmt
-- lno = index2line(text.index('insert'))
-- y = PyParse.Parser(self.indentwidth, self.tabwidth)
-- if not self.context_use_ps1:
-- for context in self.num_context_lines:
-- startat = max(lno - context, 1)
-- startatindex = `startat` + ".0"
-- rawtext = text.get(startatindex, "insert")
-- y.set_str(rawtext)
-- bod = y.find_good_parse_start(
-- self.context_use_ps1,
-- self._build_char_in_string_func(startatindex))
-- if bod is not None or startat == 1:
-- break
-- y.set_lo(bod or 0)
-- else:
-- r = text.tag_prevrange("console", "insert")
-- if r:
-- startatindex = r[1]
-- else:
-- startatindex = "1.0"
-- rawtext = text.get(startatindex, "insert")
-- y.set_str(rawtext)
-- y.set_lo(0)
-+ def _unload_extensions(self):
-+ for ins in self.extensions.values():
-+ if hasattr(ins, "close"):
-+ ins.close()
-+ self.extensions = {}
-
-- c = y.get_continuation_type()
-- if c != PyParse.C_NONE:
-- # The current stmt hasn't ended yet.
-- if c == PyParse.C_STRING_FIRST_LINE:
-- # after the first line of a string; do not indent at all
-- pass
-- elif c == PyParse.C_STRING_NEXT_LINES:
-- # inside a string which started before this line;
-- # just mimic the current indent
-- text.insert("insert", indent)
-- elif c == PyParse.C_BRACKET:
-- # line up with the first (if any) element of the
-- # last open bracket structure; else indent one
-- # level beyond the indent of the line with the
-- # last open bracket
-- self.reindent_to(y.compute_bracket_indent())
-- elif c == PyParse.C_BACKSLASH:
-- # if more than one line in this stmt already, just
-- # mimic the current indent; else if initial line
-- # has a start on an assignment stmt, indent to
-- # beyond leftmost =; else to beyond first chunk of
-- # non-whitespace on initial line
-- if y.get_num_lines_in_stmt() > 1:
-- text.insert("insert", indent)
-- else:
-- self.reindent_to(y.compute_backslash_indent())
-- else:
-- assert 0, "bogus continuation type %r" % (c,)
-- return "break"
-+ def _load_extension(self, name, tab):
-+ ext_loaded = self.extensions.get(name, None)
-
-- # This line starts a brand new stmt; indent relative to
-- # indentation of initial line of closest preceding
-- # interesting stmt.
-- indent = y.get_base_indent_string()
-- text.insert("insert", indent)
-- if y.is_block_opener():
-- self.smart_indent_event(event)
-- elif indent and y.is_block_closer():
-- self.smart_backspace_event(event)
-- return "break"
-- finally:
-- text.see("insert")
-- text.undo_block_stop()
-+ try:
-+ mod = __import__(name, globals(), locals(), [])
-+ except ImportError:
-+ print "\nFailed to import extension: ", name
-+ return
-
-- # Our editwin provides a is_char_in_string function that works
-- # with a Tk text index, but PyParse only knows about offsets into
-- # a string. This builds a function for PyParse that accepts an
-- # offset.
-+ keydefs = idleConf.GetExtensionBindings(name)
-
-- def _build_char_in_string_func(self, startindex):
-- def inner(offset, _startindex=startindex,
-- _icis=self.is_char_in_string):
-- return _icis(_startindex + "+%dc" % offset)
-- return inner
-+ if name not in self._unique_extensions or not ext_loaded:
-+ # create a new instance
-+ cls = getattr(mod, name)
-+ ins = cls(tab.editpage)
-+ self.extensions.setdefault(name, []).append(ins)
-+ if not ext_loaded:
-+ # create new items in menu only if this is the first time this
-+ # extension is being loaded in this window
-+ if hasattr(cls, "menudefs"):
-+ self._fill_menus(cls.menudefs, keydefs)
-+ elif name in self._unique_extensions and ext_loaded:
-+ # get an existing instance
-+ ins = self.extensions[name][0]
-
-- def indent_region_event(self, event):
-- head, tail, chars, lines = self.get_region()
-- for pos in range(len(lines)):
-- line = lines[pos]
-- if line:
-- raw, effective = classifyws(line, self.tabwidth)
-- effective = effective + self.indentwidth
-- lines[pos] = self._make_blanks(effective) + line[raw:]
-- self.set_region(head, tail, chars, lines)
-- return "break"
-+ if keydefs:
-+ self.apply_bindings(keydefs, tab)
-+ for vevent in keydefs.keys():
-+ methodname = vevent.replace("-", "_")
-+ while methodname[:1] == '<':
-+ methodname = methodname[1:]
-+ while methodname[-1:] == '>':
-+ methodname = methodname[:-1]
-+ methodname = methodname + "_event"
-+ if hasattr(ins, methodname):
-+ tab.editpage.text.bind(vevent, getattr(ins, methodname))
-
-- def dedent_region_event(self, event):
-- head, tail, chars, lines = self.get_region()
-- for pos in range(len(lines)):
-- line = lines[pos]
-- if line:
-- raw, effective = classifyws(line, self.tabwidth)
-- effective = max(effective - self.indentwidth, 0)
-- lines[pos] = self._make_blanks(effective) + line[raw:]
-- self.set_region(head, tail, chars, lines)
-- return "break"
-+ def _load_extensions(self):
-+ self._load_standard_extensions(self.text_notebook.last_page())
-
-- def comment_region_event(self, event):
-- head, tail, chars, lines = self.get_region()
-- for pos in range(len(lines) - 1):
-- line = lines[pos]
-- lines[pos] = '##' + line
-- self.set_region(head, tail, chars, lines)
-+ def _load_standard_extensions(self, tab):
-+ for name in self._get_standard_extension_names():
-+ try:
-+ self._load_extension(name, tab)
-+ except:
-+ print "Failed to load extension", repr(name)
-+ traceback.print_exc()
-
-- def uncomment_region_event(self, event):
-- head, tail, chars, lines = self.get_region()
-- for pos in range(len(lines)):
-- line = lines[pos]
-- if not line:
-- continue
-- if line[:2] == '##':
-- line = line[2:]
-- elif line[:1] == '#':
-- line = line[1:]
-- lines[pos] = line
-- self.set_region(head, tail, chars, lines)
-+ def _get_standard_extension_names(self):
-+ return idleConf.GetExtensions(editor_only=True)
-
-- def tabify_region_event(self, event):
-- head, tail, chars, lines = self.get_region()
-- tabwidth = self._asktabwidth()
-- for pos in range(len(lines)):
-- line = lines[pos]
-- if line:
-- raw, effective = classifyws(line, tabwidth)
-- ntabs, nspaces = divmod(effective, tabwidth)
-- lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:]
-- self.set_region(head, tail, chars, lines)
-+ def _post_tab_close(self, event):
-+ if not self.current_page:
-+ # no tabs now, close window
-+ self._close()
-+ return
-
-- def untabify_region_event(self, event):
-- head, tail, chars, lines = self.get_region()
-- tabwidth = self._asktabwidth()
-- for pos in range(len(lines)):
-- lines[pos] = lines[pos].expandtabs(tabwidth)
-- self.set_region(head, tail, chars, lines)
-+ def _update_controls(self, event):
-+ curr_page = self.current_page
-+ if not curr_page:
-+ return
-
-- def toggle_tabs_event(self, event):
-- if self.askyesno(
-- "Toggle tabs",
-- "Turn tabs " + ("on", "off")[self.usetabs] +
-- "?\nIndent width " +
-- ("will be", "remains at")[self.usetabs] + " 8." +
-- "\n Note: a tab is always 8 columns",
-- parent=self.text):
-- self.usetabs = not self.usetabs
-- # Try to prevent inconsistent indentation.
-- # User must change indent width manually after using tabs.
-- self.indentwidth = 8
-- return "break"
-+ self.text = curr_page.text
-+ curr_page.saved_change_hook(True, False) # update window title
-+ curr_page.text.focus_set()
-+ self.set_line_and_column()
-
-- # XXX this isn't bound to anything -- see tabwidth comments
--## def change_tabwidth_event(self, event):
--## new = self._asktabwidth()
--## if new != self.tabwidth:
--## self.tabwidth = new
--## self.set_indentation_params(0, guess=0)
--## return "break"
-+ # update references in extensions that are loaded only once
-+ for ext in self._unique_extensions:
-+ if ext not in self.extensions:
-+ continue
-+ ext = self.extensions[ext][0]
-+ ext.editpage = curr_page
-
-- def change_indentwidth_event(self, event):
-- new = self.askinteger(
-- "Indent width",
-- "New indent width (2-16)\n(Always use 8 when using tabs)",
-- parent=self.text,
-- initialvalue=self.indentwidth,
-- minvalue=2,
-- maxvalue=16)
-- if new and new != self.indentwidth and not self.usetabs:
-- self.indentwidth = new
-- return "break"
-+ def _create_statusbar(self):
-+ self.status_bar = MultiStatusBar(self.top)
-+ if macosxSupport.runningAsOSXApp():
-+ # Insert some padding to avoid obscuring some of the statusbar
-+ # by the resize widget.
-+ self.status_bar.set_label('_padding1', ' ', side=RIGHT)
-+ self.status_bar.set_label('column', 'Col: ?', side=RIGHT)
-+ self.status_bar.set_label('line', 'Ln: ?', side=RIGHT)
-+ self.status_bar.pack(side=BOTTOM, fill=X)
-
-- def get_region(self):
-- text = self.text
-- first, last = self.get_selection_indices()
-- if first and last:
-- head = text.index(first + " linestart")
-- tail = text.index(last + "-1c lineend +1c")
-- else:
-- head = text.index("insert linestart")
-- tail = text.index("insert lineend +1c")
-- chars = text.get(head, tail)
-- lines = chars.split("\n")
-- return head, tail, chars, lines
-+ def _createmenubar(self, text):
-+ mbar = self.menubar
-+ menudict = self.menudict
-+ for name, label in self.menu_specs:
-+ underline, label = prepstr(label)
-+ menudict[name] = menu = Menu(mbar, name=name, tearoff=0)
-+ mbar.add_cascade(label=label, menu=menu, underline=underline)
-
-- def set_region(self, head, tail, chars, lines):
-- text = self.text
-- newchars = "\n".join(lines)
-- if newchars == chars:
-- text.bell()
-- return
-- text.tag_remove("sel", "1.0", "end")
-- text.mark_set("insert", head)
-- text.undo_block_start()
-- text.delete(head, tail)
-- text.insert(head, newchars)
-- text.undo_block_stop()
-- text.tag_add("sel", head, "insert")
-+ if sys.platform == 'darwin' and '.framework' in sys.executable:
-+ # Insert the application menu
-+ menudict['application'] = menu = Menu(mbar, name='apple')
-+ mbar.add_cascade(label='IDLE', menu=menu)
-
-- # Make string that displays as n leading blanks.
-+ self._fill_menus(text=text)
-+ self.base_helpmenu_length = self.menudict['help'].index(END)
-+ self.reset_help_menu_entries()
-
-- def _make_blanks(self, n):
-- if self.usetabs:
-- ntabs, nspaces = divmod(n, self.tabwidth)
-- return '\t' * ntabs + ' ' * nspaces
-- else:
-- return ' ' * n
-+ def _fill_menus(self, menudefs=None, keydefs=None, text=None):
-+ """Add appropriate entries to the menus and submenus
-
-- # Delete from beginning of line to insert point, then reinsert
-- # column logical (meaning use tabs if appropriate) spaces.
-+ Menus that are absent or None in self.menudict are ignored.
-+ """
-+ if menudefs is None:
-+ menudefs = Bindings.menudefs
-+ if keydefs is None:
-+ keydefs = Bindings.default_keydefs
-+ menudict = self.menudict
-+ for mname, entrylist in menudefs:
-+ menu = menudict.get(mname)
-+ if not menu:
-+ continue
-+ for entry in entrylist:
-+ if not entry:
-+ menu.add_separator()
-+ else:
-+ label, eventname = entry
-+ checkbutton = (label[:1] == '!')
-+ if checkbutton:
-+ label = label[1:]
-+ underline, label = prepstr(label)
-+ accelerator = get_accelerator(keydefs, eventname)
-+ def command(eventname=eventname):
-+ self.text.event_generate(eventname)
-+ if checkbutton:
-+ var = self.get_var_obj(eventname, BooleanVar, text)
-+ menu.add_checkbutton(label=label, underline=underline,
-+ command=command, accelerator=accelerator,
-+ variable=var)
-+ else:
-+ menu.add_command(label=label, underline=underline,
-+ command=command, accelerator=accelerator)
-
-- def reindent_to(self, column):
-- text = self.text
-- text.undo_block_start()
-- if text.compare("insert linestart", "!=", "insert"):
-- text.delete("insert linestart", "insert")
-- if column:
-- text.insert("insert", self._make_blanks(column))
-- text.undo_block_stop()
-+ def __recent_file_callback(self, file_name):
-+ def open_recent_file(fn_closure=file_name):
-+ self.current_page.io.open(editFile=fn_closure)
-+ return open_recent_file
-
-- def _asktabwidth(self):
-- return self.askinteger(
-- "Tab width",
-- "Columns per tab? (2-16)",
-- parent=self.text,
-- initialvalue=self.indentwidth,
-- minvalue=2,
-- maxvalue=16) or self.tabwidth
-+ def __extra_help_callback(self, helpfile):
-+ "Create a callback with the helpfile value frozen at definition time"
-+ def display_extra_help(helpfile=helpfile):
-+ if not helpfile.startswith(('www', 'http')):
-+ url = os.path.normpath(helpfile)
-+ if sys.platform[:3] == 'win':
-+ os.startfile(helpfile)
-+ else:
-+ webbrowser.open(helpfile)
-+ return display_extra_help
-
-- # Guess indentwidth from text content.
-- # Return guessed indentwidth. This should not be believed unless
-- # it's in a reasonable range (e.g., it will be 0 if no indented
-- # blocks are found).
--
-- def guess_indent(self):
-- opener, indented = IndentSearcher(self.text, self.tabwidth).run()
-- if opener and indented:
-- raw, indentsmall = classifyws(opener, self.tabwidth)
-- raw, indentlarge = classifyws(indented, self.tabwidth)
-- else:
-- indentsmall = indentlarge = 0
-- return indentlarge - indentsmall
--
--# "line.col" -> line, as an int
--def index2line(index):
-- return int(float(index))
--
- # Look at the leading whitespace in s.
- # Return pair (# of leading ws characters,
- # effective # of leading blanks after expanding
- # tabs to width tabwidth)
-
--def classifyws(s, tabwidth):
-- raw = effective = 0
-- for ch in s:
-- if ch == ' ':
-- raw = raw + 1
-- effective = effective + 1
-- elif ch == '\t':
-- raw = raw + 1
-- effective = (effective // tabwidth + 1) * tabwidth
-- else:
-- break
-- return raw, effective
--
- import tokenize
- _tokenize = tokenize
- del tokenize
-@@ -1534,6 +857,7 @@
-
-
- def test():
-+ from Tkinter import Tk
- root = Tk()
- fixwordbreaks(root)
- root.withdraw()
-Index: help.txt
-===================================================================
---- help.txt (revision 63995)
-+++ help.txt (revision 65541)
-@@ -6,6 +6,7 @@
- File Menu:
-
- New Window -- Create a new editing window
-+ New Tab -- Create a new editing tab
- Open... -- Open an existing file
- Recent Files... -- Open a list of recent files
- Open Module... -- Open an existing module (searches sys.path)
-@@ -23,6 +24,7 @@
- ---
- Print Window -- Print the current window
- ---
-+ Close Tab -- Close current tab (asks to save if unsaved)
- Close -- Close current window (asks to save if unsaved)
- Exit -- Close all windows, quit (asks to save if unsaved)
-
-Index: editorpage.py
-===================================================================
---- editorpage.py (revision 0)
-+++ editorpage.py (revision 65541)
-@@ -0,0 +1,925 @@
-+import os
-+import sys
-+import imp
-+import webbrowser
-+import tkMessageBox
-+import tkSimpleDialog
-+from Tkinter import Text, Menu, TclError
-+
-+import utils
-+import textView
-+import aboutDialog
-+import configDialog
-+import macosxSupport
-+import PyParse
-+import IOBinding
-+import GrepDialog
-+import PathBrowser
-+import ClassBrowser
-+import SearchDialog
-+import ReplaceDialog
-+from configHandler import idleConf
-+from MultiCall import MultiCallCreator
-+from Percolator import Percolator
-+
-+def classifyws(s, tabwidth):
-+ raw = effective = 0
-+ for ch in s:
-+ if ch == ' ':
-+ raw = raw + 1
-+ effective = effective + 1
-+ elif ch == '\t':
-+ raw = raw + 1
-+ effective = (effective // tabwidth + 1) * tabwidth
-+ else:
-+ break
-+ return raw, effective
-+
-+def index2line(index):
-+ """"line.col" -> line, as an int"""
-+ return int(float(index))
-+
-+def filename_to_unicode(filename):
-+ """Convert filename to unicode in order to display it in Tk"""
-+ if isinstance(filename, unicode) or not filename:
-+ return filename
-+ else:
-+ try:
-+ return filename.decode(IOBinding.filesystemencoding)
-+ except UnicodeDecodeError:
-+ # XXX
-+ try:
-+ return filename.decode(IOBinding.encoding)
-+ except UnicodeDecodeError:
-+ # byte-to-byte conversion
-+ return filename.decode('iso8859-1')
-+
-+def _find_module(fullname, path=None):
-+ """Version of imp.find_module() that handles hierarchical module names"""
-+ file = None
-+
-+ for tgt in fullname.split('.'):
-+ if file is not None:
-+ file.close() # close intermediate files
-+ (file, filename, descr) = imp.find_module(tgt, path)
-+ if descr[2] == imp.PY_SOURCE:
-+ break # find but not load the source file
-+ module = imp.load_module(tgt, file, filename, descr)
-+ try:
-+ path = module.__path__
-+ except AttributeError:
-+ raise ImportError('No source for module %s' % module.__name__)
-+
-+ return file, filename, descr
-+
-+class EditorPage(object):
-+ def __init__(self, parent_frame, editwin, title=None, **kwargs):
-+ self.editwin = editwin
-+ self.title = title
-+ self.tab_initialized = False
-+ kwargs.setdefault('width', idleConf.GetOption('main', 'EditorPage',
-+ 'width'))
-+ kwargs.setdefault('height', idleConf.GetOption('main', 'EditorPage',
-+ 'height'))
-+
-+ self.text = MultiCallCreator(Text)(parent_frame, **kwargs)
-+ self.color = None # initialized in reset_colorizer
-+ self.per = Percolator(self.text)
-+ self.undo = self.editwin.UndoDelegator()
-+ self.per.insertfilter(self.undo)
-+ self.text.undo_block_start = self.undo.undo_block_start
-+ self.text.undo_block_stop = self.undo.undo_block_stop
-+ self.io = IOBinding.IOBinding(self)
-+
-+ self.undo.set_saved_change_hook(self.saved_change_hook)
-+ self.io.set_filename_change_hook(self.filename_change_hook)
-+ self.reset_colorizer()
-+ self._setup_bindings()
-+
-+ def post_init(self, filename=None, update_window_title=False):
-+ if filename:
-+ if os.path.exists(filename) and not os.path.isdir(filename):
-+ self.io.loadfile(filename)
-+ else:
-+ self.io.set_filename(filename)
-+ self.saved_change_hook(update_window_title=update_window_title)
-+ self.tab_initialized = True
-+
-+ def close_tab(self, event=None):
-+ """Close current tab, if no more tabs present, close the window."""
-+ if hasattr(self.editwin, 'interp'):
-+ # this is a PyShell, don't ask to save
-+ reply = 'yes'
-+ else:
-+ reply = str(self.maybesave())
-+ if reply != "cancel":
-+ if self.io.filename:
-+ self.editwin.update_recent_files_list(new_file=self.io.filename)
-+ self.close()
-+ self.editwin.text_notebook.remove_page(self.title)
-+ self.editwin.top.event_generate('<<tab-closed>>')
-+
-+ return reply
-+
-+ def close(self):
-+ """Perform necessary cleanup for this page before closing it."""
-+ self.io.close()
-+ self.io = None
-+
-+ self.undo = None
-+
-+ if self.color:
-+ self.color.close(False)
-+ self.color = None
-+
-+ self.per.close()
-+ self.per = None
-+ self.text = None
-+
-+ # XXX (1) mark where these functions are used
-+ def saved_change_hook(self,update_window_title=False,update_tab_title=True):
-+ short = self.editwin.short_title()
-+ long = self.long_title()
-+
-+ if short and long:
-+ title = short + " - " + long
-+ tabtitle = os.path.split(long)[-1]
-+ elif short:
-+ title = short
-+ tabtitle = short
-+ elif long:
-+ title = long
-+ tabtitle = os.path.split(long)[-1]
-+ else:
-+ title = tabtitle = "Untitled"
-+ icon = short or long or title
-+ if not self.get_saved():
-+ title = "*%s*" % title
-+ tabtitle = "*%s*" % tabtitle
-+ icon = "*%s" % icon
-+
-+ if update_tab_title:
-+ self.editwin.text_notebook.update_tabtitle(self, tabtitle)
-+ if update_window_title or (
-+ update_window_title is None and self.tab_initialized):
-+ self.editwin.top.wm_title(title)
-+ self.editwin.top.wm_iconname(icon)
-+
-+ def get_saved(self):
-+ return self.undo.get_saved()
-+
-+ def set_saved(self, flag):
-+ self.undo.set_saved(flag)
-+
-+ def filename_change_hook(self):
-+ if self.editwin.flist:
-+ self.editwin.flist.filename_changed_edit(self, self.editwin)
-+ self.saved_change_hook(self.tab_initialized)
-+ self.editwin.top.update_windowlist_registry(self.editwin)
-+ self.reset_colorizer()
-+
-+ def reset_undo(self):
-+ self.undo.reset_undo()
-+
-+ def reset_colorizer(self):
-+ "Update the colour theme"
-+ # Called from self.filename_change_hook and from configDialog.py
-+ self.__rmcolorizer()
-+ self.__addcolorizer()
-+ theme = idleConf.GetOption('main','Theme','name')
-+ normal_colors = idleConf.GetHighlight(theme, 'normal')
-+ cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg')
-+ select_colors = idleConf.GetHighlight(theme, 'hilite')
-+
-+ self.text.config(
-+ foreground=normal_colors['foreground'],
-+ background=normal_colors['background'],
-+ insertbackground=cursor_color,
-+ selectforeground=select_colors['foreground'],
-+ selectbackground=select_colors['background'])
-+
-+ def short_title(self):
-+ filename = self.io.filename
-+ if filename:
-+ filename = os.path.basename(filename)
-+ # return unicode string to display non-ASCII chars correctly
-+ return filename_to_unicode(filename)
-+
-+ def long_title(self):
-+ # return unicode string to display non-ASCII chars correctly
-+ return filename_to_unicode(self.io.filename or "")
-+
-+ def maybesave(self):
-+ if self.io:
-+ if not self.get_saved():
-+ if self.editwin.top.state()!= 'normal':
-+ self.editiwn.top.deiconify()
-+ self.editwin.top.lower()
-+ self.editwin.top.lift()
-+ return self.io.maybesave()
-+ # XXX (1) end
-+
-+ def center(self, mark="insert"):
-+ # Used by EditorWindow.gotoline
-+ text = self.text
-+ top, bot = self._getwindowlines()
-+ lineno = self._getlineno(mark)
-+ height = bot - top
-+ newtop = max(1, lineno - height//2)
-+ text.yview(float(newtop))
-+
-+ def newline_and_indent_event(self, event):
-+ # Used by EditorWindow.newline_and_indent_event which is used by PyShell
-+ text = self.text
-+ first, last = self.get_selection_indices()
-+ text.undo_block_start()
-+ try:
-+ if first and last:
-+ text.delete(first, last)
-+ text.mark_set("insert", first)
-+ line = text.get("insert linestart", "insert")
-+ i, n = 0, len(line)
-+ while i < n and line[i] in " \t":
-+ i = i+1
-+ if i == n:
-+ # the cursor is in or at leading indentation in a continuation
-+ # line; just inject an empty line at the start
-+ text.insert("insert linestart", '\n')
-+ return "break"
-+ indent = line[:i]
-+ # strip whitespace before insert point unless it's in the prompt
-+ i = 0
-+ last_line_of_prompt = sys.ps1.split('\n')[-1]
-+ while line and line[-1] in " \t" and line != last_line_of_prompt:
-+ line = line[:-1]
-+ i = i+1
-+ if i:
-+ text.delete("insert - %d chars" % i, "insert")
-+ # strip whitespace after insert point
-+ while text.get("insert") in " \t":
-+ text.delete("insert")
-+ # start new line
-+ text.insert("insert", '\n')
-+
-+ # adjust indentation for continuations and block
-+ # open/close first need to find the last stmt
-+ lno = index2line(text.index('insert'))
-+ #print self.editwin.indentwidth, self.editwin.tabwidth
-+ y = PyParse.Parser(self.editwin.indentwidth, self.editwin.tabwidth)
-+ if not self.editwin.context_use_ps1:
-+ for context in self.editwin.num_context_lines:
-+ startat = max(lno - context, 1)
-+ startatindex = `startat` + ".0"
-+ rawtext = text.get(startatindex, "insert")
-+ y.set_str(rawtext)
-+ bod = y.find_good_parse_start(
-+ self.editwin.context_use_ps1,
-+ self.build_char_in_string_func(startatindex))
-+ if bod is not None or startat == 1:
-+ break
-+ y.set_lo(bod or 0)
-+ else:
-+ r = text.tag_prevrange("console", "insert")
-+ if r:
-+ startatindex = r[1]
-+ else:
-+ startatindex = "1.0"
-+ rawtext = text.get(startatindex, "insert")
-+ y.set_str(rawtext)
-+ y.set_lo(0)
-+
-+ c = y.get_continuation_type()
-+ if c != PyParse.C_NONE:
-+ # The current stmt hasn't ended yet.
-+ if c == PyParse.C_STRING_FIRST_LINE:
-+ # after the first line of a string; do not indent at all
-+ pass
-+ elif c == PyParse.C_STRING_NEXT_LINES:
-+ # inside a string which started before this line;
-+ # just mimic the current indent
-+ text.insert("insert", indent)
-+ elif c == PyParse.C_BRACKET:
-+ # line up with the first (if any) element of the
-+ # last open bracket structure; else indent one
-+ # level beyond the indent of the line with the
-+ # last open bracket
-+ self.__reindent_to(y.compute_bracket_indent())
-+ elif c == PyParse.C_BACKSLASH:
-+ # if more than one line in this stmt already, just
-+ # mimic the current indent; else if initial line
-+ # has a start on an assignment stmt, indent to
-+ # beyond leftmost =; else to beyond first chunk of
-+ # non-whitespace on initial line
-+ if y.get_num_lines_in_stmt() > 1:
-+ text.insert("insert", indent)
-+ else:
-+ self.__reindent_to(y.compute_backslash_indent())
-+ else:
-+ assert 0, "bogus continuation type %r" % (c,)
-+ return "break"
-+
-+ # This line starts a brand new stmt; indent relative to
-+ # indentation of initial line of closest preceding
-+ # interesting stmt.
-+ indent = y.get_base_indent_string()
-+ text.insert("insert", indent)
-+ if y.is_block_opener():
-+ self._smart_indent_event(event)
-+ elif indent and y.is_block_closer():
-+ self._smart_backspace_event(event)
-+ return "break"
-+ finally:
-+ text.see("insert")
-+ text.undo_block_stop()
-+
-+ # If a selection is defined in the text widget, return (start,
-+ # end) as Tkinter text indices, otherwise return (None, None)
-+ def get_selection_indices(self):
-+ # Used by EditorWindow.get_selection_indices which is used by
-+ # FormatParagraph
-+ try:
-+ first = self.text.index("sel.first")
-+ last = self.text.index("sel.last")
-+ return first, last
-+ except TclError:
-+ return None, None
-+
-+ # Our editpage provides a __is_char_in_string function that works
-+ # with a Tk text index, but PyParse only knows about offsets into
-+ # a string. This builds a function for PyParse that accepts an
-+ # offset.
-+ def build_char_in_string_func(self, startindex):
-+ # Used by EditorWindow.build_char_in_string_func which is used by
-+ # HyperParser
-+ def inner(offset, _startindex=startindex,
-+ _icis=self.__is_char_in_string):
-+ return _icis(_startindex + "+%dc" % offset)
-+ return inner
-+
-+ def _setup_bindings(self):
-+ text = self.text
-+ def bind_them(to_bind, prefix='_%s'):
-+ for tb in to_bind:
-+ prefix_size = tb.count('<')
-+ method_name = tb[prefix_size:-prefix_size].replace('-', '_')
-+ text.bind(tb, getattr(self, prefix % method_name.lower()))
-+
-+ actions = ('<<help>>', '<<python-docs>>',
-+ '<<about-idle>>', '<<open-config-dialog>>', '<<open-module>>',
-+ '<<cut>>', '<<copy>>', '<<paste>>', '<<select-all>>',
-+ '<<remove-selection>>', '<<del-word-left>>', '<<del-word-right>>',
-+ '<<beginning-of-line>>')
-+ events = ('<<find>>', '<<center-insert>>', '<<find-again>>',
-+ '<<find-in-files>>', '<<find-selection>>', '<<replace>>',
-+ '<<goto-line>>', '<<smart-backspace>>', '<<smart-indent>>',
-+ '<<indent-region>>', '<<dedent-region>>', '<<comment-region>>',
-+ '<<tabify-region>>', '<<untabify-region>>', '<<toggle-tabs>>',
-+ '<<change-indentwidth>>')
-+ parent_actions = ('<<new-tab>>', '<<next-tab>>', '<<prev-tab>>')
-+
-+ bind_them(actions)
-+ bind_them(events, prefix="_%s_event")
-+ for action in parent_actions:
-+ prefix_size = action.count('<')
-+ method_name = action[prefix_size:-prefix_size].replace('-', '_')
-+ text.bind(action, getattr(self.editwin, method_name))
-+
-+ text.bind('<<close-tab>>', self.close_tab)
-+ text.bind('<<newline-and-indent>>', self.newline_and_indent_event)
-+ text.bind("<<do-nothing>>", lambda event: "break")
-+ text.bind("<Left>", self._move_at_edge_if_selection(0))
-+ text.bind("<Right>", self._move_at_edge_if_selection(1))
-+ text.bind("<3>", self._right_menu)
-+ text.bind('<<set-line-and-column>>', self.editwin.set_line_and_column)
-+ text.event_add("<<set-line-and-column>>",
-+ "<KeyRelease>", "<ButtonRelease>")
-+
-+ if self.editwin.flist:
-+ text.bind("<<open-new-window>>",
-+ utils.callback(self.editwin.new_callback, self))
-+ text.bind("<<close-all-windows>>",
-+ self.editwin.flist.close_all_callback)
-+ text.bind("<<open-class-browser>>", self._open_class_browser)
-+ text.bind("<<open-path-browser>>", self._open_path_browser)
-+
-+ if macosxSupport.runningAsOSXApp():
-+ # Command-W on editorwindows doesn't work without this.
-+ text.bind('<<close-window>>', self.editwin.close_event)
-+
-+ def _help(self, event=None):
-+ fn = os.path.join(os.path.abspath(os.path.dirname(__file__)),
-+ 'help.txt')
-+ textView.view_file(self.text, 'Help', fn)
-+
-+ def _python_docs(self, event=None):
-+ if sys.platform[:3] == 'win':
-+ os.startfile(self.editwin.help_url)
-+ else:
-+ webbrowser.open(self.editwin.help_url)
-+ return "break"
-+
-+ def _about_idle(self, event=None):
-+ aboutDialog.AboutDialog(self.text, 'About IDLE')
-+
-+ def _open_class_browser(self, event=None):
-+ filename = self.io.filename
-+ if not filename:
-+ tkMessageBox.showerror("No filename",
-+ "This buffer has no associated filename",
-+ master=self.text)
-+ self.text.focus_set()
-+ return None
-+ head, tail = os.path.split(filename)
-+ base, ext = os.path.splitext(tail)
-+ ClassBrowser.ClassBrowser(self.editwin.flist, base, [head])
-+
-+ def _open_path_browser(self, event=None):
-+ PathBrowser.PathBrowser(self.editwin.flist)
-+
-+ def _open_config_dialog(self, event=None):
-+ # When changing colors and saving it, it requires the attribute
-+ # instance_dict making necessary to pass self.editwin.top as the
-+ # parent
-+ configDialog.ConfigDialog(self.editwin.top, 'Settings')
-+
-+ def _open_module(self, event=None):
-+ try:
-+ name = self.text.get("sel.first", "sel.last")
-+ except TclError:
-+ name = ""
-+ else:
-+ name = name.strip()
-+
-+ name = tkSimpleDialog.askstring("Module",
-+ "Enter the name of a Python module\n"
-+ "to search on sys.path and open:",
-+ parent=self.text, initialvalue=name)
-+
-+ if name:
-+ name = name.strip()
-+ if not name:
-+ return
-+ # XXX Ought to insert current file's directory in front of path
-+ try:
-+ (f, file, (suffix, mode, type)) = _find_module(name)
-+ except (NameError, ImportError), msg:
-+ tkMessageBox.showerror("Import error", str(msg), parent=self.text)
-+ return
-+
-+ if type != imp.PY_SOURCE:
-+ tkMessageBox.showerror("Unsupported type",
-+ "%s is not a source module" % name, parent=self.text)
-+ return
-+ if f:
-+ f.close()
-+ if self.editwin.flist:
-+ if idleConf.GetOption('main', 'EditorWindow', 'file-in-tab',
-+ default=1, type='bool'):
-+ if hasattr(self.editwin, 'interp'):
-+ # PyShell window must open a module in a new window
-+ action = None
-+ else:
-+ action = self.editwin.new_tab
-+ else:
-+ action = None
-+ self.editwin.flist.open(file, action)
-+ else:
-+ self.io.loadfile(file)
-+
-+ def _find_event(self, event):
-+ SearchDialog.find(self.text)
-+ return "break"
-+
-+ def _find_again_event(self, event):
-+ SearchDialog.find_again(self.text)
-+ return "break"
-+
-+ def _find_selection_event(self, event):
-+ SearchDialog.find_selection(self.text)
-+ return "break"
-+
-+ def _find_in_files_event(self, event):
-+ # XXX not expected to work correctly for now
-+ GrepDialog.grep(self.text, self.editwin.io, self.editwin.flist)
-+ return "break"
-+
-+ def _replace_event(self, event):
-+ ReplaceDialog.replace(self.text)
-+ return "break"
-+
-+ def _center_insert_event(self, event):
-+ self.center()
-+
-+ def _getwindowlines(self):
-+ text = self.text
-+ top = self._getlineno("@0,0")
-+ bot = self._getlineno("@0,65535")
-+ if top == bot and text.winfo_height() == 1:
-+ # Geometry manager hasn't run yet
-+ height = int(text['height'])
-+ bot = top + height - 1
-+ return top, bot
-+
-+ def _getlineno(self, mark="insert"):
-+ return int(float(self.text.index(mark)))
-+
-+ def _goto_line_event(self, event):
-+ text = self.text
-+ lineno = tkSimpleDialog.askinteger("Goto", "Go to line number:",
-+ parent=text)
-+
-+ if lineno is None:
-+ return "break"
-+
-+ if lineno <= 0:
-+ text.bell()
-+ return "break"
-+
-+ text.mark_set("insert", "%d.0" % lineno)
-+ text.see("insert")
-+
-+ def _cut(self, event):
-+ self.text.event_generate("<<Cut>>")
-+ return "break"
-+
-+ def _copy(self, event):
-+ if not self.text.tag_ranges("sel"):
-+ # There is no selection, so do nothing and maybe interrupt.
-+ return
-+
-+ self.text.event_generate("<<Copy>>")
-+ return "break"
-+
-+ def _paste(self, event):
-+ self.text.event_generate("<<Paste>>")
-+ self.text.see("insert")
-+ return "break"
-+
-+ def _select_all(self, event=None):
-+ self.text.tag_add("sel", "1.0", "end-1c")
-+ self.text.mark_set("insert", "1.0")
-+ self.text.see("insert")
-+ return "break"
-+
-+ def _remove_selection(self, event=None):
-+ self.text.tag_remove("sel", "1.0", "end")
-+ self.text.see("insert")
-+
-+ def _del_word_left(self, event):
-+ self.text.event_generate('<Meta-Delete>')
-+ return "break"
-+
-+ def _del_word_right(self, event):
-+ self.text.event_generate('<Meta-d>')
-+ return "break"
-+
-+ def _move_at_edge_if_selection(self, edge_index):
-+ """Cursor move begins at start or end of selection
-+ When a left/right cursor key is pressed create and return to Tkinter a
-+ function which causes a cursor move from the associated edge of the
-+ selection.
-+ """
-+ text_index = self.text.index
-+ text_mark_set = self.text.mark_set
-+ edges_table = ("sel.first+1c", "sel.last-1c")
-+
-+ def move_at_edge(event):
-+ if (event.state & 5) == 0: # no shift(==1) or control(==4) pressed
-+ try:
-+ text_index("sel.first")
-+ text_mark_set("insert", edges_table[edge_index])
-+ except TclError:
-+ pass
-+
-+ return move_at_edge
-+
-+ def _beginning_of_line(self, event):
-+ if (event.state & 12) != 0 and event.keysym == "Home":
-+ # state&1==shift, state&4==control, state&8==alt
-+ return # <Modifier-Home>; fall back to class binding
-+
-+ text = self.text
-+
-+ if text.index("iomark") and \
-+ text.compare("iomark", "<=", "insert lineend") and \
-+ text.compare("insert linestart", "<=", "iomark"):
-+ insertpt = int(text.index("iomark").split(".")[1])
-+ else:
-+ line = text.get("insert linestart", "insert lineend")
-+ for insertpt in xrange(len(line)):
-+ if line[insertpt] not in (' ','\t'):
-+ break
-+ else:
-+ insertpt=len(line)
-+
-+ lineat = int(text.index("insert").split('.')[1])
-+
-+ if insertpt == lineat:
-+ insertpt = 0
-+
-+ dest = "insert linestart+%sc" % str(insertpt)
-+
-+ if (event.state & 1) == 0:
-+ # shift not pressed
-+ text.tag_remove("sel", "1.0", "end")
-+ else:
-+ if not text.index("sel.first"):
-+ text.mark_set("anchor", "insert")
-+
-+ first = text.index(dest)
-+ last = text.index("anchor")
-+
-+ if text.compare(first, ">", last):
-+ first, last = last, first
-+
-+ text.tag_remove("sel", "1.0", "end")
-+ text.tag_add("sel", first, last)
-+
-+ text.mark_set("insert", dest)
-+ text.see("insert")
-+ return "break"
-+
-+ def _smart_backspace_event(self, event):
-+ text = self.text
-+ first, last = self.get_selection_indices()
-+ if first and last:
-+ text.delete(first, last)
-+ text.mark_set("insert", first)
-+ return "break"
-+ # Delete whitespace left, until hitting a real char or closest
-+ # preceding virtual tab stop.
-+ chars = text.get("insert linestart", "insert")
-+ if chars == '':
-+ if text.compare("insert", ">", "1.0"):
-+ # easy: delete preceding newline
-+ text.delete("insert-1c")
-+ else:
-+ text.bell() # at start of buffer
-+ return "break"
-+ if chars[-1] not in " \t":
-+ # easy: delete preceding real char
-+ text.delete("insert-1c")
-+ return "break"
-+ # Ick. It may require *inserting* spaces if we back up over a
-+ # tab character! This is written to be clear, not fast.
-+ tabwidth = self.editwin.tabwidth
-+ have = len(chars.expandtabs(tabwidth))
-+ assert have > 0
-+ want = ((have - 1) //
-+ self.editwin.indentwidth) * self.editwin.indentwidth
-+ # Debug prompt is multilined....
-+ last_line_of_prompt = sys.ps1.split('\n')[-1]
-+ ncharsdeleted = 0
-+ while 1:
-+ if chars == last_line_of_prompt:
-+ break
-+ chars = chars[:-1]
-+ ncharsdeleted = ncharsdeleted + 1
-+ have = len(chars.expandtabs(tabwidth))
-+ if have <= want or chars[-1] not in " \t":
-+ break
-+ text.undo_block_start()
-+ text.delete("insert-%dc" % ncharsdeleted, "insert")
-+ if have < want:
-+ text.insert("insert", ' ' * (want - have))
-+ text.undo_block_stop()
-+ return "break"
-+
-+ def _smart_indent_event(self, event):
-+ # if intraline selection:
-+ # delete it
-+ # elif multiline selection:
-+ # do indent-region
-+ # else:
-+ # indent one level
-+ text = self.text
-+ first, last = self.get_selection_indices()
-+ text.undo_block_start()
-+ try:
-+ if first and last:
-+ if index2line(first) != index2line(last):
-+ return self._indent_region_event(event)
-+ text.delete(first, last)
-+ text.mark_set("insert", first)
-+ prefix = text.get("insert linestart", "insert")
-+ raw, effective = classifyws(prefix, self.editwin.tabwidth)
-+ if raw == len(prefix):
-+ # only whitespace to the left
-+ self.__reindent_to(effective + self.editwin.indentwidth)
-+ else:
-+ # tab to the next 'stop' within or to right of line's text:
-+ if self.editwin.usetabs:
-+ pad = '\t'
-+ else:
-+ effective = len(prefix.expandtabs(self.editwin.tabwidth))
-+ n = self.editwin.indentwidth
-+ pad = ' ' * (n - effective % n)
-+ text.insert("insert", pad)
-+ text.see("insert")
-+ return "break"
-+ finally:
-+ text.undo_block_stop()
-+
-+ def _indent_region_event(self, event):
-+ head, tail, chars, lines = self.__get_region()
-+ for pos in range(len(lines)):
-+ line = lines[pos]
-+ if line:
-+ raw, effective = classifyws(line, self.editwin.tabwidth)
-+ effective = effective + self.editwin.indentwidth
-+ lines[pos] = self.__make_blanks(effective) + line[raw:]
-+ self.__set_region(head, tail, chars, lines)
-+ return "break"
-+
-+ def _dedent_region_event(self, event):
-+ head, tail, chars, lines = self.__get_region()
-+ for pos in range(len(lines)):
-+ line = lines[pos]
-+ if line:
-+ raw, effective = classifyws(line, self.editwin.tabwidth)
-+ effective = max(effective - self.editwin.indentwidth, 0)
-+ lines[pos] = self.__make_blanks(effective) + line[raw:]
-+ self.__set_region(head, tail, chars, lines)
-+ return "break"
-+
-+ def _comment_region_event(self, event):
-+ head, tail, chars, lines = self.__get_region()
-+ for pos in range(len(lines) - 1):
-+ line = lines[pos]
-+ lines[pos] = '##' + line
-+ self.__set_region(head, tail, chars, lines)
-+
-+ def _uncomment_region_event(self, event):
-+ head, tail, chars, lines = self.__get_region()
-+ for pos in range(len(lines)):
-+ line = lines[pos]
-+ if not line:
-+ continue
-+ if line[:2] == '##':
-+ line = line[2:]
-+ elif line[:1] == '#':
-+ line = line[1:]
-+ lines[pos] = line
-+ self.__set_region(head, tail, chars, lines)
-+
-+ def _tabify_region_event(self, event):
-+ head, tail, chars, lines = self.__get_region()
-+ tabwidth = self.__asktabwidth()
-+ for pos in range(len(lines)):
-+ line = lines[pos]
-+ if line:
-+ raw, effective = classifyws(line, tabwidth)
-+ ntabs, nspaces = divmod(effective, tabwidth)
-+ lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:]
-+ self.__set_region(head, tail, chars, lines)
-+
-+ def _untabify_region_event(self, event):
-+ head, tail, chars, lines = self.__get_region()
-+ tabwidth = self.__asktabwidth()
-+ for pos in range(len(lines)):
-+ lines[pos] = lines[pos].expandtabs(tabwidth)
-+ self.__set_region(head, tail, chars, lines)
-+
-+ def _toggle_tabs_event(self, event):
-+ if self.editwin.askyesno(
-+ "Toggle tabs",
-+ "Turn tabs " + ("on", "off")[self.editwin.usetabs] +
-+ "?\nIndent width " +
-+ ("will be", "remains at")[self.editwin.usetabs] + " 8." +
-+ "\n Note: a tab is always 8 columns",
-+ parent=self.text):
-+ self.editwin.usetabs = not self.editwin.usetabs
-+ # Try to prevent inconsistent indentation.
-+ # User must change indent width manually after using tabs.
-+ self.editwin.indentwidth = 8
-+ return "break"
-+
-+ def _change_indentwidth_event(self, event):
-+ new = self.editwin.askinteger(
-+ "Indent width",
-+ "New indent width (2-16)\n(Always use 8 when using tabs)",
-+ parent=self.text,
-+ initialvalue=self.editwin.indentwidth,
-+ minvalue=2,
-+ maxvalue=16)
-+ if new and new != self.editwin.indentwidth and not self.editwin.usetabs:
-+ self.editwin.indentwidth = new
-+ return "break"
-+
-+ def _right_menu(self, event):
-+ self.text.tag_remove("sel", "1.0", "end")
-+ self.text.mark_set("insert", "@%d,%d" % (event.x, event.y))
-+
-+ if not self.editwin.rmenu:
-+ self.__make_rmenu()
-+
-+ rmenu = self.editwin.rmenu
-+ self.event = event
-+ iswin = sys.platform[:3] == 'win'
-+ if iswin:
-+ self.text.config(cursor="arrow")
-+ rmenu.tk_popup(event.x_root, event.y_root)
-+ if iswin:
-+ self.text.config(cursor="ibeam")
-+
-+ def __make_rmenu(self):
-+ rmenu = Menu(self.text, tearoff=False)
-+
-+ for label, eventname in self.editwin.rmenu_specs:
-+ def command(text=self.text, eventname=eventname):
-+ text.event_generate(eventname)
-+ rmenu.add_command(label=label, command=command)
-+
-+ self.editwin.rmenu = rmenu
-+
-+ def __rmcolorizer(self):
-+ if not self.color:
-+ return
-+ self.color.removecolors()
-+ self.per.removefilter(self.color)
-+ self.color = None
-+
-+ def __addcolorizer(self):
-+ if self.color:
-+ return
-+ if self.editwin.ispythonsource(self.io.filename):
-+ self.color = self.editwin.ColorDelegator()
-+
-+ # can add more colorizers here...
-+ if self.color:
-+ self.per.removefilter(self.undo)
-+ self.per.insertfilter(self.color)
-+ self.per.insertfilter(self.undo)
-+
-+ def __asktabwidth(self):
-+ return self.editwin.askinteger(
-+ "Tab width",
-+ "Columns per tab? (2-16)",
-+ parent=self.text,
-+ initialvalue=self.editwin.indentwidth,
-+ minvalue=2,
-+ maxvalue=16) or self.editwin.tabwidth
-+
-+ # Make string that displays as n leading blanks.
-+ def __make_blanks(self, n):
-+ if self.editwin.usetabs:
-+ ntabs, nspaces = divmod(n, self.editwin.tabwidth)
-+ return '\t' * ntabs + ' ' * nspaces
-+ else:
-+ return ' ' * n
-+
-+ def __get_region(self):
-+ text = self.text
-+ first, last = self.get_selection_indices()
-+ if first and last:
-+ head = text.index(first + " linestart")
-+ tail = text.index(last + "-1c lineend +1c")
-+ else:
-+ head = text.index("insert linestart")
-+ tail = text.index("insert lineend +1c")
-+ chars = text.get(head, tail)
-+ lines = chars.split("\n")
-+ return head, tail, chars, lines
-+
-+ def __set_region(self, head, tail, chars, lines):
-+ text = self.text
-+ newchars = "\n".join(lines)
-+ if newchars == chars:
-+ text.bell()
-+ return
-+ text.tag_remove("sel", "1.0", "end")
-+ text.mark_set("insert", head)
-+ text.undo_block_start()
-+ text.delete(head, tail)
-+ text.insert(head, newchars)
-+ text.undo_block_stop()
-+ text.tag_add("sel", head, "insert")
-+
-+ # Delete from beginning of line to insert point, then reinsert
-+ # column logical (meaning use tabs if appropriate) spaces.
-+ def __reindent_to(self, column):
-+ text = self.text
-+ text.undo_block_start()
-+ if text.compare("insert linestart", "!=", "insert"):
-+ text.delete("insert linestart", "insert")
-+ if column:
-+ text.insert("insert", self.__make_blanks(column))
-+ text.undo_block_stop()
-+
-+ # Tk implementations of "virtual text methods" -- each platform
-+ # reusing IDLE's support code needs to define these for its GUI's
-+ # flavor of widget.
-+
-+ # Is character at text_index in a Python string? Return 0 for
-+ # "guaranteed no", true for anything else. This info is expensive
-+ # to compute ab initio, but is probably already known by the
-+ # platform's colorizer.
-+ def __is_char_in_string(self, text_index):
-+ if self.color:
-+ # Return true iff colorizer hasn't (re)gotten this far
-+ # yet, or the character is tagged as being in a string
-+ return self.text.tag_prevrange("TODO", text_index) or \
-+ "STRING" in self.text.tag_names(text_index)
-+ else:
-+ # The colorizer is missing: assume the worst
-+ return 1
-Index: OutputWindow.py
-===================================================================
---- OutputWindow.py (revision 63995)
-+++ OutputWindow.py (revision 65541)
-@@ -1,8 +1,9 @@
--from Tkinter import *
--from EditorWindow import EditorWindow
- import re
- import tkMessageBox
-+
-+import utils
- import IOBinding
-+from EditorWindow import EditorWindow
-
- class OutputWindow(EditorWindow):
-
-@@ -14,8 +15,15 @@
-
- def __init__(self, *args):
- EditorWindow.__init__(self, *args)
-- self.text.bind("<<goto-file-line>>", self.goto_file_line)
-+ self.top.bind("<<tab-created>>", self.__configure_new_tab)
-+ # configure the tab created in EditorWindow.__init__
-+ self.__configure_new_tab()
-
-+ def __configure_new_tab(self, event=None):
-+ page = self.text_notebook.last_page().editpage
-+ page.text.bind("<<goto-file-line>>", utils.callback(self.goto_file_line,
-+ page.text))
-+
- # Customize EditorWindow
-
- def ispythonsource(self, filename):
-@@ -34,7 +42,8 @@
-
- # Act as output file
-
-- def write(self, s, tags=(), mark="insert"):
-+ def write(self, s, tags=(), mark="insert", text=None):
-+ assert text is not None
- # Tk assumes that byte strings are Latin-1;
- # we assume that they are in the locale's encoding
- if isinstance(s, str):
-@@ -43,12 +52,12 @@
- except UnicodeError:
- # some other encoding; let Tcl deal with it
- pass
-- self.text.insert(mark, s, tags)
-- self.text.see(mark)
-- self.text.update()
-+ text.insert(mark, s, tags)
-+ text.see(mark)
-+ text.update()
-
- def writelines(self, l):
-- map(self.write, l)
-+ map(self.write, l, text=self.current_page.text)
-
- def flush(self):
- pass
-@@ -67,28 +76,26 @@
-
- file_line_progs = None
-
-- def goto_file_line(self, event=None):
-+ def goto_file_line(self, event, text):
- if self.file_line_progs is None:
- l = []
- for pat in self.file_line_pats:
- l.append(re.compile(pat, re.IGNORECASE))
- self.file_line_progs = l
-- # x, y = self.event.x, self.event.y
-- # self.text.mark_set("insert", "@%d,%d" % (x, y))
-- line = self.text.get("insert linestart", "insert lineend")
-+
-+ line = text.get("insert linestart", "insert lineend")
- result = self._file_line_helper(line)
- if not result:
- # Try the previous line. This is handy e.g. in tracebacks,
- # where you tend to right-click on the displayed source line
-- line = self.text.get("insert -1line linestart",
-- "insert -1line lineend")
-+ line = text.get("insert -1line linestart", "insert -1line ineend")
- result = self._file_line_helper(line)
- if not result:
- tkMessageBox.showerror(
- "No special line",
- "The line you point at doesn't look like "
- "a valid file name followed by a line number.",
-- master=self.text)
-+ master=text)
- return
- filename, lineno = result
- edit = self.flist.open(filename)
-@@ -111,47 +118,3 @@
- return filename, int(lineno)
- except TypeError:
- return None
--
--# These classes are currently not used but might come in handy
--
--class OnDemandOutputWindow:
--
-- tagdefs = {
-- # XXX Should use IdlePrefs.ColorPrefs
-- "stdout": {"foreground": "blue"},
-- "stderr": {"foreground": "#007700"},
-- }
--
-- def __init__(self, flist):
-- self.flist = flist
-- self.owin = None
--
-- def write(self, s, tags, mark):
-- if not self.owin:
-- self.setup()
-- self.owin.write(s, tags, mark)
--
-- def setup(self):
-- self.owin = owin = OutputWindow(self.flist)
-- text = owin.text
-- for tag, cnf in self.tagdefs.items():
-- if cnf:
-- text.tag_configure(tag, **cnf)
-- text.tag_raise('sel')
-- self.write = self.owin.write
--
--#class PseudoFile:
--#
--# def __init__(self, owin, tags, mark="end"):
--# self.owin = owin
--# self.tags = tags
--# self.mark = mark
--
--# def write(self, s):
--# self.owin.write(s, self.tags, self.mark)
--
--# def writelines(self, l):
--# map(self.write, l)
--
--# def flush(self):
--# pass
-Index: aboutDialog.py
-===================================================================
---- aboutDialog.py (revision 63995)
-+++ aboutDialog.py (revision 65541)
-@@ -1,13 +1,18 @@
--"""About Dialog for IDLE
-+"""About Dialog for IDLE"""
-+import os
-+import sys
-+from Tkinter import Toplevel, Frame, Button, Label, TkVersion
-+from Tkconstants import LEFT, NSEW, SUNKEN, EW, W, BOTH, TOP, BOTTOM
-
--"""
--
--from Tkinter import *
--import os
--import os.path
-+import idlever
- import textView
--import idlever
-+from stylist import PoorManStyle
-+from configHandler import idleConf
-
-+TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
-+if TTK:
-+ from ttk import Frame, Button, Label, Style
-+
- class AboutDialog(Toplevel):
- """Modal about dialog for idle
-
-@@ -15,12 +20,15 @@
- def __init__(self,parent,title):
- Toplevel.__init__(self, parent)
- self.configure(borderwidth=5)
-+
- self.geometry("+%d+%d" % (parent.winfo_rootx()+30,
- parent.winfo_rooty()+30))
- self.bg = "#707070"
- self.fg = "#ffffff"
-+
-+ self.SetupStyles()
- self.CreateWidgets()
-- self.resizable(height=FALSE, width=FALSE)
-+ self.resizable(height=False, width=False)
- self.title(title)
- self.transient(parent)
- self.grab_set()
-@@ -31,40 +39,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.pack(side=BOTTOM, fill=X)
-- frameMain.pack(side=TOP, expand=TRUE, fill=BOTH)
-- 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)
-- frameBg.pack(expand=TRUE, fill=BOTH)
-- labelTitle = Label(frameBg, text='IDLE', fg=self.fg, bg=self.bg,
-- font=('courier', 24, 'bold'))
-+ 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.pack()
-+ frameBg = Frame(frameMain)
-+ frameBg.pack(expand=True, fill=BOTH)
-+ 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,
-- fg=self.fg, bg=self.bg)
-+ 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)
- 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)
- labelWWW.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0)
-- Frame(frameBg, borderwidth=1, relief=SUNKEN,
-- height=2, bg=self.bg).grid(row=8, column=0, sticky=EW,
-- 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])
- 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('.')
-@@ -72,44 +84,50 @@
- if tkVer[len(tkVer)-1] == '':
- tkVer[len(tkVer)-1] = '0'
- tkVer = '.'.join(tkVer)
-- labelTkVer = Label(frameBg, text='Tk version: '+
-- tkVer, fg=self.fg, bg=self.bg)
-+ 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)
- py_button_f.grid(row=10, column=0, columnspan=2, sticky=NSEW)
- buttonLicense = Button(py_button_f, text='License', width=8,
-- highlightbackground=self.bg,
- command=self.ShowLicense)
- buttonLicense.pack(side=LEFT, padx=10, pady=10)
- buttonCopyright = Button(py_button_f, text='Copyright', width=8,
-- highlightbackground=self.bg,
- command=self.ShowCopyright)
- buttonCopyright.pack(side=LEFT, padx=10, pady=10)
- buttonCredits = Button(py_button_f, text='Credits', width=8,
-- highlightbackground=self.bg,
- command=self.ShowPythonCredits)
- buttonCredits.pack(side=LEFT, padx=10, pady=10)
-- Frame(frameBg, borderwidth=1, relief=SUNKEN,
-- height=2, bg=self.bg).grid(row=11, column=0, sticky=EW,
-- columnspan=3, padx=5, pady=5)
-- idle_v = Label(frameBg, text='IDLE version: ' + idlever.IDLE_VERSION,
-- fg=self.fg, bg=self.bg)
-+ 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)
- 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,
- command=self.ShowIDLEAbout)
- idle_about_b.pack(side=LEFT, padx=10, pady=10)
- idle_news_b = Button(idle_button_f, text='NEWS', width=8,
-- highlightbackground=self.bg,
- command=self.ShowIDLENEWS)
- idle_news_b.pack(side=LEFT, padx=10, pady=10)
- idle_credits_b = Button(idle_button_f, text='Credits', width=8,
-- highlightbackground=self.bg,
- 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)
-
-@@ -142,9 +160,9 @@
-
- if __name__ == '__main__':
- # test the dialog
-+ from Tkinter import Tk
- root = Tk()
- def run():
-- import aboutDialog
-- aboutDialog.AboutDialog(root, 'About')
-+ AboutDialog(root, 'About')
- Button(root, text='Dialog', command=run).pack()
- root.mainloop()
-Index: config-main.def
-===================================================================
---- config-main.def (revision 63995)
-+++ config-main.def (revision 65541)
-@@ -49,8 +49,14 @@
- print-command-posix=lpr %s
- print-command-win=start /min notepad /p %s
- delete-exitfunc= 1
-+use-ttk = 0
-
- [EditorWindow]
-+width = 80
-+height = 40
-+file-in-tab = 1
-+
-+[EditorPage]
- width= 80
- height= 40
- font= courier
-@@ -68,6 +74,7 @@
- [Theme]
- default= 1
- name= IDLE Classic
-+displaytheme = default
-
- [Keys]
- default= 1
-Index: PathBrowser.py
-===================================================================
---- PathBrowser.py (revision 63995)
-+++ PathBrowser.py (revision 65541)
-@@ -15,25 +15,29 @@
- self.top.wm_iconname("Path Browser")
-
- def rootnode(self):
-- return PathBrowserTreeItem()
-+ return PathBrowserTreeItem(self.flist)
-
- class PathBrowserTreeItem(TreeItem):
-
-+ def __init__(self, flist):
-+ self.flist = flist
-+
- def GetText(self):
- return "sys.path"
-
- def GetSubList(self):
- sublist = []
- for dir in sys.path:
-- item = DirBrowserTreeItem(dir)
-+ item = DirBrowserTreeItem(dir, flist=self.flist)
- sublist.append(item)
- return sublist
-
- class DirBrowserTreeItem(TreeItem):
-
-- def __init__(self, dir, packages=[]):
-+ def __init__(self, dir, packages=[], flist=None):
- self.dir = dir
- self.packages = packages
-+ self.flist = flist
-
- def GetText(self):
- if not self.packages:
-@@ -55,10 +59,11 @@
- packages.sort()
- sublist = []
- for nn, name, file in packages:
-- item = DirBrowserTreeItem(file, self.packages + [name])
-+ item = DirBrowserTreeItem(file, self.packages + [name], self.flist)
- sublist.append(item)
- for nn, name in self.listmodules(names):
-- item = ModuleBrowserTreeItem(os.path.join(self.dir, name))
-+ item = ModuleBrowserTreeItem(os.path.join(self.dir, name),
-+ self.flist)
- sublist.append(item)
- return sublist
-
-Index: IOBinding.py
-===================================================================
---- IOBinding.py (revision 63995)
-+++ IOBinding.py (revision 65541)
-@@ -6,17 +6,20 @@
- # which will only understand the local convention.
-
- import os
-+import re
-+import sys
- import types
--import sys
- import codecs
- import tempfile
- import tkFileDialog
- import tkMessageBox
--import re
--from Tkinter import *
-+from Tkinter import Toplevel, Entry, Frame, Button, Label
-+from Tkconstants import W, X, TOP, LEFT, BOTH
- from SimpleDialog import SimpleDialog
-
- from configHandler import idleConf
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
-+ from ttk import Entry, Frame, Button, Label
-
- try:
- from codecs import BOM_UTF8
-@@ -93,11 +96,11 @@
- # For some reason, the text is not selectable anymore if the
- # widget is disabled.
- # l2['state'] = DISABLED
-- l2.pack(side=TOP, anchor = W, fill=X)
-+ l2.pack(side=TOP, anchor=W, fill=X)
- l3 = Label(top, text="to your file\n"
- "Choose OK to save this file as %s\n"
- "Edit your general options to silence this warning" % enc)
-- l3.pack(side=TOP, anchor = W)
-+ l3.pack(side=TOP, anchor=W)
-
- buttons = Frame(top)
- buttons.pack(side=TOP, fill=X)
-@@ -142,10 +145,14 @@
-
-
- class IOBinding:
-+ filename_change_hook = None
-+ filename = None
-+ dirname = None
-
-- def __init__(self, editwin):
-- self.editwin = editwin
-- self.text = editwin.text
-+ def __init__(self, editpage):
-+ self.editpage = editpage
-+ self.editwin = editpage.editwin
-+ self.text = editpage.text
- self.__id_open = self.text.bind("<<open-window-from-file>>", self.open)
- self.__id_save = self.text.bind("<<save-window>>", self.save)
- self.__id_saveas = self.text.bind("<<save-window-as-file>>",
-@@ -163,27 +170,23 @@
- self.text.unbind("<<save-copy-of-window-as-file>>", self.__id_savecopy)
- self.text.unbind("<<print-window>>", self.__id_print)
- # Break cycles
-+ self.text = None
-+ self.editpage = None
- self.editwin = None
-- self.text = None
- self.filename_change_hook = None
-
- def get_saved(self):
-- return self.editwin.get_saved()
-+ return self.editpage.get_saved()
-
- def set_saved(self, flag):
-- self.editwin.set_saved(flag)
-+ self.editpage.set_saved(flag)
-
- def reset_undo(self):
-- self.editwin.reset_undo()
-+ self.editpage.reset_undo()
-
-- filename_change_hook = None
--
- def set_filename_change_hook(self, hook):
- self.filename_change_hook = hook
-
-- filename = None
-- dirname = None
--
- def set_filename(self, filename):
- if filename and os.path.isdir(filename):
- self.filename = None
-@@ -200,21 +203,33 @@
- if not editFile:
- filename = self.askopenfile()
- else:
-- filename=editFile
-+ filename = editFile
- if filename:
- # If the current window has no filename and hasn't been
-- # modified, we replace its contents (no loss). Otherwise
-- # we open a new window. But we won't replace the
-- # shell window (which has an interp(reter) attribute), which
-- # gets set to "not modified" at every new prompt.
-+ # modified, we replace its contents (no loss). Otherwise
-+ # we open a new window, or maybe open in a tab.
-+ # But we won't replace the shell window (which has an
-+ # interp(reter) attribute), which gets set to "not modified"
-+ # at every new prompt.
- try:
- interp = self.editwin.interp
- except AttributeError:
- interp = None
-+
- if not self.filename and self.get_saved() and not interp:
- self.editwin.flist.open(filename, self.loadfile)
- else:
-- self.editwin.flist.open(filename)
-+ if idleConf.GetOption('main', 'EditorWindow',
-+ 'file-in-tab', default=1, type='bool'):
-+ if interp:
-+ # this is a PyShell, force file to be opened in a
-+ # new window
-+ action = None
-+ else:
-+ action = self.editwin.new_tab
-+ else:
-+ action = None
-+ self.editwin.flist.open(filename, action)
- else:
- self.text.focus_set()
- return "break"
-@@ -341,8 +356,8 @@
- if self.writefile(self.filename):
- self.set_saved(1)
- try:
-- self.editwin.store_file_breaks()
-- except AttributeError: # may be a PyShell
-+ self.editwin.store_file_breaks(self.editpage)
-+ except AttributeError: # may not be a PyShell
- pass
- self.text.focus_set()
- return "break"
-@@ -354,7 +369,7 @@
- self.set_filename(filename)
- self.set_saved(1)
- try:
-- self.editwin.store_file_breaks()
-+ self.editwin.store_file_breaks(self.editpage)
- except AttributeError:
- pass
- self.text.focus_set()
-@@ -381,8 +396,7 @@
- f.close()
- return True
- except IOError, msg:
-- tkMessageBox.showerror("I/O Error", str(msg),
-- master=self.text)
-+ tkMessageBox.showerror("I/O Error", str(msg), master=self.text)
- return False
-
- def encode(self, chars):
-@@ -429,8 +443,7 @@
- return BOM_UTF8 + chars.encode("utf-8")
- # Nothing was declared, and we had not determined an encoding
- # on loading. Recommend an encoding line.
-- config_encoding = idleConf.GetOption("main","EditorWindow",
-- "encoding")
-+ config_encoding = idleConf.GetOption("main", "EditorPage", "encoding")
- if config_encoding == 'utf-8':
- # User has requested that we save files as UTF-8
- return BOM_UTF8 + chars.encode("utf-8")
-@@ -563,6 +576,7 @@
- self.editwin.update_recent_files_list(filename)
-
- def test():
-+ from Tkinter import Tk, Text
- root = Tk()
- class MyEditWin:
- def __init__(self, text):
-Index: WindowList.py
-===================================================================
---- WindowList.py (revision 63995)
-+++ WindowList.py (revision 65541)
-@@ -1,4 +1,4 @@
--from Tkinter import *
-+from Tkinter import Toplevel, TclError
-
- class WindowList:
-
-@@ -45,8 +45,8 @@
- try:
- callback()
- except:
-- print "warning: callback failed in WindowList", \
-- sys.exc_type, ":", sys.exc_value
-+ print ("warning: callback failed in WindowList",
-+ sys.exc_type, ":", sys.exc_value)
-
- registry = WindowList()
-
-Index: ScrolledList.py
-===================================================================
---- ScrolledList.py (revision 63995)
-+++ ScrolledList.py (revision 65541)
-@@ -1,5 +1,9 @@
--from Tkinter import *
-+from Tkinter import Frame, Menu, Listbox, Scrollbar
-+from idlelib.configHandler import idleConf
-
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
-+ from ttk import Frame, Scrollbar
-+
- class ScrolledList:
-
- default = "(None)"
-@@ -120,6 +124,7 @@
-
-
- def test():
-+ from Tkinter import Tk
- root = Tk()
- root.protocol("WM_DELETE_WINDOW", root.destroy)
- class MyScrolledList(ScrolledList):
-Index: ClassBrowser.py
-===================================================================
---- ClassBrowser.py (revision 63995)
-+++ ClassBrowser.py (revision 65541)
-@@ -14,7 +14,6 @@
- import sys
- import pyclbr
-
--import PyShell
- from WindowList import ListedToplevel
- from TreeWidget import TreeNode, TreeItem, ScrolledCanvas
- from configHandler import idleConf
-@@ -26,6 +25,7 @@
- # XXX the code here is bogus!
- self.name = name
- self.file = os.path.join(path[0], self.name + ".py")
-+ self.flist = None
- self.init(flist)
-
- def close(self, event=None):
-@@ -57,12 +57,13 @@
- self.top.wm_iconname("Class Browser")
-
- def rootnode(self):
-- return ModuleBrowserTreeItem(self.file)
-+ return ModuleBrowserTreeItem(self.file, self.flist)
-
- class ModuleBrowserTreeItem(TreeItem):
-
-- def __init__(self, file):
-+ def __init__(self, file, flist):
- self.file = file
-+ self.flist = flist
-
- def GetText(self):
- return os.path.basename(self.file)
-@@ -73,7 +74,8 @@
- def GetSubList(self):
- sublist = []
- for name in self.listclasses():
-- item = ClassBrowserTreeItem(name, self.classes, self.file)
-+ item = ClassBrowserTreeItem(name, self.classes, self.file,
-+ self.flist)
- sublist.append(item)
- return sublist
-
-@@ -82,7 +84,7 @@
- return
- if not os.path.exists(self.file):
- return
-- PyShell.flist.open(self.file)
-+ self.flist.open(self.file)
-
- def IsExpandable(self):
- return os.path.normcase(self.file[-3:]) == ".py"
-@@ -122,10 +124,11 @@
-
- class ClassBrowserTreeItem(TreeItem):
-
-- def __init__(self, name, classes, file):
-+ def __init__(self, name, classes, file, flist):
- self.name = name
- self.classes = classes
- self.file = file
-+ self.flist = flist
- try:
- self.cl = self.classes[self.name]
- except (IndexError, KeyError):
-@@ -163,7 +166,7 @@
- def OnDoubleClick(self):
- if not os.path.exists(self.file):
- return
-- edit = PyShell.flist.open(self.file)
-+ edit = self.flist.open(self.file)
- if hasattr(self.cl, 'lineno'):
- lineno = self.cl.lineno
- edit.gotoline(lineno)
-@@ -199,10 +202,11 @@
- def OnDoubleClick(self):
- if not os.path.exists(self.file):
- return
-- edit = PyShell.flist.open(self.file)
-+ edit = self.flist.open(self.file)
- edit.gotoline(self.cl.methods[self.name])
-
- def main():
-+ import PyShell
- try:
- file = __file__
- except NameError:
-Index: FileList.py
-===================================================================
---- FileList.py (revision 63995)
-+++ FileList.py (revision 65541)
-@@ -1,7 +1,15 @@
- import os
--from Tkinter import *
- import tkMessageBox
-
-+def _canonize(filename):
-+ if not os.path.isabs(filename):
-+ try:
-+ pwd = os.getcwd()
-+ except os.error:
-+ pass
-+ else:
-+ filename = os.path.join(pwd, filename)
-+ return os.path.normpath(filename)
-
- class FileList:
-
-@@ -16,7 +24,7 @@
-
- def open(self, filename, action=None):
- assert filename
-- filename = self.canonize(filename)
-+ filename = _canonize(filename)
- if os.path.isdir(filename):
- # This can happen when bad filename is passed on command line:
- tkMessageBox.showerror(
-@@ -29,9 +37,10 @@
- edit = self.dict[key]
- edit.top.wakeup()
- return edit
-+
- if action:
- # Don't create window, perform 'action', e.g. open in same window
-- return action(filename)
-+ return action(filename=filename)
- else:
- return self.EditorWindow(self, filename, key)
-
-@@ -62,20 +71,20 @@
- if not self.inversedict:
- self.root.quit()
-
-- def filename_changed_edit(self, edit):
-- edit.saved_change_hook()
-+ def filename_changed_edit(self, page, editwin):
-+ page.saved_change_hook(page.tab_initialized)
- try:
-- key = self.inversedict[edit]
-+ key = self.inversedict[editwin]
- except KeyError:
- print "Don't know this EditorWindow object. (rename)"
- return
-- filename = edit.io.filename
-+ filename = page.io.filename
- if not filename:
- if key:
- del self.dict[key]
-- self.inversedict[edit] = None
-+ self.inversedict[editwin] = None
- return
-- filename = self.canonize(filename)
-+ filename = _canonize(filename)
- newkey = os.path.normcase(filename)
- if newkey == key:
- return
-@@ -86,28 +95,19 @@
- "Name Conflict",
- "You now have multiple edit windows open for %r" % (filename,),
- master=self.root)
-- self.dict[newkey] = edit
-- self.inversedict[edit] = newkey
-+ self.dict[newkey] = editwin
-+ self.inversedict[editwin] = newkey
- if key:
- try:
- del self.dict[key]
- except KeyError:
- pass
-
-- def canonize(self, filename):
-- if not os.path.isabs(filename):
-- try:
-- pwd = os.getcwd()
-- except os.error:
-- pass
-- else:
-- filename = os.path.join(pwd, filename)
-- return os.path.normpath(filename)
-
--
- def _test():
-+ import sys
-+ from Tkinter import Tk
- from EditorWindow import fixwordbreaks
-- import sys
- root = Tk()
- fixwordbreaks(root)
- root.withdraw()
-Index: CallTips.py
-===================================================================
---- CallTips.py (revision 63995)
-+++ CallTips.py (revision 65541)
-@@ -22,12 +22,12 @@
- ])
- ]
-
-- def __init__(self, editwin=None):
-- if editwin is None: # subprocess and test
-- self.editwin = None
-+ def __init__(self, editpage=None):
-+ if editpage is None: # subprocess and test
-+ self.editpage = None
- return
-- self.editwin = editwin
-- self.text = editwin.text
-+ self.editpage = editpage
-+ self.text = editpage.text
- self.calltip = None
- self._make_calltip_window = self._make_tk_calltip_window
-
-@@ -66,7 +66,7 @@
- def open_calltip(self, evalfuncs):
- self._remove_calltip_window()
-
-- hp = HyperParser(self.editwin, "insert")
-+ hp = HyperParser(self.editpage, "insert")
- sur_paren = hp.get_surrounding_brackets('(')
- if not sur_paren:
- return
-@@ -95,7 +95,7 @@
-
- """
- try:
-- rpcclt = self.editwin.flist.pyshell.interp.rpcclt
-+ rpcclt = self.editpage.editwin.flist.pyshell.interp.rpcclt
- except:
- rpcclt = None
- if rpcclt:
-Index: CodeContext.py
-===================================================================
---- CodeContext.py (revision 63995)
-+++ CodeContext.py (revision 65541)
-@@ -23,7 +23,7 @@
- getspacesfirstword =\
- lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups()
-
--class CodeContext:
-+class CodeContext(object):
- menudefs = [('options', [('!Code Conte_xt', '<<toggle-code-context>>')])]
- context_depth = idleConf.GetOption("extensions", "CodeContext",
- "numlines", type="int", default=3)
-@@ -31,10 +31,10 @@
- "bgcolor", type="str", default="LightGray")
- fgcolor = idleConf.GetOption("extensions", "CodeContext",
- "fgcolor", type="str", default="Black")
-- def __init__(self, editwin):
-- self.editwin = editwin
-- self.text = editwin.text
-- self.textfont = self.text["font"]
-+
-+ def __init__(self, editpage):
-+ self.editpage = editpage
-+ self.editwin = editpage.editwin
- self.label = None
- # self.info is a list of (line number, indent level, line text, block
- # keyword) tuples providing the block structure associated with
-@@ -43,14 +43,11 @@
- # starts the toplevel 'block' of the module.
- self.info = [(0, -1, "", False)]
- self.topvisible = 1
-- visible = idleConf.GetOption("extensions", "CodeContext",
-- "visible", type="bool", default=False)
-+ visible = idleConf.GetOption("extensions", "CodeContext", "visible",
-+ type="bool", default=False)
- if visible:
- self.toggle_code_context_event()
- self.editwin.setvar('<<toggle-code-context>>', True)
-- # Start two update cycles, one for context lines, one for font changes.
-- self.text.after(UPDATEINTERVAL, self.timer_event)
-- self.text.after(FONTUPDATEINTERVAL, self.font_timer_event)
-
- def toggle_code_context_event(self, event=None):
- if not self.label:
-@@ -59,33 +56,27 @@
- #
- # All values are passed through int(str(<value>)), since some
- # values may be pixel objects, which can't simply be added to ints.
-- widgets = self.editwin.text, self.editwin.text_frame
-- # Calculate the required vertical padding
-- padx = 0
-- for widget in widgets:
-- padx += int(str( widget.pack_info()['padx'] ))
-- padx += int(str( widget.cget('padx') ))
-- # Calculate the required border width
-- border = 0
-- for widget in widgets:
-- border += int(str( widget.cget('border') ))
-+
-+ # Calculate the required horizontal padding
-+ padx = int(str(self.editwin.text_notebook.pack_info()['padx']))
-+
- self.label = Tkinter.Label(self.editwin.top,
- text="\n" * (self.context_depth - 1),
- anchor=W, justify=LEFT,
- font=self.textfont,
- bg=self.bgcolor, fg=self.fgcolor,
- width=1, #don't request more than we get
-- padx=padx, border=border,
-+ padx=padx,
- relief=SUNKEN)
-- # Pack the label widget before and above the text_frame widget,
-- # thus ensuring that it will appear directly above text_frame
-+ # Pack the label widget before and above the text_notebook widget,
-+ # thus ensuring that it will appear directly above text_notebook
- self.label.pack(side=TOP, fill=X, expand=False,
-- before=self.editwin.text_frame)
-+ before=self.editwin.text_notebook)
- else:
- self.label.destroy()
- self.label = None
- idleConf.SetOption("extensions", "CodeContext", "visible",
-- str(self.label is not None))
-+ str(self.label is not None))
- idleConf.SaveUserCfgFiles()
-
- def get_line_info(self, linenum):
-@@ -132,15 +123,12 @@
- return lines, lastindent
-
- def update_code_context(self):
-- """Update context information and lines visible in the context pane.
--
-- """
-+ """Update context information and lines visible in the context pane."""
- new_topvisible = int(self.text.index("@0,0").split('.')[0])
- if self.topvisible == new_topvisible: # haven't scrolled
- return
- if self.topvisible < new_topvisible: # scroll down
-- lines, lastindent = self.get_context(new_topvisible,
-- self.topvisible)
-+ lines, lastindent = self.get_context(new_topvisible, self.topvisible)
- # retain only context info applicable to the region
- # between topvisible and new_topvisible:
- while self.info[-1][1] >= lastindent:
-@@ -153,8 +141,7 @@
- stopindent = self.info[-1][1]
- del self.info[-1]
- lines, lastindent = self.get_context(new_topvisible,
-- self.info[-1][0]+1,
-- stopindent)
-+ self.info[-1][0] + 1, stopindent)
- self.info.extend(lines)
- self.topvisible = new_topvisible
- # empty lines in context pane:
-@@ -174,3 +161,18 @@
- self.textfont = newtextfont
- self.label["font"] = self.textfont
- self.text.after(FONTUPDATEINTERVAL, self.font_timer_event)
-+
-+ # Private methods
-+
-+ def _get_editpage(self):
-+ return self._editpage
-+
-+ def _set_editpage(self, page):
-+ self._editpage = page
-+ self.text = page.text
-+ self.textfont = self.text["font"]
-+ # Start two update cycles, one for context lines, one for font changes.
-+ self.text.after(UPDATEINTERVAL, self.timer_event)
-+ self.text.after(FONTUPDATEINTERVAL, self.font_timer_event)
-+
-+ editpage = property(_get_editpage, _set_editpage)
-Index: textView.py
-===================================================================
---- textView.py (revision 63995)
-+++ textView.py (revision 65541)
-@@ -1,10 +1,16 @@
--"""Simple text browser for IDLE
-+"""Simple text browser for IDLE"""
-
--"""
--
--from Tkinter import *
- import tkMessageBox
-+from Tkinter import Toplevel, Frame, Button, Scrollbar, Text
-+from Tkconstants import DISABLED, SUNKEN, VERTICAL, WORD, RIGHT, Y, TOP, \
-+ LEFT, BOTH, BOTTOM
-
-+from configHandler import idleConf
-+
-+TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
-+if TTK:
-+ from ttk import Frame, Button, Scrollbar
-+
- class TextViewer(Toplevel):
- """A simple text viewer dialog for IDLE
-
-@@ -40,19 +46,22 @@
- frameText = Frame(self, relief=SUNKEN, height=700)
- frameButtons = Frame(self)
- self.buttonOk = Button(frameButtons, text='Close',
-- command=self.Ok, takefocus=FALSE)
-+ command=self.Ok, takefocus=False)
- self.scrollbarView = Scrollbar(frameText, orient=VERTICAL,
-- takefocus=FALSE, highlightthickness=0)
-- self.textView = Text(frameText, wrap=WORD, highlightthickness=0,
-- fg=self.fg, bg=self.bg)
-+ takefocus=False)
-+ self.textView = Text(frameText, wrap=WORD, fg=self.fg, bg=self.bg,
-+ highlightthickness=0)
- self.scrollbarView.config(command=self.textView.yview)
- self.textView.config(yscrollcommand=self.scrollbarView.set)
- self.buttonOk.pack()
- self.scrollbarView.pack(side=RIGHT,fill=Y)
-- self.textView.pack(side=LEFT,expand=TRUE,fill=BOTH)
-- frameButtons.pack(side=BOTTOM,fill=X)
-- frameText.pack(side=TOP,expand=TRUE,fill=BOTH)
-+ self.textView.pack(side=LEFT,expand=True,fill=BOTH)
-+ 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()
-
-@@ -68,7 +77,6 @@
- else:
- textFile = open(filename, 'r')
- except IOError:
-- import tkMessageBox
- tkMessageBox.showerror(title='File Load Error',
- message='Unable to load file %r .' % filename,
- parent=parent)
-@@ -77,6 +85,7 @@
-
-
- if __name__ == '__main__':
-+ from Tkinter import Tk
- #test the dialog
- root=Tk()
- root.title('textView test')
-Index: SearchDialogBase.py
-===================================================================
---- SearchDialogBase.py (revision 63995)
-+++ SearchDialogBase.py (revision 65541)
-@@ -1,35 +1,42 @@
--from Tkinter import *
-+from Tkinter import Toplevel, Frame, Label, Entry, Button, Checkbutton, \
-+ Radiobutton
-
-+from configHandler import idleConf
-+
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
-+ from ttk import Frame, Label, Entry, Button, Checkbutton, Radiobutton
-+
- class SearchDialogBase:
-
- title = "Search Dialog"
- icon = "Search"
- needwrapbutton = 1
-+ bottom_btns = None
-
- def __init__(self, root, engine):
- self.root = root
- self.engine = engine
-- self.top = None
-+ self.ttop = None
-
- def open(self, text, searchphrase=None):
- self.text = text
-- if not self.top:
-+ if not self.ttop:
- self.create_widgets()
- else:
-- self.top.deiconify()
-- self.top.tkraise()
-+ self.ttop.deiconify()
-+ self.ttop.tkraise()
- if searchphrase:
-- self.ent.delete(0,"end")
-- self.ent.insert("end",searchphrase)
-+ self.ent.delete(0, "end")
-+ self.ent.insert("end", searchphrase)
- self.ent.focus_set()
- self.ent.selection_range(0, "end")
- self.ent.icursor(0)
-- self.top.grab_set()
-+ self.ttop.grab_set()
-
- def close(self, event=None):
-- if self.top:
-- self.top.grab_release()
-- self.top.withdraw()
-+ if self.ttop:
-+ self.ttop.grab_release()
-+ self.ttop.withdraw()
-
- def create_widgets(self):
- top = Toplevel(self.root)
-@@ -38,103 +45,96 @@
- top.protocol("WM_DELETE_WINDOW", self.close)
- top.wm_title(self.title)
- top.wm_iconname(self.icon)
-- self.top = top
-+ top.resizable(height=False, width=False)
-+ self.ttop = top
-+ self.top = Frame(top)
-
- self.row = 0
-- self.top.grid_columnconfigure(0, pad=2, weight=0)
-- self.top.grid_columnconfigure(1, pad=2, minsize=100, weight=100)
-+ self.top.grid(sticky='news')
-
- self.create_entries()
- self.create_option_buttons()
- self.create_other_buttons()
-- return self.create_command_buttons()
-+ self.create_command_buttons()
-
-+
- def make_entry(self, label, var):
- l = Label(self.top, text=label)
-- l.grid(row=self.row, column=0, sticky="nw")
-+ l.grid(row=self.row, column=0, sticky="ne", padx=6, pady=6)
- e = Entry(self.top, textvariable=var, exportselection=0)
-- e.grid(row=self.row, column=1, sticky="nwe")
-+ e.grid(row=self.row, column=1, sticky="nwe", padx=6, pady=6)
- self.row = self.row + 1
- return e
-
- def make_frame(self,labeltext=None):
- if labeltext:
- l = Label(self.top, text=labeltext)
-- l.grid(row=self.row, column=0, sticky="nw")
-+ l.grid(row=self.row, column=0, sticky="ne", padx=6, pady=6)
- f = Frame(self.top)
-- f.grid(row=self.row, column=1, columnspan=1, sticky="nwe")
-+ f.grid(row=self.row, column=1, columnspan=1, sticky="nwe",
-+ padx=6, pady=6 if labeltext else 0)
- self.row = self.row + 1
- return f
-
-- def make_button(self, label, command, isdef=0):
-- b = Button(self.buttonframe,
-- text=label, command=command,
-- default=isdef and "active" or "normal")
-- cols,rows=self.buttonframe.grid_size()
-- b.grid(pady=1,row=rows,column=0,sticky="ew")
-- self.buttonframe.grid(rowspan=rows+1)
-- return b
--
- def create_entries(self):
-- self.ent = self.make_entry("Find:", self.engine.patvar)
-+ self.ent = self.make_entry("Find", self.engine.patvar)
-
- def create_option_buttons(self):
- f = self.make_frame("Options")
-
-- btn = Checkbutton(f, anchor="w",
-- variable=self.engine.revar,
-- text="Regular expression")
-+ btn = Checkbutton(f, variable=self.engine.revar,
-+ text="Regular expression")
- btn.pack(side="left", fill="both")
- if self.engine.isre():
-- btn.select()
-+ btn.invoke()
-
-- btn = Checkbutton(f, anchor="w",
-- variable=self.engine.casevar,
-- text="Match case")
-+ btn = Checkbutton(f, variable=self.engine.casevar, text="Match case")
- btn.pack(side="left", fill="both")
- if self.engine.iscase():
-- btn.select()
-+ btn.invoke()
-
-- btn = Checkbutton(f, anchor="w",
-- variable=self.engine.wordvar,
-- text="Whole word")
-+ btn = Checkbutton(f, variable=self.engine.wordvar, text="Whole word")
- btn.pack(side="left", fill="both")
- if self.engine.isword():
-- btn.select()
-+ btn.invoke()
-
- if self.needwrapbutton:
-- btn = Checkbutton(f, anchor="w",
-- variable=self.engine.wrapvar,
-- text="Wrap around")
-+ btn = Checkbutton(f, variable=self.engine.wrapvar,
-+ text="Wrap around")
- btn.pack(side="left", fill="both")
- if self.engine.iswrap():
-- btn.select()
-+ btn.invoke()
-
- def create_other_buttons(self):
- f = self.make_frame("Direction")
-
-- #lbl = Label(f, text="Direction: ")
-- #lbl.pack(side="left")
--
-- btn = Radiobutton(f, anchor="w",
-- variable=self.engine.backvar, value=1,
-- text="Up")
-- btn.pack(side="left", fill="both")
-+ btn = Radiobutton(f, variable=self.engine.backvar, value=1, text="Up")
-+ btn.pack(side="left")
- if self.engine.isback():
-- btn.select()
-+ btn.invoke()
-
-- btn = Radiobutton(f, anchor="w",
-- variable=self.engine.backvar, value=0,
-- text="Down")
-- btn.pack(side="left", fill="both")
-+ btn = Radiobutton(f, variable=self.engine.backvar, value=0, text="Down")
-+ btn.pack(side="left")
- if not self.engine.isback():
-- btn.select()
-+ btn.invoke()
-
- def create_command_buttons(self):
-- #
-- # place button frame on the right
-- f = self.buttonframe = Frame(self.top)
-- f.grid(row=0,column=2,padx=2,pady=2,ipadx=2,ipady=2)
-+ self.bottom_btns = self.bottom_btns or []
-+ f = Frame(self.top)
-+ f.grid(row=self.row, column=0, columnspan=len(self.bottom_btns) + 1,
-+ pady=6)
-
-- b = self.make_button("close", self.close)
-- b.lower()
-+ column = 0
-+ b = Button(f, text="Close", command=self.close)
-+ b.grid(row=self.row, column=column, padx=6, pady=6)
-+ column += 1
-+
-+ btns = {}
-+ for tbtn in self.bottom_btns:
-+ opts = {'text': tbtn[0], 'command': getattr(self, tbtn[1])}
-+ if len(tbtn) == 3:
-+ opts['default'] = tbtn[2] and 'active' or 'normal'
-+
-+ btns[opts['text']] = Button(f, **opts).grid(row=self.row, padx=6,
-+ pady=6, column=column)
-+ column += 1
-Index: CallTipWindow.py
-===================================================================
---- CallTipWindow.py (revision 63995)
-+++ CallTipWindow.py (revision 65541)
-@@ -4,8 +4,14 @@
- Used by the CallTips IDLE extension.
-
- """
--from Tkinter import *
-+from Tkinter import Toplevel, Label, TclError
-+from Tkconstants import SOLID, LEFT
-
-+from configHandler import idleConf
-+
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
-+ from ttk import Label
-+
- HIDE_VIRTUAL_EVENT_NAME = "<<calltipwindow-hide>>"
- HIDE_SEQUENCES = ("<Key-Escape>", "<FocusOut>")
- CHECKHIDE_VIRTUAL_EVENT_NAME = "<<calltipwindow-checkhide>>"
-@@ -142,6 +148,8 @@
- #
- class container: # Conceptually an editor_window
- def __init__(self):
-+ from Tkinter import Tk, Text
-+ from Tkconstants import BOTH
- root = Tk()
- text = self.text = Text(root)
- text.pack(side=LEFT, fill=BOTH, expand=1)
-@@ -163,6 +171,8 @@
- def calltip_hide(self, event):
- self.calltip.hidetip()
-
-+# XXX Bugged test
-+
- def main():
- # Test code
- c=container()
-Index: SearchDialog.py
-===================================================================
---- SearchDialog.py (revision 63995)
-+++ SearchDialog.py (revision 65541)
-@@ -1,8 +1,8 @@
--from Tkinter import *
-+from Tkinter import TclError
-+
- import SearchEngine
- from SearchDialogBase import SearchDialogBase
-
--
- def _setup(text):
- root = text._root()
- engine = SearchEngine.get(root)
-@@ -12,7 +12,7 @@
-
- def find(text):
- pat = text.get("sel.first", "sel.last")
-- return _setup(text).open(text,pat)
-+ return _setup(text).open(text, pat)
-
- def find_again(text):
- return _setup(text).find_again(text)
-@@ -21,10 +21,10 @@
- return _setup(text).find_selection(text)
-
- class SearchDialog(SearchDialogBase):
-+ bottom_btns = [("Find", 'default_command', 1)]
-
- def create_widgets(self):
-- f = SearchDialogBase.create_widgets(self)
-- self.make_button("Find", self.default_command, 1)
-+ SearchDialogBase.create_widgets(self)
-
- def default_command(self, event=None):
- if not self.engine.getprog():
-Index: idlever.py
-===================================================================
---- idlever.py (revision 63995)
-+++ idlever.py (revision 65541)
-@@ -1 +1 @@
--IDLE_VERSION = "2.6a3"
-+IDLE_VERSION = "2.6a3-gpolo"
-Index: tabbedpages_old.py
-===================================================================
---- tabbedpages_old.py (revision 0)
-+++ tabbedpages_old.py (revision 65541)
-@@ -0,0 +1,546 @@
-+"""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 Frame, Radiobutton
-+from Tkconstants import BOTH, TOP, X, RAISED, NSEW, FLAT, LEFT
-+
-+from tabbedpages import InvalidNameError, AlreadyExistsError
-+
-+
-+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" % tab_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" % tab_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 update_tabtitle(self, tab, newtitle):
-+ """Update tab title to newtitle."""
-+ currpage = self.pages[tab.title]
-+ old = tab.title
-+
-+ # resolve title duplicate
-+ if newtitle in self.pages:
-+ count = 1
-+ temptitle = newtitle
-+ while temptitle in self.pages:
-+ temptitle = "%s #%d" % (newtitle, count)
-+ count += 1
-+ newtitle = temptitle
-+
-+ tab.title = newtitle
-+ # now update 1 million places.. yeh..
-+ self.pages[newtitle] = self.pages.pop(old)
-+ self._pages_order[self._pages_order.index(old)] = newtitle
-+ self._tab_set._tab_names[self._tab_set._tab_names.index(old)] = newtitle
-+ self._tab_set._tabs[newtitle] = self._tab_set._tabs.pop(old)
-+ self._tab_set._tabs[newtitle].button['text'] = newtitle
-+ if self._tab_set._selected_tab == old:
-+ self._tab_set._selected_tab = newtitle
-+ if self._current_page == old:
-+ self._current_page = newtitle
-+ if self._default_page == old:
-+ self._default_page = newtitle
-+
-+ 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)
-+
-+ return self.pages[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)
-+ self.event_generate('<<NotebookTabChanged>>') # conform to ttk.Notebook
-+
-+ def last_page(self):
-+ return self.pages[self._pages_order[-1]]
-+
-+ # Some methods to make this Notebook compatible with the ttk Notebook
-+
-+ def select(self, page_id=None):
-+ """Return the name of the currently selected page, otherwise
-+ selects page_id.
-+
-+ page_id may be an integer or a page name."""
-+ if page_id is None:
-+ return self._current_page
-+ elif isinstance(page_id, int):
-+ self.change_page(self._pages_order[page_id])
-+ elif isinstance(page_id, str):
-+ self.change_page(page_id)
-+
-+ def index(self, page_name):
-+ """Return the index of page_name."""
-+ return self._pages_order.index(page_name)
-+
-+ def tabs(self):
-+ """Return a list of page names."""
-+ return self._pages_order
-+
-+if __name__ == '__main__':
-+ from Tkinter import Tk, Label, Entry, Button
-+ # 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: utils.py
-===================================================================
---- utils.py (revision 0)
-+++ utils.py (revision 65541)
-@@ -0,0 +1,4 @@
-+def callback(func, *myargs):
-+ def w(*args):
-+ return func(*(args + myargs))
-+ return w
-Index: TreeWidget.py
-===================================================================
---- TreeWidget.py (revision 63995)
-+++ TreeWidget.py (revision 65541)
-@@ -15,12 +15,16 @@
- # - optimize tree redraw after expand of subnode
-
- import os
--from Tkinter import *
--import imp
-+from Tkinter import Tk, Label, Entry, Frame, Canvas, Scrollbar, PhotoImage
-+from Tkconstants import ALL, END
-
- import ZoomHeight
- from configHandler import idleConf
-
-+TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
-+if TTK:
-+ from ttk import Label, Entry, Frame, Scrollbar
-+
- ICONDIR = "Icons"
-
- # Look for Icons subdirectory in the same directory as this module
-@@ -248,7 +252,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)
-+ 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,7 +457,10 @@
-
- # Testing functions
-
-+# XXX Can't run these tests
-+
- def test():
-+ from Tkinter import Toplevel
- import PyShell
- root = Toplevel(PyShell.root)
- root.configure(bd=0, bg="yellow")
-Index: run.py
-===================================================================
---- run.py (revision 63995)
-+++ run.py (revision 65541)
-@@ -24,11 +24,13 @@
- except ImportError:
- pass
- else:
-- def idle_formatwarning_subproc(message, category, filename, lineno):
-+ def idle_formatwarning_subproc(message, category, filename, lineno,
-+ line=None):
- """Format warnings the IDLE way"""
- s = "\nWarning (from warnings module):\n"
- s += ' File \"%s\", line %s\n' % (filename, lineno)
-- line = linecache.getline(filename, lineno).strip()
-+ if line is None:
-+ line = linecache.getline(filename, lineno).strip()
- if line:
- s += " %s\n" % line
- s += "%s: %s\n" % (category.__name__, message)
-Index: AutoExpand.py
-===================================================================
---- AutoExpand.py (revision 63995)
-+++ AutoExpand.py (revision 65541)
-@@ -15,8 +15,8 @@
-
- wordchars = string.ascii_letters + string.digits + "_"
-
-- def __init__(self, editwin):
-- self.text = editwin.text
-+ def __init__(self, editpage):
-+ self.text = editpage.text
- self.state = None
-
- def expand_word_event(self, event):
-Index: Percolator.py
-===================================================================
---- Percolator.py (revision 63995)
-+++ Percolator.py (revision 65541)
-@@ -1,5 +1,5 @@
-+from Delegator import Delegator
- from WidgetRedirector import WidgetRedirector
--from Delegator import Delegator
-
- class Percolator:
-
-@@ -81,5 +81,5 @@
- root.mainloop()
-
- if __name__ == "__main__":
-- from Tkinter import *
-+ from Tkinter import Tk, Text
- main()
-Index: tabbedpages_new.py
-===================================================================
---- tabbedpages_new.py (revision 0)
-+++ tabbedpages_new.py (revision 65541)
-@@ -0,0 +1,116 @@
-+"""Classes exported:
-+
-+TabbedPageSet -- A custom ttk.Notebook used by IDLE.
-+"""
-+from ttk import Frame, Notebook
-+
-+from tabbedpages import InvalidNameError, AlreadyExistsError
-+
-+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 = {}
-+ page_names = page_names or ()
-+ for name in page_names:
-+ self.add_page(name)
-+
-+ def update_tabtitle(self, tab, newtitle):
-+ """Update tab title to newtitle."""
-+ currpage = self.pages[tab.title].frame
-+ old = tab.title
-+
-+ # resolve title duplicate
-+ if newtitle in self.pages and currpage != self.pages[newtitle].frame:
-+ # newtitle is already present, and the current tab is not the
-+ # one who owns it
-+ count = 1
-+ temptitle = newtitle
-+ while temptitle in self.pages:
-+ if currpage == self.pages[temptitle].frame:
-+ break
-+ temptitle = "%s #%d" % (newtitle, count)
-+ count += 1
-+ newtitle = temptitle
-+
-+ tab.title = newtitle
-+ self.pages[newtitle] = self.pages.pop(old)
-+ self.tab(currpage, text=newtitle)
-+
-+ 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>')
-+
-+ return fpage
-+
-+ def remove_page(self, page_name):
-+ """Remove page_name from the notebook."""
-+ 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>')
-+
-+ def last_page(self):
-+ """Return the last page in the notebook."""
-+ return self.pages[self.tab(self.index('end') - 1)['text']]
-+
-+if __name__ == '__main__':
-+ from Tkinter import Tk
-+ from Tkconstants import TOP, BOTH
-+ from ttk import Label, Entry, Button, Style
-+ # 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: dynOptionMenuWidget.py
-===================================================================
---- dynOptionMenuWidget.py (revision 63995)
-+++ dynOptionMenuWidget.py (revision 65541)
-@@ -2,34 +2,41 @@
- OptionMenu widget modified to allow dynamic menu reconfiguration
- and setting of highlightthickness
- """
--from Tkinter import OptionMenu
-+from Tkinter import OptionMenu, Menu
- from Tkinter import _setit
- import copy
-
-+from configHandler import idleConf
-+TTK = idleConf.GetOption('main', 'General', 'use-ttk', type='int')
-+if TTK:
-+ from ttk import *
-+
- class DynOptionMenu(OptionMenu):
-- """
-- unlike OptionMenu, our kwargs can include highlightthickness
-- """
-+ """Unlike OptionMenu, our kwargs can include highlightthickness"""
- def __init__(self, master, variable, value, *values, **kwargs):
- #get a copy of kwargs before OptionMenu.__init__ munges them
- kwargsCopy=copy.copy(kwargs)
- if 'highlightthickness' in kwargs.keys():
- del(kwargs['highlightthickness'])
-+ self.command=kwargs.get('command')
-+ self.variable=variable
-+
- OptionMenu.__init__(self, master, variable, value, *values, **kwargs)
- self.config(highlightthickness=kwargsCopy.get('highlightthickness'))
-- #self.menu=self['menu']
-- self.variable=variable
-- self.command=kwargs.get('command')
-
-- def SetMenu(self,valueList,value=None):
-+ def SetMenu(self, valueList, value=None):
- """
- clear and reload the menu with a new set of options.
- valueList - list of new options
- value - initial value to set the optionmenu's menubutton to
- """
-- self['menu'].delete(0,'end')
-- for item in valueList:
-- self['menu'].add_command(label=item,
-+ if TTK:
-+ self.set_menu(value, *valueList)
-+ else:
-+ menu = self['menu']
-+ menu.delete(0,'end')
-+ for item in valueList:
-+ menu.add_command(label=item,
- command=_setit(self.variable,item,self.command))
-- if value:
-- self.variable.set(value)
-+ if value:
-+ self.variable.set(value)
-Index: extend.txt
-===================================================================
---- extend.txt (revision 63995)
-+++ extend.txt (revision 65541)
-@@ -81,3 +81,10 @@
-
- For further information on binding refer to the Tkinter Resources web page at
- python.org and to the Tk Command "bind" man page.
-+
-+
-+Note
-+----
-+
-+Given that this branch is using tabbed pages, don't expect the previous
-+description to be correct related to the code present here.
-Index: MultiStatusBar.py
-===================================================================
---- MultiStatusBar.py (revision 63995)
-+++ MultiStatusBar.py (revision 65541)
-@@ -1,5 +1,11 @@
--from Tkinter import *
-+from Tkinter import Tk, Frame, Label
-+from Tkconstants import LEFT, SUNKEN, W
-
-+from configHandler import idleConf
-+
-+if idleConf.GetOption('main', 'General', 'use-ttk', type='int'):
-+ from ttk import Frame, Label
-+
- class MultiStatusBar(Frame):
-
- def __init__(self, master=None, **kw):
-@@ -10,7 +16,7 @@
-
- def set_label(self, name, text='', side=LEFT):
- if not self.labels.has_key(name):
-- label = Label(self, bd=1, relief=SUNKEN, anchor=W)
-+ label = Label(self, relief=SUNKEN, anchor=W)
- label.pack(side=side)
- self.labels[name] = label
- else:
-@@ -18,6 +24,8 @@
- label.config(text=text)
-
- def _test():
-+ from Tkinter import Text
-+ from Tkconstants import TOP, BOTTOM, X
- b = Frame()
- c = Text(b)
- c.pack(side=TOP)
-
-Property changes on: .
-___________________________________________________________________
-Name: svnmerge-integrated
- + /python/trunk/Lib/idlelib:1-63994
-
More information about the Python-checkins
mailing list