[3.6] bpo-30853: IDLE: Convert font and general vars to use VarTrace (GH-2914) (#2935)

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%.
(cherry picked from commit 5b59154)
This commit is contained in:
Terry Jan Reedy 2017-07-28 15:42:43 -04:00 committed by GitHub
parent 2cbb6733bf
commit 02f88d2a41
2 changed files with 47 additions and 62 deletions

View file

@ -30,6 +30,7 @@ from idlelib.textview import view_text
changes = ConfigChanges() changes = ConfigChanges()
class ConfigDialog(Toplevel): class ConfigDialog(Toplevel):
"""Config dialog for IDLE. """Config dialog for IDLE.
""" """
@ -75,13 +76,15 @@ class ConfigDialog(Toplevel):
# 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 @@ class ConfigDialog(Toplevel):
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 @@ class ConfigDialog(Toplevel):
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 @@ class ConfigDialog(Toplevel):
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 @@ class ConfigDialog(Toplevel):
(*)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 @@ class ConfigDialog(Toplevel):
'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 @@ class ConfigDialog(Toplevel):
'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 @@ class ConfigDialog(Toplevel):
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 @@ class ConfigDialog(Toplevel):
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 @@ class ConfigDialog(Toplevel):
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 @@ class ConfigDialog(Toplevel):
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 @@ class VarTrace:
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 @@ class VarTrace:
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%.