diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 64636df957e..689539e73c1 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -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 the 'Startup failure' section of the IDLE doc. diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py index 6ce8cc8a5f6..20e5e9014ee 100644 --- a/Lib/idlelib/idle_test/htest.py +++ b/Lib/idlelib/idle_test/htest.py @@ -110,10 +110,11 @@ _color_delegator_spec = { CustomRun_spec = { 'file': 'query', - 'kwds': {'title': 'Custom Run Args', + 'kwds': {'title': 'Customize query.py Run', '_htest': True}, - 'msg': "Enter with or [Ok]. Print valid entry to Shell\n" + 'msg': "Enter with or [Run]. Print valid entry to Shell\n" "Arguments are parsed into a list\n" + "Mode is currently restart True or False\n" "Close dialog with valid entry, , [Cancel], [X]" } diff --git a/Lib/idlelib/query.py b/Lib/idlelib/query.py index 9b3bb1d186b..d74084feed7 100644 --- a/Lib/idlelib/query.py +++ b/Lib/idlelib/query.py @@ -36,10 +36,10 @@ class Query(Toplevel): """ def __init__(self, parent, title, message, *, text0='', used_names={}, _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 - unless _utest=True is passed to suppress wait_window(). + Additional subclass init must be done before this unless + _utest=True is passed to suppress wait_window(). title - string, title of popup dialog message - string, informational message to display @@ -48,15 +48,17 @@ class Query(Toplevel): _htest - bool, change box location when running htest _utest - bool, leave window hidden and not modal """ - Toplevel.__init__(self, parent) - self.withdraw() # Hide while configuring, especially geometry. - self.parent = parent - self.title(title) + self.parent = parent # Needed for Font call. self.message = message self.text0 = text0 self.used_names = used_names + + Toplevel.__init__(self, parent) + self.withdraw() # Hide while configuring, especially geometry. + self.title(title) self.transient(parent) self.grab_set() + windowingsystem = self.tk.call('tk', 'windowingsystem') if windowingsystem == 'aqua': try: @@ -69,9 +71,9 @@ class Query(Toplevel): self.protocol("WM_DELETE_WINDOW", self.cancel) self.bind('', self.ok) self.bind("", self.ok) - self.resizable(height=False, width=False) + 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). "+%d+%d" % ( parent.winfo_rootx() + @@ -80,12 +82,19 @@ class Query(Toplevel): ((parent.winfo_height()/2 - self.winfo_reqheight()/2) if not _htest else 150) ) ) + self.resizable(height=False, width=False) + if not _utest: self.deiconify() # Unhide now that geometry set. self.wait_window() - def create_widgets(self, ok_text='OK'): # Call from override, if any. - # Bind to self widgets needed for entry_ok or unittest. + def create_widgets(self, ok_text='OK'): # Do not replace. + """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) frame.grid(column=0, row=0, sticky='news') frame.grid_columnconfigure(0, weight=1) @@ -99,19 +108,24 @@ class Query(Toplevel): exists=True, root=self.parent) self.entry_error = Label(frame, text=' ', foreground='red', 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) self.entry.grid(column=0, row=1, columnspan=3, padx=5, sticky=W+E, pady=[10,0]) self.entry_error.grid(column=0, row=2, columnspan=3, padx=5, 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_cancel.grid(column=2, row=99, padx=5) + def create_extra(self): pass # Override to add widgets. + def showerror(self, message, widget=None): #self.bell(displayof=self) (widget or self.entry_error)['text'] = 'ERROR: ' + message @@ -227,8 +241,8 @@ class HelpSource(Query): parent, title, message, text0=menuitem, used_names=used_names, _htest=_htest, _utest=_utest) - def create_widgets(self): - super().create_widgets() + def create_extra(self): + "Add path widjets to rows 10-12." frame = self.frame pathlabel = Label(frame, anchor='w', justify='left', text='Help File Path: Enter URL or browse for file') @@ -319,8 +333,8 @@ class CustomRun(Query): parent, title, message, text0=cli_args, _htest=_htest, _utest=_utest) - def create_widgets(self): - super().create_widgets(ok_text='Run') + def create_extra(self): + "Add run mode on rows 10-12." frame = self.frame self.restartvar = BooleanVar(self, value=True) restart = Checkbutton(frame, variable=self.restartvar, onvalue=True, @@ -328,7 +342,7 @@ class CustomRun(Query): self.args_error = Label(frame, text=' ', foreground='red', 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, sticky='we') diff --git a/Misc/NEWS.d/next/IDLE/2019-06-18-16-40-05.bpo-37325.GssOf1.rst b/Misc/NEWS.d/next/IDLE/2019-06-18-16-40-05.bpo-37325.GssOf1.rst new file mode 100644 index 00000000000..edfffbefe88 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-06-18-16-40-05.bpo-37325.GssOf1.rst @@ -0,0 +1 @@ +Fix tab focus traversal order for help source and custom run dialogs.