summaryrefslogtreecommitdiff
path: root/Lib/idlelib/editor.py
diff options
context:
space:
mode:
authorTal Einat <taleinat+github@gmail.com>2019-08-25 08:52:58 +0300
committerGitHub <noreply@github.com>2019-08-25 08:52:58 +0300
commitd4b4c00b57d24f6ee2cf3a96213406bb09953df3 (patch)
treef91a4598253622581add7aec2cf867f2bb8090e2 /Lib/idlelib/editor.py
parentaef9ad82f7f667cd001a7112d3bc636e918626f7 (diff)
downloadcpython-git-d4b4c00b57d24f6ee2cf3a96213406bb09953df3.tar.gz
bpo-37929: IDLE: avoid Squeezer-related config dialog crashes (GH-15452)
These were caused by keeping around a reference to the Squeezer instance and calling it's load_font() upon config changes, which sometimes happened even if the shell window no longer existed. This change completely removes that mechanism, instead having the editor window properly update its width attribute, which can then be used by Squeezer.
Diffstat (limited to 'Lib/idlelib/editor.py')
-rw-r--r--Lib/idlelib/editor.py25
1 files changed, 22 insertions, 3 deletions
diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py
index 35027da76b..793ed3afae 100644
--- a/Lib/idlelib/editor.py
+++ b/Lib/idlelib/editor.py
@@ -10,6 +10,7 @@ import traceback
import webbrowser
from tkinter import *
+from tkinter.font import Font
from tkinter.ttk import Scrollbar
import tkinter.simpledialog as tkSimpleDialog
import tkinter.messagebox as tkMessageBox
@@ -120,14 +121,13 @@ class EditorWindow(object):
self.prompt_last_line = '' # Override in PyShell
self.text_frame = text_frame = Frame(top)
self.vbar = vbar = Scrollbar(text_frame, name='vbar')
- self.width = idleConf.GetOption('main', 'EditorWindow',
- 'width', type='int')
+ width = idleConf.GetOption('main', 'EditorWindow', 'width', type='int')
text_options = {
'name': 'text',
'padx': 5,
'wrap': 'none',
'highlightthickness': 0,
- 'width': self.width,
+ 'width': width,
'tabstyle': 'wordprocessor', # new in 8.5
'height': idleConf.GetOption(
'main', 'EditorWindow', 'height', type='int'),
@@ -154,6 +154,7 @@ class EditorWindow(object):
text.bind('<MouseWheel>', self.mousescroll)
text.bind('<Button-4>', self.mousescroll)
text.bind('<Button-5>', self.mousescroll)
+ text.bind('<Configure>', self.handle_winconfig)
text.bind("<<cut>>", self.cut)
text.bind("<<copy>>", self.copy)
text.bind("<<paste>>", self.paste)
@@ -211,6 +212,7 @@ class EditorWindow(object):
text['font'] = idleConf.GetFont(self.root, 'main', 'EditorWindow')
text.grid(row=1, column=1, sticky=NSEW)
text.focus_set()
+ self.set_width()
# usetabs true -> literal tab characters are used by indent and
# dedent cmds, possibly mixed with spaces if
@@ -338,6 +340,22 @@ class EditorWindow(object):
else:
self.update_menu_state('options', '*Line Numbers', 'disabled')
+ def handle_winconfig(self, event=None):
+ self.set_width()
+
+ def set_width(self):
+ text = self.text
+ inner_padding = sum(map(text.tk.getint, [text.cget('border'),
+ text.cget('padx')]))
+ pixel_width = text.winfo_width() - 2 * inner_padding
+
+ # Divide the width of the Text widget by the font width,
+ # which is taken to be the width of '0' (zero).
+ # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21
+ zero_char_width = \
+ Font(text, font=text.cget('font')).measure('0')
+ self.width = pixel_width // zero_char_width
+
def _filename_to_unicode(self, filename):
"""Return filename as BMP unicode so displayable in Tk."""
# Decode bytes to unicode.
@@ -830,6 +848,7 @@ class EditorWindow(object):
# Finally, update the main text widget.
new_font = idleConf.GetFont(self.root, 'main', 'EditorWindow')
self.text['font'] = new_font
+ self.set_width()
def RemoveKeybindings(self):
"Remove the keybindings before they are changed."