Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-27755: replace DynOptionMenu/OptionMenu with ttk.Combobox #7979

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Lib/idlelib/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ config.py # Load, fetch, and save configuration (nim).
configdialog.py # Display user configuration dialogs.
config_help.py # Specify help source in configdialog.
config_key.py # Change keybindings.
dynoption.py # Define mutable OptionMenu widget (nim).
debugobj.py # Define class used in stackviewer.
debugobj_r.py # Communicate objects between processes with rpc (nim).
debugger.py # Debug code run from shell or editor; show window.
Expand Down
139 changes: 85 additions & 54 deletions Lib/idlelib/configdialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@
TOP, BOTTOM, RIGHT, LEFT, SOLID, GROOVE,
NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW,
HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END)
from tkinter.ttk import (Frame, LabelFrame, Button, Checkbutton, Entry, Label,
OptionMenu, Notebook, Radiobutton, Scrollbar, Style)
from tkinter.ttk import (Button, Checkbutton, Entry, Frame, Label, LabelFrame,
Notebook, Radiobutton, Scrollbar, Style, Combobox)
import tkinter.colorchooser as tkColorChooser
import tkinter.font as tkFont
from tkinter import messagebox

from idlelib.config import idleConf, ConfigChanges
from idlelib.config_key import GetKeysDialog
from idlelib.dynoption import DynOptionMenu
from idlelib import macosx
from idlelib.query import SectionName, HelpSource
from idlelib.textview import view_text
Expand Down Expand Up @@ -520,7 +519,7 @@ def create_page_font_tab(self):
scroll_font: Scrollbar
frame_font_param: Frame
font_size_title: Label
(*)sizelist: DynOptionMenu - font_size
(*)sizelist: Combobox - font_size
(*)bold_toggle: Checkbutton - font_bold
frame_sample: LabelFrame
(*)font_sample: Label
Expand Down Expand Up @@ -555,7 +554,10 @@ 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 = Combobox(frame_font_param, textvariable=self.font_size,
width=3, state='readonly')
self.sizelist.bind('<<ComboboxSelected>>',
lambda e: self.sizelist.selection_clear())
self.bold_toggle = Checkbutton(
frame_font_param, variable=self.font_bold,
onvalue=1, offvalue=0, text='Bold')
Expand Down Expand Up @@ -621,9 +623,10 @@ 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['values'] = ('7', '8', '9', '10', '11', '12', '13', '14',
'16', '18', '20', '22', '25', '29', '34', '40')
self.sizelist.set(font_size)

# Set font weight.
self.font_bold.set(font_bold)
self.set_samples()
Expand Down Expand Up @@ -707,7 +710,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
Comboboxes 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.

Expand Down Expand Up @@ -737,7 +740,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
Combobox 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().
Expand Down Expand Up @@ -795,7 +798,7 @@ def create_page_highlight(self):
(*)highlight_sample: Text
(*)frame_color_set: Frame
(*)button_set_color: Button
(*)targetlist: DynOptionMenu - highlight_target
(*)targetlist: Combobox - highlight_target
frame_fg_bg_toggle: Frame
(*)fg_on: Radiobutton - fg_bg_toggle
(*)bg_on: Radiobutton - fg_bg_toggle
Expand All @@ -804,8 +807,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: Combobox - builtin_name
(*)customlist: Combobox - custom_name
(*)button_delete_custom: Button
(*)theme_message: Label
"""
Expand Down Expand Up @@ -894,9 +897,10 @@ 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 = Combobox(self.frame_color_set,
textvariable=self.highlight_target, state='readonly')
self.targetlist.bind('<<ComboboxSelected>>',
lambda e: self.targetlist.selection_clear())
self.fg_on = Radiobutton(
frame_fg_bg_toggle, variable=self.fg_bg_toggle, value=1,
text='Foreground', command=self.set_color_sample_binding)
Expand All @@ -915,10 +919,15 @@ 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(
frame_theme, self.builtin_name, None, command=None)
self.customlist = DynOptionMenu(
frame_theme, self.custom_name, None, command=None)
self.builtinlist = Combobox(frame_theme,
textvariable=self.builtin_name, state='readonly')
self.builtinlist.bind('<<ComboboxSelected>>',
lambda e: self.builtinlist.selection_clear())
self.customlist = Combobox(frame_theme,
textvariable=self.custom_name, state='readonly')
self.customlist.bind('<<ComboboxSelected>>',
lambda e: self.customlist.selection_clear())

self.button_delete_custom = Button(
frame_theme, text='Delete Custom Theme',
command=self.delete_custom)
Expand Down Expand Up @@ -975,26 +984,31 @@ 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['values'] = item_list
self.builtinlist.set(current_option)
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['values'] = item_list
self.customlist.set(item_list[0])
else: # User theme selected.
item_list = idleConf.GetSectionList('user', 'highlight')
item_list.sort()
self.customlist.SetMenu(item_list, current_option)
self.customlist['values'] = item_list
self.customlist.set(current_option)
item_list = idleConf.GetSectionList('default', 'highlight')
item_list.sort()
self.builtinlist.SetMenu(item_list, item_list[0])
self.builtinlist['values'] = item_list
self.builtinlist.set(item_list[0])
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['values'] = theme_names
self.targetlist.set(theme_names[0])
self.paint_theme_sample()
self.set_highlight_target()

Expand Down Expand Up @@ -1068,13 +1082,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):
Expand Down Expand Up @@ -1181,7 +1195,8 @@ 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['values'] = custom_theme_list
self.customlist.set(new_theme_name)
self.theme_source.set(0)
self.set_theme_type()

Expand Down Expand Up @@ -1329,9 +1344,11 @@ 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['values'] = item_list
self.customlist.set('- no custom themes -')
else:
self.customlist.SetMenu(item_list, item_list[0])
self.customlist['values'] = item_list
self.customlist.set(item_list[0])
# Revert to default theme.
self.theme_source.set(idleConf.defaultCfg['main'].Get('Theme', 'default'))
self.builtin_name.set(idleConf.defaultCfg['main'].Get('Theme', 'name'))
Expand Down Expand Up @@ -1364,7 +1381,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. Comboboxes 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.
Expand Down Expand Up @@ -1416,9 +1433,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: Combobox - var builtin_name,
func keybinding_selected
(*)customlist: DynOptionMenu - var custom_name,
(*)customlist: Combobox - var custom_name,
func keybinding_selected
(*)keys_message: Label
frames[1]: Frame
Expand Down Expand Up @@ -1473,10 +1490,14 @@ 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(
frames[0], self.builtin_name, None, command=None)
self.customlist = DynOptionMenu(
frames[0], self.custom_name, None, command=None)
self.builtinlist = Combobox(frames[0],
textvariable=self.builtin_name, state='readonly')
self.builtinlist.bind('<<ComboboxSelected>>',
lambda e: self.builtinlist.selection_clear())
self.customlist = Combobox(frames[0],
textvariable=self.custom_name, state='readonly')
self.customlist.bind('<<ComboboxSelected>>',
lambda e: self.customlist.selection_clear())
self.button_delete_custom_keys = Button(
frames[1], text='Delete Custom Key Set',
command=self.delete_custom_keys)
Expand Down Expand Up @@ -1521,21 +1542,25 @@ 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['values'] = item_list
self.builtinlist.set(current_option)
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['values'] = item_list
self.customlist.set(item_list[0])
else: # User key set selected.
item_list = idleConf.GetSectionList('user', 'keys')
item_list.sort()
self.customlist.SetMenu(item_list, current_option)
self.customlist['values'] = item_list
self.customlist.set(current_option)
item_list = idleConf.GetSectionList('default', 'keys')
item_list.sort()
self.builtinlist.SetMenu(item_list, idleConf.default_keys())
self.builtinlist['values'] = item_list
self.builtinlist.set(idleConf.default_keys())
self.set_keys_type()
# Load keyset element list.
keyset_name = idleConf.CurrentKeys()
Expand Down Expand Up @@ -1592,13 +1617,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):
Expand Down Expand Up @@ -1689,7 +1714,8 @@ 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['values'] = custom_key_list
self.customlist.set(new_key_set_name)
self.keyset_source.set(0)
self.set_keys_type()

Expand Down Expand Up @@ -1759,9 +1785,11 @@ 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['values'] = item_list
self.customlist.set('- no custom keys -')
else:
self.customlist.SetMenu(item_list, item_list[0])
self.customlist['values'] = item_list
self.customlist.set(item_list[0])
# Revert to default key set.
self.keyset_source.set(idleConf.defaultCfg['main']
.Get('Keys', 'default'))
Expand Down Expand Up @@ -1829,7 +1857,7 @@ def create_page_general(self):
(*)auto_wait_int: Entry - autocomplete_wait
frame_paren1: Frame
paren_style_title: Label
(*)paren_style_type: OptionMenu - paren_style
(*)paren_style_type: Combobox - paren_style
frame_paren2: Frame
paren_time_title: Label
(*)paren_flash_time: Entry - flash_delay
Expand Down Expand Up @@ -1942,9 +1970,12 @@ def create_page_general(self):

frame_paren1 = Frame(frame_window, borderwidth=0)
paren_style_title = Label(frame_paren1, text='Paren Match Style')
self.paren_style_type = OptionMenu(
frame_paren1, self.paren_style, 'expression',
"opener","parens","expression")
self.paren_style_type = Combobox(frame_paren1,
textvariable=self.paren_style, state='readonly', width=10,
values=("opener","parens","expression"))
self.paren_style_type.set('expression')
self.paren_style_type.bind('<<ComboboxSelected>>',
lambda e: self.paren_style_type.selection_clear())
frame_paren2 = Frame(frame_window, borderwidth=0)
paren_time_title = Label(
frame_paren2, text='Time Match Displayed (milliseconds)\n'
Expand Down
Loading