From 259cc30169e0f4dee2963f5f9b9dd01cb6558d40 Mon Sep 17 00:00:00 2001 From: Cheryl Sabella Date: Sat, 26 Aug 2017 19:13:57 -0400 Subject: [PATCH 1/2] bpo-30781: IDLE: Convert configdialog DynOptionMenu to ttk OptionMenu --- Lib/idlelib/configdialog.py | 87 +++++++++++----------- Lib/idlelib/idle_test/test_configdialog.py | 40 +++++----- 2 files changed, 63 insertions(+), 64 deletions(-) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index ff7b638b51fef6..0b5cb642d2ecf2 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -15,7 +15,7 @@ NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW, HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END) from tkinter.ttk import (Button, Checkbutton, Entry, Frame, Label, LabelFrame, - Notebook, Radiobutton, Scrollbar, Style) + Notebook, OptionMenu, Radiobutton, Scrollbar, Style) import tkinter.colorchooser as tkColorChooser import tkinter.font as tkFont import tkinter.messagebox as tkMessageBox @@ -469,7 +469,7 @@ def create_page_font_tab(self): scroll_font: Scrollbar frame_font_param: Frame font_size_title: Label - (*)sizelist: DynOptionMenu - font_size + (*)sizelist: OptionMenu - font_size (*)bold_toggle: Checkbutton - font_bold frame_font_sample: Frame (*)font_sample: Label @@ -502,7 +502,7 @@ def create_page_font_tab(self): scroll_font.config(command=self.fontlist.yview) self.fontlist.config(yscrollcommand=scroll_font.set) font_size_title = Label(frame_font_param, text='Size :') - self.sizelist = DynOptionMenu(frame_font_param, self.font_size, None) + self.sizelist = OptionMenu(frame_font_param, self.font_size, None) self.bold_toggle = Checkbutton( frame_font_param, variable=self.font_bold, onvalue=1, offvalue=0, text='Bold') @@ -567,9 +567,9 @@ def load_font_cfg(self): except ValueError: pass # Set font size dropdown. - self.sizelist.SetMenu(('7', '8', '9', '10', '11', '12', '13', '14', - '16', '18', '20', '22', '25', '29', '34', '40'), - font_size) + self.sizelist.set_menu(font_size, *('7', '8', '9', '10', '11', '12', + '13', '14', '16', '18', '20', '22', + '25', '29', '34', '40')) # Set font weight. self.font_bold.set(font_bold) self.set_samples() @@ -653,7 +653,7 @@ def create_page_highlight(self): for the current theme. Radiobuttons builtin_theme_on and custom_theme_on toggle var theme_source, which controls if the current set of colors are from a builtin or custom theme. - DynOptionMenus builtinlist and customlist contain lists of the + OptionMenus builtinlist and customlist contain lists of the builtin and custom themes, respectively, and the current item from each list is stored in vars builtin_name and custom_name. @@ -683,7 +683,7 @@ def create_page_highlight(self): if the current selected color for a tag is for the foreground or background. - DynOptionMenu targetlist contains a readable description of the + OptionMenu targetlist contains a readable description of the tags applied to Python source within IDLE. Selecting one of the tags from this list populates highlight_target, which has a callback function set_highlight_target(). @@ -741,7 +741,7 @@ def create_page_highlight(self): (*)highlight_sample: Text (*)frame_color_set: Frame (*)button_set_color: Button - (*)targetlist: DynOptionMenu - highlight_target + (*)targetlist: OptionMenu - highlight_target frame_fg_bg_toggle: Frame (*)fg_on: Radiobutton - fg_bg_toggle (*)bg_on: Radiobutton - fg_bg_toggle @@ -750,8 +750,8 @@ def create_page_highlight(self): theme_type_title: Label (*)builtin_theme_on: Radiobutton - theme_source (*)custom_theme_on: Radiobutton - theme_source - (*)builtinlist: DynOptionMenu - builtin_name - (*)customlist: DynOptionMenu - custom_name + (*)builtinlist: OptionMenu - builtin_name + (*)customlist: OptionMenu - custom_name (*)button_delete_custom: Button (*)theme_message: Label """ @@ -829,9 +829,8 @@ def tem(event, elem=element): self.button_set_color = Button( self.frame_color_set, text='Choose Color for :', command=self.get_color) - self.targetlist = DynOptionMenu( - self.frame_color_set, self.highlight_target, None, - highlightthickness=0) #, command=self.set_highlight_targetBinding + self.targetlist = OptionMenu( + self.frame_color_set, self.highlight_target, None) self.fg_on = Radiobutton( frame_fg_bg_toggle, variable=self.fg_bg_toggle, value=1, text='Foreground', command=self.set_color_sample_binding) @@ -850,9 +849,9 @@ def tem(event, elem=element): self.custom_theme_on = Radiobutton( frame_theme, variable=self.theme_source, value=0, command=self.set_theme_type, text='a Custom Theme') - self.builtinlist = DynOptionMenu( + self.builtinlist = OptionMenu( frame_theme, self.builtin_name, None, command=None) - self.customlist = DynOptionMenu( + self.customlist = OptionMenu( frame_theme, self.custom_name, None, command=None) self.button_delete_custom = Button( frame_theme, text='Delete Custom Theme', @@ -911,26 +910,26 @@ def load_theme_cfg(self): if self.theme_source.get(): # Default theme selected. item_list = idleConf.GetSectionList('default', 'highlight') item_list.sort() - self.builtinlist.SetMenu(item_list, current_option) + self.builtinlist.set_menu(current_option, *item_list) item_list = idleConf.GetSectionList('user', 'highlight') item_list.sort() if not item_list: self.custom_theme_on.state(('disabled',)) self.custom_name.set('- no custom themes -') else: - self.customlist.SetMenu(item_list, item_list[0]) + self.customlist.set_menu(item_list[0], *item_list) else: # User theme selected. item_list = idleConf.GetSectionList('user', 'highlight') item_list.sort() - self.customlist.SetMenu(item_list, current_option) + self.customlist.set_menu(current_option, *item_list) item_list = idleConf.GetSectionList('default', 'highlight') item_list.sort() - self.builtinlist.SetMenu(item_list, item_list[0]) + self.builtinlist.set_menu(item_list[0], *item_list) self.set_theme_type() # Load theme element option menu. theme_names = list(self.theme_elements.keys()) theme_names.sort(key=lambda x: self.theme_elements[x][1]) - self.targetlist.SetMenu(theme_names, theme_names[0]) + self.targetlist.set_menu(theme_names[0], *theme_names) self.paint_theme_sample() self.set_highlight_target() @@ -1004,13 +1003,13 @@ def set_theme_type(self): load_theme_cfg """ if self.theme_source.get(): - self.builtinlist['state'] = 'normal' - self.customlist['state'] = 'disabled' + self.builtinlist.state(('!disabled',)) + self.customlist.state(('disabled',)) self.button_delete_custom.state(('disabled',)) else: - self.builtinlist['state'] = 'disabled' + self.builtinlist.state(('disabled',)) self.custom_theme_on.state(('!disabled',)) - self.customlist['state'] = 'normal' + self.customlist.state(('!disabled',)) self.button_delete_custom.state(('!disabled',)) def get_color(self): @@ -1117,7 +1116,7 @@ def create_new(self, new_theme_name): # Change GUI over to the new theme. custom_theme_list = idleConf.GetSectionList('user', 'highlight') custom_theme_list.sort() - self.customlist.SetMenu(custom_theme_list, new_theme_name) + self.customlist.set_menu(new_theme_name, *custom_theme_list) self.theme_source.set(0) self.set_theme_type() @@ -1262,9 +1261,9 @@ def delete_custom(self): item_list.sort() if not item_list: self.custom_theme_on.state(('disabled',)) - self.customlist.SetMenu(item_list, '- no custom themes -') + self.customlist.set_menu('- no custom themes -', *item_list) else: - self.customlist.SetMenu(item_list, item_list[0]) + self.customlist.set_menu(item_list[0], *item_list) # Revert to default theme. self.theme_source.set(idleConf.defaultCfg['main'].Get('Theme', 'default')) self.builtin_name.set(idleConf.defaultCfg['main'].Get('Theme', 'name')) @@ -1297,7 +1296,7 @@ def create_page_keys(self): lists and calls load_keys_list for the current keyset. Radiobuttons builtin_keyset_on and custom_keyset_on toggle var keyset_source, which controls if the current set of keybindings - are from a builtin or custom keyset. DynOptionMenus builtinlist + are from a builtin or custom keyset. OptionMenus builtinlist and customlist contain lists of the builtin and custom keysets, respectively, and the current item from each list is stored in vars builtin_name and custom_name. @@ -1349,9 +1348,9 @@ def create_page_keys(self): frames[0]: Frame (*)builtin_keyset_on: Radiobutton - var keyset_source (*)custom_keyset_on: Radiobutton - var keyset_source - (*)builtinlist: DynOptionMenu - var builtin_name, + (*)builtinlist: OptionMenu - var builtin_name, func keybinding_selected - (*)customlist: DynOptionMenu - var custom_name, + (*)customlist: OptionMenu - var custom_name, func keybinding_selected (*)keys_message: Label frames[1]: Frame @@ -1406,9 +1405,9 @@ def create_page_keys(self): self.custom_keyset_on = Radiobutton( frames[0], variable=self.keyset_source, value=0, command=self.set_keys_type, text='Use a Custom Key Set') - self.builtinlist = DynOptionMenu( + self.builtinlist = OptionMenu( frames[0], self.builtin_name, None, command=None) - self.customlist = DynOptionMenu( + self.customlist = OptionMenu( frames[0], self.custom_name, None, command=None) self.button_delete_custom_keys = Button( frames[1], text='Delete Custom Key Set', @@ -1454,21 +1453,21 @@ def load_key_cfg(self): if self.keyset_source.get(): # Default theme selected. item_list = idleConf.GetSectionList('default', 'keys') item_list.sort() - self.builtinlist.SetMenu(item_list, current_option) + self.builtinlist.set_menu(current_option, *item_list) item_list = idleConf.GetSectionList('user', 'keys') item_list.sort() if not item_list: self.custom_keyset_on.state(('disabled',)) self.custom_name.set('- no custom keys -') else: - self.customlist.SetMenu(item_list, item_list[0]) + self.customlist.set_menu(item_list[0], *item_list) else: # User key set selected. item_list = idleConf.GetSectionList('user', 'keys') item_list.sort() - self.customlist.SetMenu(item_list, current_option) + self.customlist.set_menu(current_option, *item_list) item_list = idleConf.GetSectionList('default', 'keys') item_list.sort() - self.builtinlist.SetMenu(item_list, idleConf.default_keys()) + self.builtinlist.set_menu(idleConf.default_keys(), *item_list) self.set_keys_type() # Load keyset element list. keyset_name = idleConf.CurrentKeys() @@ -1525,13 +1524,13 @@ def var_changed_keybinding(self, *params): def set_keys_type(self): "Set available screen options based on builtin or custom key set." if self.keyset_source.get(): - self.builtinlist['state'] = 'normal' - self.customlist['state'] = 'disabled' + self.builtinlist.state(('!disabled',)) + self.customlist.state(('disabled',)) self.button_delete_custom_keys.state(('disabled',)) else: - self.builtinlist['state'] = 'disabled' + self.builtinlist.state(('disabled',)) self.custom_keyset_on.state(('!disabled',)) - self.customlist['state'] = 'normal' + self.customlist.state(('!disabled',)) self.button_delete_custom_keys.state(('!disabled',)) def get_new_keys(self): @@ -1622,7 +1621,7 @@ def create_new_key_set(self, new_key_set_name): # Change GUI over to the new key set. custom_key_list = idleConf.GetSectionList('user', 'keys') custom_key_list.sort() - self.customlist.SetMenu(custom_key_list, new_key_set_name) + self.customlist.set_menu(new_key_set_name, *custom_key_list) self.keyset_source.set(0) self.set_keys_type() @@ -1689,9 +1688,9 @@ def delete_custom_keys(self): item_list.sort() if not item_list: self.custom_keyset_on.state(('disabled',)) - self.customlist.SetMenu(item_list, '- no custom keys -') + self.customlist.set_menu('- no custom keys -', *item_list) else: - self.customlist.SetMenu(item_list, item_list[0]) + self.customlist.set_menu(item_list[0], *item_list) # Revert to default key set. self.keyset_source.set(idleConf.defaultCfg['main'] .Get('Keys', 'default')) diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index c947da1866e099..f9c7dd563c6385 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -141,7 +141,7 @@ def test_fontlist_mouse(self): def test_sizelist(self): # Click on number should select that number d = self.page - d.sizelist.variable.set(40) + d.sizelist._variable.set(40) self.assertEqual(d.font_size.get(), '40') def test_bold_toggle(self): @@ -329,7 +329,7 @@ def test_builtin_name(self): # Not in old_themes, defaults name to first item. idleConf.SetOption('main', 'Theme', 'name', 'spam') - d.builtinlist.SetMenu(item_list, 'IDLE Dark') + d.builtinlist.set_menu('IDLE Dark', *item_list) eq(mainpage, {'Theme': {'name': 'IDLE Classic', 'name2': 'IDLE Dark'}}) eq(d.theme_message['text'], 'New theme, see Help') @@ -338,14 +338,14 @@ def test_builtin_name(self): # Not in old themes - uses name2. changes.clear() idleConf.SetOption('main', 'Theme', 'name', 'IDLE New') - d.builtinlist.SetMenu(item_list, 'IDLE Dark') + d.builtinlist.set_menu('IDLE Dark', *item_list) eq(mainpage, {'Theme': {'name2': 'IDLE Dark'}}) eq(d.theme_message['text'], 'New theme, see Help') eq(d.paint_theme_sample.called, 2) # Builtin name in old_themes. changes.clear() - d.builtinlist.SetMenu(item_list, 'IDLE Classic') + d.builtinlist.set_menu('IDLE Classic', *item_list) eq(mainpage, {'Theme': {'name': 'IDLE Classic', 'name2': ''}}) eq(d.theme_message['text'], '') eq(d.paint_theme_sample.called, 3) @@ -354,13 +354,13 @@ def test_custom_name(self): d = self.page # If no selections, doesn't get added. - d.customlist.SetMenu([], '- no custom themes -') + d.customlist.set_menu('- no custom themes -', *[]) self.assertNotIn('Theme', mainpage) self.assertEqual(d.paint_theme_sample.called, 0) # Custom name selected. changes.clear() - d.customlist.SetMenu(['a', 'b', 'c'], 'c') + d.customlist.set_menu('c', *['a', 'b', 'c']) self.assertEqual(mainpage, {'Theme': {'name': 'c'}}) self.assertEqual(d.paint_theme_sample.called, 1) @@ -377,7 +377,7 @@ def test_highlight_target_list_mouse(self): eq = self.assertEqual d = self.page - d.targetlist.SetMenu(['a', 'b', 'c'], 'c') + d.targetlist.set_menu('c', ['a', 'b', 'c']) eq(d.highlight_target.get(), 'c') eq(d.set_highlight_target.called, 1) @@ -426,16 +426,16 @@ def test_set_theme_type(self): # Builtin theme selected. d.theme_source.set(True) d.set_theme_type() - eq(d.builtinlist['state'], NORMAL) - eq(d.customlist['state'], DISABLED) + eq(d.builtinlist.state(), ()) + eq(d.customlist.state(), ('disabled',)) eq(d.button_delete_custom.state(), ('disabled',)) # Custom theme selected. d.theme_source.set(False) d.set_theme_type() - eq(d.builtinlist['state'], DISABLED) + eq(d.builtinlist.state(), ('disabled',)) eq(d.custom_theme_on.state(), ('selected',)) - eq(d.customlist['state'], NORMAL) + eq(d.customlist.state(), ()) eq(d.button_delete_custom.state(), ()) d.set_theme_type = Func() @@ -781,7 +781,7 @@ def test_builtin_name(self): 'IDLE Modern UNIX'] # Not in old_keys, defaults name to first item. - d.builtinlist.SetMenu(item_list, 'IDLE Modern UNIX') + d.builtinlist.set_menu('IDLE Modern UNIX', *item_list) eq(mainpage, {'Keys': {'name': 'IDLE Classic Windows', 'name2': 'IDLE Modern UNIX'}}) eq(d.keys_message['text'], 'New key set, see Help') @@ -791,7 +791,7 @@ def test_builtin_name(self): # Not in old keys - uses name2. changes.clear() idleConf.SetOption('main', 'Keys', 'name', 'IDLE Classic Unix') - d.builtinlist.SetMenu(item_list, 'IDLE Modern UNIX') + d.builtinlist.set_menu('IDLE Modern UNIX', *item_list) eq(mainpage, {'Keys': {'name2': 'IDLE Modern UNIX'}}) eq(d.keys_message['text'], 'New key set, see Help') eq(d.load_keys_list.called, 2) @@ -799,7 +799,7 @@ def test_builtin_name(self): # Builtin name in old_keys. changes.clear() - d.builtinlist.SetMenu(item_list, 'IDLE Classic OSX') + d.builtinlist.set_menu('IDLE Classic OSX', *item_list) eq(mainpage, {'Keys': {'name': 'IDLE Classic OSX', 'name2': ''}}) eq(d.keys_message['text'], '') eq(d.load_keys_list.called, 3) @@ -809,13 +809,13 @@ def test_custom_name(self): d = self.page # If no selections, doesn't get added. - d.customlist.SetMenu([], '- no custom keys -') + d.customlist.set_menu('- no custom keys -', *[]) self.assertNotIn('Keys', mainpage) self.assertEqual(d.load_keys_list.called, 0) # Custom name selected. changes.clear() - d.customlist.SetMenu(['a', 'b', 'c'], 'c') + d.customlist.set_menu('c', *['a', 'b', 'c']) self.assertEqual(mainpage, {'Keys': {'name': 'c'}}) self.assertEqual(d.load_keys_list.called, 1) @@ -846,16 +846,16 @@ def test_set_keys_type(self): # Builtin keyset selected. d.keyset_source.set(True) d.set_keys_type() - eq(d.builtinlist['state'], NORMAL) - eq(d.customlist['state'], DISABLED) + eq(d.builtinlist.state(), ()) + eq(d.customlist.state(), ('disabled',)) eq(d.button_delete_custom_keys.state(), ('disabled',)) # Custom keyset selected. d.keyset_source.set(False) d.set_keys_type() - eq(d.builtinlist['state'], DISABLED) + eq(d.builtinlist.state(), ('disabled',)) eq(d.custom_keyset_on.state(), ('selected',)) - eq(d.customlist['state'], NORMAL) + eq(d.customlist.state(), ()) eq(d.button_delete_custom_keys.state(), ()) d.set_keys_type = Func() From 73084771c89971cf17998f8b3f6724cf5b0fc7f4 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 10 Sep 2017 23:31:43 -0400 Subject: [PATCH 2/2] News blurb --- Misc/NEWS.d/next/IDLE/2017-09-10-23-30-54.bpo-27755.eBjhV-.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/IDLE/2017-09-10-23-30-54.bpo-27755.eBjhV-.rst diff --git a/Misc/NEWS.d/next/IDLE/2017-09-10-23-30-54.bpo-27755.eBjhV-.rst b/Misc/NEWS.d/next/IDLE/2017-09-10-23-30-54.bpo-27755.eBjhV-.rst new file mode 100644 index 00000000000000..4cdb8e36136c68 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2017-09-10-23-30-54.bpo-27755.eBjhV-.rst @@ -0,0 +1,2 @@ +IDLE: Selectively replace DynOptionMenu with ttk.OptionMenu. Patch by Cheryl +Sabella.