bpo-30853: IDLE: Convert font and general vars to use VarTrace (#2914)

Instance tracers manages pairs consisting of a tk variable and a
callback function.  When tracing is turned on, setting the variable
calls the function.  Test coverage for the new class is 100%.
This commit is contained in:
csabella 2017-07-28 14:40:59 -04:00 committed by Terry Jan Reedy
parent 6fcb69dad5
commit 5b59154c0d
2 changed files with 47 additions and 62 deletions

View file

@ -30,6 +30,7 @@
changes = ConfigChanges() changes = ConfigChanges()
class ConfigDialog(Toplevel): class ConfigDialog(Toplevel):
"""Config dialog for IDLE. """Config dialog for IDLE.
""" """
@ -75,13 +76,15 @@ def __init__(self, parent, title='', _htest=False, _utest=False):
# self.bind('<Alt-a>', self.Apply) #apply changes, save # self.bind('<Alt-a>', self.Apply) #apply changes, save
# self.bind('<F1>', self.Help) #context help # self.bind('<F1>', self.Help) #context help
self.load_configs() self.load_configs()
self.attach_var_callbacks() # Avoid callbacks during load_configs. # Avoid callbacks during load_configs.
tracers.attach()
if not _utest: if not _utest:
self.grab_set() self.grab_set()
self.wm_deiconify() self.wm_deiconify()
self.wait_window() self.wait_window()
def create_widgets(self): def create_widgets(self):
"""Create and place widgets for tabbed dialog. """Create and place widgets for tabbed dialog.
@ -96,7 +99,6 @@ def create_widgets(self):
create_page_extensions create_page_extensions
create_action_buttons create_action_buttons
load_configs: Load pages except for extensions. load_configs: Load pages except for extensions.
attach_var_callbacks
remove_var_callbacks remove_var_callbacks
activate_config_changes: Tell editors to reload. activate_config_changes: Tell editors to reload.
""" """
@ -131,37 +133,9 @@ def load_configs(self):
self.load_general_cfg() self.load_general_cfg()
# note: extension page handled separately # note: extension page handled separately
def attach_var_callbacks(self):
"Attach callbacks to variables that can be changed."
self.font_size.trace_add('write', self.var_changed_font)
self.font_name.trace_add('write', self.var_changed_font)
self.font_bold.trace_add('write', self.var_changed_font)
self.space_num.trace_add('write', self.var_changed_space_num)
self.color.trace_add('write', self.var_changed_color)
self.builtin_theme.trace_add('write', self.var_changed_builtin_theme)
self.custom_theme.trace_add('write', self.var_changed_custom_theme)
self.is_builtin_theme.trace_add('write', self.var_changed_is_builtin_theme)
self.highlight_target.trace_add('write', self.var_changed_highlight_target)
self.keybinding.trace_add('write', self.var_changed_keybinding)
self.builtin_keys.trace_add('write', self.var_changed_builtin_keys)
self.custom_keys.trace_add('write', self.var_changed_custom_keys)
self.are_keys_builtin.trace_add('write', self.var_changed_are_keys_builtin)
self.win_width.trace_add('write', self.var_changed_win_width)
self.win_height.trace_add('write', self.var_changed_win_height)
self.startup_edit.trace_add('write', self.var_changed_startup_edit)
self.autosave.trace_add('write', self.var_changed_autosave)
def remove_var_callbacks(self): def remove_var_callbacks(self):
"Remove callbacks to prevent memory leaks." "Remove callbacks to prevent memory leaks."
for var in ( tracers.detach()
self.font_size, self.font_name, self.font_bold,
self.space_num, self.color, self.builtin_theme,
self.custom_theme, self.is_builtin_theme, self.highlight_target,
self.keybinding, self.builtin_keys, self.custom_keys,
self.are_keys_builtin, self.win_width, self.win_height,
self.startup_edit, self.autosave,):
var.trace_remove('write', var.trace_info()[0][1])
def create_action_buttons(self): def create_action_buttons(self):
"""Return frame of action buttons for dialog. """Return frame of action buttons for dialog.
@ -273,7 +247,7 @@ def create_page_font_tab(self):
Tabs: Enable users to change spaces entered for indent tabs. Tabs: Enable users to change spaces entered for indent tabs.
Changing indent_scale value with the mouse sets Var space_num, Changing indent_scale value with the mouse sets Var space_num,
which invokes var_changed_space_num, which adds an entry to which invokes the default callback to add an entry to
changes. Load_tab_cfg initializes space_num to default. changes. Load_tab_cfg initializes space_num to default.
Widget Structure: (*) widgets bound to self Widget Structure: (*) widgets bound to self
@ -294,10 +268,10 @@ def create_page_font_tab(self):
(*)indent_scale: Scale - space_num (*)indent_scale: Scale - space_num
""" """
parent = self.parent parent = self.parent
self.font_name = StringVar(parent) self.font_name = tracers.add(StringVar(parent), self.var_changed_font)
self.font_size = StringVar(parent) self.font_size = tracers.add(StringVar(parent), self.var_changed_font)
self.font_bold = BooleanVar(parent) self.font_bold = tracers.add(BooleanVar(parent), self.var_changed_font)
self.space_num = IntVar(parent) self.space_num = tracers.add(IntVar(parent), ('main', 'Indent', 'num-spaces'))
# Create widgets: # Create widgets:
# body and body section frames. # body and body section frames.
@ -443,12 +417,6 @@ def load_tab_cfg(self):
'main', 'Indent', 'num-spaces', default=4, type='int') 'main', 'Indent', 'num-spaces', default=4, type='int')
self.space_num.set(space_num) self.space_num.set(space_num)
def var_changed_space_num(self, *params):
"Store change to indentation size."
value = self.space_num.get()
changes.add_option('main', 'Indent', 'num-spaces', value)
def create_page_highlight(self): def create_page_highlight(self):
"""Return frame of widgets for Highlighting tab. """Return frame of widgets for Highlighting tab.
@ -518,12 +486,17 @@ def create_page_highlight(self):
'Shell Stderr Text': ('stderr', '13'), 'Shell Stderr Text': ('stderr', '13'),
} }
parent = self.parent parent = self.parent
self.builtin_theme = StringVar(parent) self.builtin_theme = tracers.add(
self.custom_theme = StringVar(parent) StringVar(parent), self.var_changed_builtin_theme)
self.custom_theme = tracers.add(
StringVar(parent), self.var_changed_custom_theme)
self.fg_bg_toggle = BooleanVar(parent) self.fg_bg_toggle = BooleanVar(parent)
self.color = StringVar(parent) self.color = tracers.add(
self.is_builtin_theme = BooleanVar(parent) StringVar(parent), self.var_changed_color)
self.highlight_target = StringVar(parent) self.is_builtin_theme = tracers.add(
BooleanVar(parent), self.var_changed_is_builtin_theme)
self.highlight_target = tracers.add(
StringVar(parent), self.var_changed_highlight_target)
##widget creation ##widget creation
#body frame #body frame
@ -1062,10 +1035,14 @@ def create_page_keys(self):
button_save_custom_keys: Button button_save_custom_keys: Button
""" """
parent = self.parent parent = self.parent
self.builtin_keys = StringVar(parent) self.builtin_keys = tracers.add(
self.custom_keys = StringVar(parent) StringVar(parent), self.var_changed_builtin_keys)
self.are_keys_builtin = BooleanVar(parent) self.custom_keys = tracers.add(
self.keybinding = StringVar(parent) StringVar(parent), self.var_changed_custom_keys)
self.are_keys_builtin = tracers.add(
BooleanVar(parent), self.var_changed_are_keys_builtin)
self.keybinding = tracers.add(
StringVar(parent), self.var_changed_keybinding)
##widget creation ##widget creation
#body frame #body frame
@ -1169,9 +1146,6 @@ def load_key_cfg(self):
keyset_name = idleConf.CurrentKeys() keyset_name = idleConf.CurrentKeys()
self.load_keys_list(keyset_name) self.load_keys_list(keyset_name)
def var_changed_builtin_keys(self, *params): def var_changed_builtin_keys(self, *params):
"Process selection of builtin key set." "Process selection of builtin key set."
old_keys = ( old_keys = (
@ -1434,7 +1408,7 @@ def create_page_general(self):
set var startup_edit. Radiobuttons save_ask_on and save_auto_on set var startup_edit. Radiobuttons save_ask_on and save_auto_on
set var autosave. Entry boxes win_width_int and win_height_int set var autosave. Entry boxes win_width_int and win_height_int
set var win_width and win_height. Setting var_name invokes the set var win_width and win_height. Setting var_name invokes the
var_changed_var_name callback that adds option to changes. default callback that adds option to changes.
Helplist: load_general_cfg loads list user_helplist with Helplist: load_general_cfg loads list user_helplist with
name, position pairs and copies names to listbox helplist. name, position pairs and copies names to listbox helplist.
@ -1470,10 +1444,14 @@ def create_page_general(self):
scroll_helplist: Scrollbar scroll_helplist: Scrollbar
""" """
parent = self.parent parent = self.parent
self.startup_edit = IntVar(parent) self.startup_edit = tracers.add(
self.autosave = IntVar(parent) IntVar(parent), ('main', 'General', 'editor-on-startup'))
self.win_width = StringVar(parent) self.autosave = tracers.add(
self.win_height = StringVar(parent) IntVar(parent), ('main', 'General', 'autosave'))
self.win_width = tracers.add(
StringVar(parent), ('main', 'EditorWindow', 'width'))
self.win_height = tracers.add(
StringVar(parent), ('main', 'EditorWindow', 'height'))
# Create widgets: # Create widgets:
# body. # body.
@ -1873,9 +1851,9 @@ def add(self, var, callback):
Args: Args:
var: Tk variable instance. var: Tk variable instance.
callback: Function to be used as a callback or callback: Either function name to be used as a callback
a tuple with IdleConf values for default or a tuple with IdleConf config-type, section, and
callback. option names used in the default callback.
Return: Return:
Tk variable instance. Tk variable instance.
@ -1908,6 +1886,8 @@ def detach(self):
self.untraced.append((var, callback)) self.untraced.append((var, callback))
tracers = VarTrace()
help_common = '''\ help_common = '''\
When you click either the Apply or Ok buttons, settings in this When you click either the Apply or Ok buttons, settings in this
dialog that are different from IDLE's default are saved in dialog that are different from IDLE's default are saved in

View file

@ -0,0 +1,5 @@
IDLE -- Factor a VarTrace class out of ConfigDialog.
Instance tracers manages pairs consisting of a tk variable and a
callback function. When tracing is turned on, setting the variable
calls the function. Test coverage for the new class is 100%.