Commit 54cf2e07 authored by Terry Jan Reedy's avatar Terry Jan Reedy Committed by GitHub

bpo-37325: Fix focus traversal for 2 IDLE dialogs (#14209)

Tab now moves focus across and down for Help Source and Custom Run.
parent d287215d
...@@ -3,6 +3,9 @@ Released on 2019-10-20? ...@@ -3,6 +3,9 @@ Released on 2019-10-20?
====================================== ======================================
bpo-37325: Fix tab focus traversal order for help source and custom
run dialogs.
bpo-37321: Both subprocess connection error messages now refer to bpo-37321: Both subprocess connection error messages now refer to
the 'Startup failure' section of the IDLE doc. the 'Startup failure' section of the IDLE doc.
......
...@@ -110,10 +110,11 @@ _color_delegator_spec = { ...@@ -110,10 +110,11 @@ _color_delegator_spec = {
CustomRun_spec = { CustomRun_spec = {
'file': 'query', 'file': 'query',
'kwds': {'title': 'Custom Run Args', 'kwds': {'title': 'Customize query.py Run',
'_htest': True}, '_htest': True},
'msg': "Enter with <Return> or [Ok]. Print valid entry to Shell\n" 'msg': "Enter with <Return> or [Run]. Print valid entry to Shell\n"
"Arguments are parsed into a list\n" "Arguments are parsed into a list\n"
"Mode is currently restart True or False\n"
"Close dialog with valid entry, <Escape>, [Cancel], [X]" "Close dialog with valid entry, <Escape>, [Cancel], [X]"
} }
......
...@@ -36,10 +36,10 @@ class Query(Toplevel): ...@@ -36,10 +36,10 @@ class Query(Toplevel):
""" """
def __init__(self, parent, title, message, *, text0='', used_names={}, def __init__(self, parent, title, message, *, text0='', used_names={},
_htest=False, _utest=False): _htest=False, _utest=False):
"""Create popup, do not return until tk widget destroyed. """Create modal popup, return when destroyed.
Additional subclass init must be done before calling this Additional subclass init must be done before this unless
unless _utest=True is passed to suppress wait_window(). _utest=True is passed to suppress wait_window().
title - string, title of popup dialog title - string, title of popup dialog
message - string, informational message to display message - string, informational message to display
...@@ -48,15 +48,17 @@ class Query(Toplevel): ...@@ -48,15 +48,17 @@ class Query(Toplevel):
_htest - bool, change box location when running htest _htest - bool, change box location when running htest
_utest - bool, leave window hidden and not modal _utest - bool, leave window hidden and not modal
""" """
Toplevel.__init__(self, parent) self.parent = parent # Needed for Font call.
self.withdraw() # Hide while configuring, especially geometry.
self.parent = parent
self.title(title)
self.message = message self.message = message
self.text0 = text0 self.text0 = text0
self.used_names = used_names self.used_names = used_names
Toplevel.__init__(self, parent)
self.withdraw() # Hide while configuring, especially geometry.
self.title(title)
self.transient(parent) self.transient(parent)
self.grab_set() self.grab_set()
windowingsystem = self.tk.call('tk', 'windowingsystem') windowingsystem = self.tk.call('tk', 'windowingsystem')
if windowingsystem == 'aqua': if windowingsystem == 'aqua':
try: try:
...@@ -69,9 +71,9 @@ class Query(Toplevel): ...@@ -69,9 +71,9 @@ class Query(Toplevel):
self.protocol("WM_DELETE_WINDOW", self.cancel) self.protocol("WM_DELETE_WINDOW", self.cancel)
self.bind('<Key-Return>', self.ok) self.bind('<Key-Return>', self.ok)
self.bind("<KP_Enter>", self.ok) self.bind("<KP_Enter>", self.ok)
self.resizable(height=False, width=False)
self.create_widgets() self.create_widgets()
self.update_idletasks() # Needed here for winfo_reqwidth below. self.update_idletasks() # Need here for winfo_reqwidth below.
self.geometry( # Center dialog over parent (or below htest box). self.geometry( # Center dialog over parent (or below htest box).
"+%d+%d" % ( "+%d+%d" % (
parent.winfo_rootx() + parent.winfo_rootx() +
...@@ -80,12 +82,19 @@ class Query(Toplevel): ...@@ -80,12 +82,19 @@ class Query(Toplevel):
((parent.winfo_height()/2 - self.winfo_reqheight()/2) ((parent.winfo_height()/2 - self.winfo_reqheight()/2)
if not _htest else 150) if not _htest else 150)
) ) ) )
self.resizable(height=False, width=False)
if not _utest: if not _utest:
self.deiconify() # Unhide now that geometry set. self.deiconify() # Unhide now that geometry set.
self.wait_window() self.wait_window()
def create_widgets(self, ok_text='OK'): # Call from override, if any. def create_widgets(self, ok_text='OK'): # Do not replace.
# Bind to self widgets needed for entry_ok or unittest. """Create entry (rows, extras, buttons.
Entry stuff on rows 0-2, spanning cols 0-2.
Buttons on row 99, cols 1, 2.
"""
# Bind to self the widgets needed for entry_ok or unittest.
self.frame = frame = Frame(self, padding=10) self.frame = frame = Frame(self, padding=10)
frame.grid(column=0, row=0, sticky='news') frame.grid(column=0, row=0, sticky='news')
frame.grid_columnconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1)
...@@ -99,19 +108,24 @@ class Query(Toplevel): ...@@ -99,19 +108,24 @@ class Query(Toplevel):
exists=True, root=self.parent) exists=True, root=self.parent)
self.entry_error = Label(frame, text=' ', foreground='red', self.entry_error = Label(frame, text=' ', foreground='red',
font=self.error_font) font=self.error_font)
self.button_ok = Button(
frame, text=ok_text, default='active', command=self.ok)
self.button_cancel = Button(
frame, text='Cancel', command=self.cancel)
entrylabel.grid(column=0, row=0, columnspan=3, padx=5, sticky=W) entrylabel.grid(column=0, row=0, columnspan=3, padx=5, sticky=W)
self.entry.grid(column=0, row=1, columnspan=3, padx=5, sticky=W+E, self.entry.grid(column=0, row=1, columnspan=3, padx=5, sticky=W+E,
pady=[10,0]) pady=[10,0])
self.entry_error.grid(column=0, row=2, columnspan=3, padx=5, self.entry_error.grid(column=0, row=2, columnspan=3, padx=5,
sticky=W+E) sticky=W+E)
self.create_extra()
self.button_ok = Button(
frame, text=ok_text, default='active', command=self.ok)
self.button_cancel = Button(
frame, text='Cancel', command=self.cancel)
self.button_ok.grid(column=1, row=99, padx=5) self.button_ok.grid(column=1, row=99, padx=5)
self.button_cancel.grid(column=2, row=99, padx=5) self.button_cancel.grid(column=2, row=99, padx=5)
def create_extra(self): pass # Override to add widgets.
def showerror(self, message, widget=None): def showerror(self, message, widget=None):
#self.bell(displayof=self) #self.bell(displayof=self)
(widget or self.entry_error)['text'] = 'ERROR: ' + message (widget or self.entry_error)['text'] = 'ERROR: ' + message
...@@ -227,8 +241,8 @@ class HelpSource(Query): ...@@ -227,8 +241,8 @@ class HelpSource(Query):
parent, title, message, text0=menuitem, parent, title, message, text0=menuitem,
used_names=used_names, _htest=_htest, _utest=_utest) used_names=used_names, _htest=_htest, _utest=_utest)
def create_widgets(self): def create_extra(self):
super().create_widgets() "Add path widjets to rows 10-12."
frame = self.frame frame = self.frame
pathlabel = Label(frame, anchor='w', justify='left', pathlabel = Label(frame, anchor='w', justify='left',
text='Help File Path: Enter URL or browse for file') text='Help File Path: Enter URL or browse for file')
...@@ -319,8 +333,8 @@ class CustomRun(Query): ...@@ -319,8 +333,8 @@ class CustomRun(Query):
parent, title, message, text0=cli_args, parent, title, message, text0=cli_args,
_htest=_htest, _utest=_utest) _htest=_htest, _utest=_utest)
def create_widgets(self): def create_extra(self):
super().create_widgets(ok_text='Run') "Add run mode on rows 10-12."
frame = self.frame frame = self.frame
self.restartvar = BooleanVar(self, value=True) self.restartvar = BooleanVar(self, value=True)
restart = Checkbutton(frame, variable=self.restartvar, onvalue=True, restart = Checkbutton(frame, variable=self.restartvar, onvalue=True,
...@@ -328,7 +342,7 @@ class CustomRun(Query): ...@@ -328,7 +342,7 @@ class CustomRun(Query):
self.args_error = Label(frame, text=' ', foreground='red', self.args_error = Label(frame, text=' ', foreground='red',
font=self.error_font) font=self.error_font)
restart.grid(column=0, row=4, columnspan=3, padx=5, sticky='w') restart.grid(column=0, row=10, columnspan=3, padx=5, sticky='w')
self.args_error.grid(column=0, row=12, columnspan=3, padx=5, self.args_error.grid(column=0, row=12, columnspan=3, padx=5,
sticky='we') sticky='we')
......
Fix tab focus traversal order for help source and custom run dialogs.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment