[Python-checkins] r65143 - in sandbox/trunk/ttk-gsoc/src/idlelib: EditorWindow.py IOBinding.py PyShell.py editorpage.py
guilherme.polo
python-checkins at python.org
Sat Jul 19 16:33:45 CEST 2008
Author: guilherme.polo
Date: Sat Jul 19 16:33:44 2008
New Revision: 65143
Log:
Continuing the move to tabs support. New marks added to remember what to do next.
Modified:
sandbox/trunk/ttk-gsoc/src/idlelib/EditorWindow.py
sandbox/trunk/ttk-gsoc/src/idlelib/IOBinding.py
sandbox/trunk/ttk-gsoc/src/idlelib/PyShell.py
sandbox/trunk/ttk-gsoc/src/idlelib/editorpage.py
Modified: sandbox/trunk/ttk-gsoc/src/idlelib/EditorWindow.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/idlelib/EditorWindow.py (original)
+++ sandbox/trunk/ttk-gsoc/src/idlelib/EditorWindow.py Sat Jul 19 16:33:44 2008
@@ -14,12 +14,9 @@
import WindowList
import PathBrowser
import ClassBrowser
-from editorpage import EditorPage, classifyws
+from editorpage import EditorPage, classifyws, filename_to_unicode
from tabbedpages import get_tabbedpage
from configHandler import idleConf
-from IOBinding import IOBinding, filesystemencoding, encoding
-from Percolator import Percolator
-from UndoDelegator import UndoDelegator
from MultiStatusBar import MultiStatusBar
TabbedPageSet = get_tabbedpage()
@@ -49,7 +46,9 @@
return file, filename, descr
class EditorWindow(object):
- from ColorDelegator import ColorDelegator
+ from ColorDelegator import ColorDelegator # overridden by PyShell
+ from UndoDelegator import UndoDelegator # overridden by PyShell
+
help_url = None
rmenu = None
rmenu_specs = [
@@ -126,10 +125,15 @@
# create a Notebook where the text pages for this EditorWindow will
# reside
self.text_notebook = TabbedPageSet(top)
- self.text = text = self.new_tab()
+ self.text_notebook.bind('<<NotebookTabChanged>>',
+ self.update_controls)
+ self.new_tab(filename=filename)
+ self.text = text = self.current_page().text
self.top.focused_widget = self.text
self.text_notebook.pack(fill=BOTH, expand=True)
+ self.io = self.current_page().io
+
# The following "width" attribute is used by PyShell, so keep it here
self.width = idleConf.GetOption('main', 'EditorPage', 'width')
@@ -138,6 +142,7 @@
self.top.protocol("WM_DELETE_WINDOW", self.close)
self.top.bind("<<close-window>>", self.close_event)
+ # XXX This need to be done per tab too
if flist:
flist.inversedict[self] = key
if key:
@@ -147,7 +152,8 @@
text.bind("<<open-class-browser>>", self.open_class_browser)
text.bind("<<open-path-browser>>", self.open_path_browser)
- self.set_status_bar()
+ self.create_statusbar()
+ 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
@@ -186,18 +192,6 @@
# Making the initial values larger slows things down more often.
self.num_context_lines = 50, 500, 5000000
- self.per = per = Percolator(text)
-
- self.undo = undo = 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 = 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',
@@ -205,15 +199,6 @@
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()
@@ -234,27 +219,14 @@
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
- else:
- try:
- return filename.decode(filesystemencoding)
- except UnicodeDecodeError:
- # XXX
- try:
- return filename.decode(encoding)
- except UnicodeDecodeError:
- # byte-to-byte conversion
- return filename.decode('iso8859-1')
-
def new_callback(self, event):
- dirname, basename = self.io.defaultfilename()
- self.flist.new(dirname)
+ # XXX
+ current_page = self.current_page()
+ dirname, basename = current_page.io.defaultfilename()
+ current_page.flist.new(dirname)
return "break"
- def new_tab(self, event=None):
+ def new_tab(self, event=None, filename=None):
"""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)
@@ -265,8 +237,8 @@
parent = page.frame
vbar = Scrollbar(parent, name='vbar')
- page.editpage = EditorPage(parent, self, name='text', padx=5,
- wrap='none')
+ page.editpage = EditorPage(parent, self, filename=filename, name='text',
+ padx=5, wrap='none')
text = page.editpage.text
vbar['command'] = text.yview
@@ -283,9 +255,13 @@
self.apply_bindings()
- return text
+ return "break"
+
+ def update_controls(self, event):
+ self.io = self.current_page().io
+ self.set_line_and_column()
- def set_status_bar(self):
+ def create_statusbar(self):
self.status_bar = MultiStatusBar(self.top)
if macosxSupport.runningAsOSXApp():
# Insert some padding to avoid obscuring some of the statusbar
@@ -294,13 +270,10 @@
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
+ line, column = self.current_page().text.index(INSERT).split('.')
self.status_bar.set_label('column', 'Col: %s' % column)
self.status_bar.set_label('line', 'Ln: %s' % line)
@@ -331,7 +304,7 @@
menu.delete(self.wmenu_end+1, end)
WindowList.add_windows_to_menu(menu)
- def open_module(self, event=None):
+ def open_module(self, event=None): # XXX depends on self.text
# XXX Shouldn't this be in IOBinding or in FileList?
try:
name = self.text.get("sel.first", "sel.last")
@@ -360,11 +333,11 @@
if f:
f.close()
if self.flist:
- self.flist.open(file)
+ self.flist.open(file) # XXX change this to create a new tab instead
else:
self.io.loadfile(file)
- def open_class_browser(self, event=None):
+ def open_class_browser(self, event=None): # XXX depends on self.text
filename = self.io.filename
if not filename:
tkMessageBox.showerror(
@@ -434,49 +407,13 @@
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 _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):
+ def ResetFont(self): # XXX depends on self.text
"Update the text widgets' font if it is changed"
# Called from configDialog.py
fontWeight = 'normal'
@@ -486,7 +423,7 @@
idleConf.GetOption('main', 'EditorPage', 'font-size'),
fontWeight))
- def RemoveKeybindings(self):
+ def RemoveKeybindings(self): # XXX depends on self.text
"Remove the keybindings before they are changed."
# Called from configDialog.py
Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet()
@@ -599,7 +536,7 @@
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,
@@ -610,43 +547,8 @@
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()
-
- 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 "")
+ return self.current_page().undo.get_saved() # XXX Pretty wrong
def get_geometry(self):
"Return (width, height, x, y)"
@@ -673,21 +575,17 @@
self._close()
return reply
- def _close(self):
+ def _close(self): # XXX There should be one like this per EditorPage
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.unload_extensions() # XXX maybe this should be done per tab
self.text = None
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
@@ -714,7 +612,7 @@
def get_standard_extension_names(self):
return idleConf.GetExtensions(editor_only=True)
- def load_extension(self, name):
+ def load_extension(self, name): # XXX depends on self.text
try:
mod = __import__(name, globals(), locals(), [])
except ImportError:
@@ -749,7 +647,7 @@
if keylist:
text.event_add(event, *keylist)
- def fill_menus(self, menudefs=None, keydefs=None):
+ def fill_menus(self, menudefs=None, keydefs=None):# XXX depends on self.text
"""Add appropriate entries to the menus and submenus
Menus that are absent or None in self.menudict are ignored.
@@ -801,7 +699,7 @@
else:
raise NameError, name
- def get_var_obj(self, name, vartype=None):
+ def get_var_obj(self, name, vartype=None): # XXX depends on self.text
var = self.tkinter_vars.get(name)
if not var and vartype:
# create a Tkinter variable object with self.text as master:
@@ -814,12 +712,12 @@
# 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"],
@@ -845,7 +743,7 @@
# 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):
+ 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)
Modified: sandbox/trunk/ttk-gsoc/src/idlelib/IOBinding.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/idlelib/IOBinding.py (original)
+++ sandbox/trunk/ttk-gsoc/src/idlelib/IOBinding.py Sat Jul 19 16:33:44 2008
@@ -145,10 +145,14 @@
class IOBinding:
+ # XXX will need to change this too
- def __init__(self, editwin):
- self.editwin = editwin
- self.text = editwin.text
+ #def __init__(self, editwin):
+ def __init__(self, editpage):
+ #self.editwin = editwin
+ #self.text = editwin.text
+ self.editpage = editpage
+ 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>>",
@@ -166,18 +170,22 @@
self.text.unbind("<<save-copy-of-window-as-file>>", self.__id_savecopy)
self.text.unbind("<<print-window>>", self.__id_print)
# Break cycles
- self.editwin = None
+ #self.editwin = None
+ self.editpage = None
self.text = None
self.filename_change_hook = None
def get_saved(self):
- return self.editwin.get_saved()
+ #return self.editwin.get_saved()
+ return self.editpage.get_saved()
def set_saved(self, flag):
- self.editwin.set_saved(flag)
+ #self.editwin.set_saved(flag)
+ self.editpage.set_saved(flag)
def reset_undo(self):
- self.editwin.reset_undo()
+ #self.editwin.reset_undo()
+ self.editpage.reset_undo()
filename_change_hook = None
@@ -357,7 +365,8 @@
self.set_filename(filename)
self.set_saved(1)
try:
- self.editwin.store_file_breaks()
+ #self.editwin.store_file_breaks()
+ self.editpage.editwin.store_file_breaks()
except AttributeError:
pass
self.text.focus_set()
@@ -447,7 +456,8 @@
enc = "utf-8"
if not ask_user:
return chars
- dialog = EncodingMessage(self.editwin.top, enc)
+ #dialog = EncodingMessage(self.editwin.top, enc)
+ dialog = EncodingMessage(self.editpage.editwin.top, enc)
dialog.go()
if dialog.num == 1:
# User asked us to edit the file
@@ -562,7 +572,8 @@
def updaterecentfileslist(self,filename):
"Update recent file list on all editor windows"
- self.editwin.update_recent_files_list(filename)
+ #self.editwin.update_recent_files_list(filename)
+ self.editpage.editwin.update_recent_files_list(filename)
def test():
from Tkinter import Tk, Text
Modified: sandbox/trunk/ttk-gsoc/src/idlelib/PyShell.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/idlelib/PyShell.py (original)
+++ sandbox/trunk/ttk-gsoc/src/idlelib/PyShell.py Sat Jul 19 16:33:44 2008
@@ -111,6 +111,7 @@
def __init__(self, *args):
self.breakpoints = []
EditorWindow.__init__(self, *args)
+ # XXX more things to be done after page is created
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)
@@ -823,13 +824,13 @@
#
OutputWindow.__init__(self, flist, None, None)
#
-## 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
+ # XXX needs to be done after a page is created
text.configure(wrap="char")
text.bind("<<newline-and-indent>>", self.enter_callback)
text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
@@ -1217,9 +1218,11 @@
except:
s = ""
self.console.write(s)
- self.text.mark_set("insert", "end-1c")
+
+ curr_page = self.current_page()
+ 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")
@@ -1417,7 +1420,7 @@
if enable_edit:
if not (cmd or script):
for filename in args:
- flist.open(filename)
+ flist.open(filename) # XXX this creates a new EditorWindow
if not args:
flist.new()
if enable_shell:
Modified: sandbox/trunk/ttk-gsoc/src/idlelib/editorpage.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/idlelib/editorpage.py (original)
+++ sandbox/trunk/ttk-gsoc/src/idlelib/editorpage.py Sat Jul 19 16:33:44 2008
@@ -9,20 +9,13 @@
import configDialog
import macosxSupport
import PyParse
+import IOBinding
import GrepDialog
import SearchDialog
import ReplaceDialog
from configHandler import idleConf
from MultiCall import MultiCallCreator
-
-#def callback(method, widget=None):
-# def func(*args):
-# if widget:
-# return method(widget=widget, *args)
-# else:
-# return method(*args)
-
-# return func
+from Percolator import Percolator
def classifyws(s, tabwidth):
raw = effective = 0
@@ -37,21 +30,135 @@
break
return raw, effective
-# "line.col" -> line, as an int
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')
+
class EditorPage:
- def __init__(self, parent, editwin, **kwargs):
+ def __init__(self, parent_frame, editwin, filename=None, **kwargs):
self.editwin = editwin
kwargs.setdefault('width', idleConf.GetOption('main', 'EditorPage',
'width'))
kwargs.setdefault('height', idleConf.GetOption('main', 'EditorPage',
'height'))
- self.text = MultiCallCreator(Text)(parent, **kwargs)
+ self.text = MultiCallCreator(Text)(parent_frame, **kwargs)
+
+ 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.undo.set_saved_change_hook(self.saved_change_hook)
+
+ self.io = IOBinding.IOBinding(self)
+ self.io.set_filename_change_hook(self.filename_change_hook)
+ if filename:
+ fail = self.io.loadfile(filename)
+ if fail:
+ self.io.set_filename(filename)
+ self.saved_change_hook()
+
+ self.color = None # initialized below in reset_colorizer
+ self.reset_colorizer()
+
self._setup_bindings()
+ 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
+
+ # XXX (1) mark where these functions are used
+ 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.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.saved_change_hook()
+ self.editwin.top.update_windowlist_registry(self)
+ 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 "")
+ # XXX (1) end
+
def center(self, mark="insert"):
# Used by EditorWindow.gotoline
text = self.text
@@ -225,6 +332,9 @@
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 macosxSupport.runningAsOSXApp():
# Command-W on editorwindows doesn't work without this.
@@ -601,6 +711,25 @@
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",
More information about the Python-checkins
mailing list