Commit b1660800 authored by Terry Jan Reedy's avatar Terry Jan Reedy Committed by GitHub

bpo-31060: IDLE: Finish regrouping ConfigDialog methods (#2908)

Finish resorting the 72 ConfigDialog methods into 7 groups that represent the dialog, action buttons, and font, highlight, keys, general, and extension pages.  This will help with continuing to add tests and improve the pages. It will enable splitting ConfigDialog into 6 or 7 more comprehensible classes. 
parent 12953ffe
...@@ -30,7 +30,6 @@ from idlelib.textview import view_text ...@@ -30,7 +30,6 @@ from idlelib.textview import view_text
changes = ConfigChanges() changes = ConfigChanges()
class ConfigDialog(Toplevel): class ConfigDialog(Toplevel):
"""Config dialog for IDLE. """Config dialog for IDLE.
""" """
...@@ -112,6 +111,58 @@ class ConfigDialog(Toplevel): ...@@ -112,6 +111,58 @@ class ConfigDialog(Toplevel):
self.create_page_extensions() self.create_page_extensions()
self.create_action_buttons().pack(side=BOTTOM) self.create_action_buttons().pack(side=BOTTOM)
def load_configs(self):
"""Load configuration for each page.
Load configuration from default and user config files and populate
the widgets on the config dialog pages.
Methods:
load_font_cfg
load_tab_cfg
load_theme_cfg
load_key_cfg
load_general_cfg
"""
self.load_font_cfg()
self.load_tab_cfg()
self.load_theme_cfg()
self.load_key_cfg()
self.load_general_cfg()
# 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):
"Remove callbacks to prevent memory leaks."
for var in (
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.
...@@ -150,6 +201,50 @@ class ConfigDialog(Toplevel): ...@@ -150,6 +201,50 @@ class ConfigDialog(Toplevel):
buttons.pack(side=BOTTOM) buttons.pack(side=BOTTOM)
return outer return outer
def ok(self):
"""Apply config changes, then dismiss dialog.
Methods:
apply
destroy: inherited
"""
self.apply()
self.destroy()
def apply(self):
"""Apply config changes and leave dialog open.
Methods:
deactivate_current_config
save_all_changed_extensions
activate_config_changes
"""
self.deactivate_current_config()
changes.save_all()
self.save_all_changed_extensions()
self.activate_config_changes()
def cancel(self):
"""Dismiss config dialog.
Methods:
destroy: inherited
"""
self.destroy()
def help(self):
"""Create textview for config dialog help.
Attrbutes accessed:
tab_pages
Methods:
view_text: Method from textview module.
"""
page = self.tab_pages._current_page
view_text(self, title='Help for IDLE preferences',
text=help_common+help_pages.get(page, ''))
def create_page_font_tab(self): def create_page_font_tab(self):
"""Return frame of widgets for Font/Tabs tab. """Return frame of widgets for Font/Tabs tab.
...@@ -299,16 +394,6 @@ class ConfigDialog(Toplevel): ...@@ -299,16 +394,6 @@ class ConfigDialog(Toplevel):
# Set font weight. # Set font weight.
self.font_bold.set(font_bold) self.font_bold.set(font_bold)
def on_fontlist_select(self, event):
"""Handle selecting a font from the list.
Event can result from either mouse click or Up or Down key.
Set font_name and example displays to selection.
"""
font = self.fontlist.get(
ACTIVE if event.type.name == 'KeyRelease' else ANCHOR)
self.font_name.set(font.lower())
def var_changed_font(self, *params): def var_changed_font(self, *params):
"""Store changes to font attributes. """Store changes to font attributes.
...@@ -324,6 +409,16 @@ class ConfigDialog(Toplevel): ...@@ -324,6 +409,16 @@ class ConfigDialog(Toplevel):
changes.add_option('main', 'EditorWindow', 'font-bold', value) changes.add_option('main', 'EditorWindow', 'font-bold', value)
self.set_samples() self.set_samples()
def on_fontlist_select(self, event):
"""Handle selecting a font from the list.
Event can result from either mouse click or Up or Down key.
Set font_name and example displays to selection.
"""
font = self.fontlist.get(
ACTIVE if event.type.name == 'KeyRelease' else ANCHOR)
self.font_name.set(font.lower())
def set_samples(self, event=None): def set_samples(self, event=None):
"""Update update both screen samples with the font settings. """Update update both screen samples with the font settings.
...@@ -531,409 +626,60 @@ class ConfigDialog(Toplevel): ...@@ -531,409 +626,60 @@ class ConfigDialog(Toplevel):
self.new_custom_theme.pack(side=TOP, fill=X, pady=5) self.new_custom_theme.pack(side=TOP, fill=X, pady=5)
return frame return frame
def create_page_keys(self): def load_theme_cfg(self):
"""Return frame of widgets for Keys tab. """Load current configuration settings for the theme options.
Tk Variables: Based on the is_builtin_theme toggle, the theme is set as
builtin_keys: Menu variable for built-in keybindings. either builtin or custom and the initial widget values
custom_keys: Menu variable for custom keybindings. reflect the current settings from idleConf.
are_keys_builtin: Selector for built-in or custom keybindings.
keybinding: Action/key bindings.
Methods: Attributes updated:
load_key_config: Set table. is_builtin_theme: Set from idleConf.
load_keys_list: Reload active set. opt_menu_theme_builtin: List of default themes from idleConf.
keybinding_selected: Bound to list_bindings button release. opt_menu_theme_custom: List of custom themes from idleConf.
get_new_keys: Command for button_new_keys. radio_theme_custom: Disabled if there are no custom themes.
get_new_keys_name: Call popup. custom_theme: Message with additional information.
create_new_key_set: Combine active keyset and changes. opt_menu_highlight_target: Create menu from self.theme_elements.
set_keys_type: Command for are_keys_builtin.
delete_custom_keys: Command for button_delete_custom_keys.
save_as_new_key_set: Command for button_save_custom_keys.
save_new_key_set: Save to idleConf.userCfg['keys'] (is function).
deactivate_current_config: Remove keys bindings in editors.
Widget Structure: (*) widgets bound to self Methods:
frame set_theme_type
frame_custom: LabelFrame paint_theme_sample
frame_target: Frame set_highlight_target
target_title: Label
scroll_target_y: Scrollbar
scroll_target_x: Scrollbar
(*)list_bindings: ListBox
(*)button_new_keys: Button
frame_key_sets: LabelFrame
frames[0]: Frame
(*)radio_keys_builtin: Radiobutton - are_keys_builtin
(*)radio_keys_custom: Radiobutton - are_keys_builtin
(*)opt_menu_keys_builtin: DynOptionMenu - builtin_keys
(*)opt_menu_keys_custom: DynOptionMenu - custom_keys
(*)new_custom_keys: Label
frames[1]: Frame
(*)button_delete_custom_keys: Button
button_save_custom_keys: Button
""" """
parent = self.parent # Set current theme type radiobutton.
self.builtin_keys = StringVar(parent) self.is_builtin_theme.set(idleConf.GetOption(
self.custom_keys = StringVar(parent) 'main', 'Theme', 'default', type='bool', default=1))
self.are_keys_builtin = BooleanVar(parent) # Set current theme.
self.keybinding = StringVar(parent) current_option = idleConf.CurrentTheme()
# Load available theme option menus.
if self.is_builtin_theme.get(): # Default theme selected.
item_list = idleConf.GetSectionList('default', 'highlight')
item_list.sort()
self.opt_menu_theme_builtin.SetMenu(item_list, current_option)
item_list = idleConf.GetSectionList('user', 'highlight')
item_list.sort()
if not item_list:
self.radio_theme_custom['state'] = DISABLED
self.custom_theme.set('- no custom themes -')
else:
self.opt_menu_theme_custom.SetMenu(item_list, item_list[0])
else: # User theme selected.
item_list = idleConf.GetSectionList('user', 'highlight')
item_list.sort()
self.opt_menu_theme_custom.SetMenu(item_list, current_option)
item_list = idleConf.GetSectionList('default', 'highlight')
item_list.sort()
self.opt_menu_theme_builtin.SetMenu(item_list, 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.opt_menu_highlight_target.SetMenu(theme_names, theme_names[0])
self.paint_theme_sample()
self.set_highlight_target()
##widget creation def var_changed_builtin_theme(self, *params):
#body frame """Process new builtin theme selection.
frame = self.tab_pages.pages['Keys'].frame
#body section frames
frame_custom = LabelFrame(
frame, borderwidth=2, relief=GROOVE,
text=' Custom Key Bindings ')
frame_key_sets = LabelFrame(
frame, borderwidth=2, relief=GROOVE, text=' Key Set ')
#frame_custom
frame_target = Frame(frame_custom)
target_title = Label(frame_target, text='Action - Key(s)')
scroll_target_y = Scrollbar(frame_target)
scroll_target_x = Scrollbar(frame_target, orient=HORIZONTAL)
self.list_bindings = Listbox(
frame_target, takefocus=FALSE, exportselection=FALSE)
self.list_bindings.bind('<ButtonRelease-1>', self.keybinding_selected)
scroll_target_y.config(command=self.list_bindings.yview)
scroll_target_x.config(command=self.list_bindings.xview)
self.list_bindings.config(yscrollcommand=scroll_target_y.set)
self.list_bindings.config(xscrollcommand=scroll_target_x.set)
self.button_new_keys = Button(
frame_custom, text='Get New Keys for Selection',
command=self.get_new_keys, state=DISABLED)
#frame_key_sets
frames = [Frame(frame_key_sets, padx=2, pady=2, borderwidth=0)
for i in range(2)]
self.radio_keys_builtin = Radiobutton(
frames[0], variable=self.are_keys_builtin, value=1,
command=self.set_keys_type, text='Use a Built-in Key Set')
self.radio_keys_custom = Radiobutton(
frames[0], variable=self.are_keys_builtin, value=0,
command=self.set_keys_type, text='Use a Custom Key Set')
self.opt_menu_keys_builtin = DynOptionMenu(
frames[0], self.builtin_keys, None, command=None)
self.opt_menu_keys_custom = DynOptionMenu(
frames[0], self.custom_keys, None, command=None)
self.button_delete_custom_keys = Button(
frames[1], text='Delete Custom Key Set',
command=self.delete_custom_keys)
button_save_custom_keys = Button(
frames[1], text='Save as New Custom Key Set',
command=self.save_as_new_key_set)
self.new_custom_keys = Label(frames[0], bd=2)
##widget packing
#body
frame_custom.pack(side=BOTTOM, padx=5, pady=5, expand=TRUE, fill=BOTH)
frame_key_sets.pack(side=BOTTOM, padx=5, pady=5, fill=BOTH)
#frame_custom
self.button_new_keys.pack(side=BOTTOM, fill=X, padx=5, pady=5)
frame_target.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
#frame target
frame_target.columnconfigure(0, weight=1)
frame_target.rowconfigure(1, weight=1)
target_title.grid(row=0, column=0, columnspan=2, sticky=W)
self.list_bindings.grid(row=1, column=0, sticky=NSEW)
scroll_target_y.grid(row=1, column=1, sticky=NS)
scroll_target_x.grid(row=2, column=0, sticky=EW)
#frame_key_sets
self.radio_keys_builtin.grid(row=0, column=0, sticky=W+NS)
self.radio_keys_custom.grid(row=1, column=0, sticky=W+NS)
self.opt_menu_keys_builtin.grid(row=0, column=1, sticky=NSEW)
self.opt_menu_keys_custom.grid(row=1, column=1, sticky=NSEW)
self.new_custom_keys.grid(row=0, column=2, sticky=NSEW, padx=5, pady=5)
self.button_delete_custom_keys.pack(side=LEFT, fill=X, expand=True, padx=2)
button_save_custom_keys.pack(side=LEFT, fill=X, expand=True, padx=2)
frames[0].pack(side=TOP, fill=BOTH, expand=True)
frames[1].pack(side=TOP, fill=X, expand=True, pady=2)
return frame
def create_page_general(self):
"""Return frame of widgets for General tab.
Enable users to provisionally change general options. Function
load_general_cfg intializes tk variables and helplist using
idleConf. Radiobuttons startup_shell_on and startup_editor_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 win_width and win_height. Setting var_name invokes the
var_changed_var_name callback that adds option to changes.
Helplist: load_general_cfg loads list user_helplist with
name, position pairs and copies names to listbox helplist.
Clicking a name invokes help_source selected. Clicking
button_helplist_name invokes helplist_item_name, which also
changes user_helplist. These functions all call
set_add_delete_state. All but load call update_help_changes to
rewrite changes['main']['HelpFiles'].
Widget Structure: (*) widgets bound to self
frame
frame_run: LabelFrame
startup_title: Label
(*)startup_editor_on: Radiobutton - startup_edit
(*)startup_shell_on: Radiobutton - startup_edit
frame_save: LabelFrame
run_save_title: Label
(*)save_ask_on: Radiobutton - autosave
(*)save_auto_on: Radiobutton - autosave
frame_win_size: LabelFrame
win_size_title: Label
win_width_title: Label
(*)win_width_int: Entry - win_width
win_height_title: Label
(*)win_height_int: Entry - win_height
frame_help: LabelFrame
frame_helplist: Frame
frame_helplist_buttons: Frame
(*)button_helplist_edit
(*)button_helplist_add
(*)button_helplist_remove
(*)helplist: ListBox
scroll_helplist: Scrollbar
"""
parent = self.parent
self.startup_edit = IntVar(parent)
self.autosave = IntVar(parent)
self.win_width = StringVar(parent)
self.win_height = StringVar(parent)
# Create widgets:
# body.
frame = self.tab_pages.pages['General'].frame
# body section frames.
frame_run = LabelFrame(frame, borderwidth=2, relief=GROOVE,
text=' Startup Preferences ')
frame_save = LabelFrame(frame, borderwidth=2, relief=GROOVE,
text=' autosave Preferences ')
frame_win_size = Frame(frame, borderwidth=2, relief=GROOVE)
frame_help = LabelFrame(frame, borderwidth=2, relief=GROOVE,
text=' Additional Help Sources ')
# frame_run.
startup_title = Label(frame_run, text='At Startup')
self.startup_editor_on = Radiobutton(
frame_run, variable=self.startup_edit, value=1,
text="Open Edit Window")
self.startup_shell_on = Radiobutton(
frame_run, variable=self.startup_edit, value=0,
text='Open Shell Window')
# frame_save.
run_save_title = Label(frame_save, text='At Start of Run (F5) ')
self.save_ask_on = Radiobutton(
frame_save, variable=self.autosave, value=0,
text="Prompt to Save")
self.save_auto_on = Radiobutton(
frame_save, variable=self.autosave, value=1,
text='No Prompt')
# frame_win_size.
win_size_title = Label(
frame_win_size, text='Initial Window Size (in characters)')
win_width_title = Label(frame_win_size, text='Width')
self.win_width_int = Entry(
frame_win_size, textvariable=self.win_width, width=3)
win_height_title = Label(frame_win_size, text='Height')
self.win_height_int = Entry(
frame_win_size, textvariable=self.win_height, width=3)
# frame_help.
frame_helplist = Frame(frame_help)
frame_helplist_buttons = Frame(frame_helplist)
self.helplist = Listbox(
frame_helplist, height=5, takefocus=FALSE,
exportselection=FALSE)
scroll_helplist = Scrollbar(frame_helplist)
scroll_helplist['command'] = self.helplist.yview
self.helplist['yscrollcommand'] = scroll_helplist.set
self.helplist.bind('<ButtonRelease-1>', self.help_source_selected)
self.button_helplist_edit = Button(
frame_helplist_buttons, text='Edit', state=DISABLED,
width=8, command=self.helplist_item_edit)
self.button_helplist_add = Button(
frame_helplist_buttons, text='Add',
width=8, command=self.helplist_item_add)
self.button_helplist_remove = Button(
frame_helplist_buttons, text='Remove', state=DISABLED,
width=8, command=self.helplist_item_remove)
# Pack widgets:
# body.
frame_run.pack(side=TOP, padx=5, pady=5, fill=X)
frame_save.pack(side=TOP, padx=5, pady=5, fill=X)
frame_win_size.pack(side=TOP, padx=5, pady=5, fill=X)
frame_help.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
# frame_run.
startup_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
self.startup_shell_on.pack(side=RIGHT, anchor=W, padx=5, pady=5)
self.startup_editor_on.pack(side=RIGHT, anchor=W, padx=5, pady=5)
# frame_save.
run_save_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
self.save_auto_on.pack(side=RIGHT, anchor=W, padx=5, pady=5)
self.save_ask_on.pack(side=RIGHT, anchor=W, padx=5, pady=5)
# frame_win_size.
win_size_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
self.win_height_int.pack(side=RIGHT, anchor=E, padx=10, pady=5)
win_height_title.pack(side=RIGHT, anchor=E, pady=5)
self.win_width_int.pack(side=RIGHT, anchor=E, padx=10, pady=5)
win_width_title.pack(side=RIGHT, anchor=E, pady=5)
# frame_help.
frame_helplist_buttons.pack(side=RIGHT, padx=5, pady=5, fill=Y)
frame_helplist.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
scroll_helplist.pack(side=RIGHT, anchor=W, fill=Y)
self.helplist.pack(side=LEFT, anchor=E, expand=TRUE, fill=BOTH)
self.button_helplist_edit.pack(side=TOP, anchor=W, pady=5)
self.button_helplist_add.pack(side=TOP, anchor=W)
self.button_helplist_remove.pack(side=TOP, anchor=W, pady=5)
return frame
def load_general_cfg(self):
"Load current configuration settings for the general options."
# Set startup state.
self.startup_edit.set(idleConf.GetOption(
'main', 'General', 'editor-on-startup', default=0, type='bool'))
# Set autosave state.
self.autosave.set(idleConf.GetOption(
'main', 'General', 'autosave', default=0, type='bool'))
# Set initial window size.
self.win_width.set(idleConf.GetOption(
'main', 'EditorWindow', 'width', type='int'))
self.win_height.set(idleConf.GetOption(
'main', 'EditorWindow', 'height', type='int'))
# Set additional help sources.
self.user_helplist = idleConf.GetAllExtraHelpSourcesList()
self.helplist.delete(0, 'end')
for help_item in self.user_helplist:
self.helplist.insert(END, help_item[0])
self.set_add_delete_state()
def var_changed_startup_edit(self, *params):
"Store change to toggle for starting IDLE in the editor or shell."
value = self.startup_edit.get()
changes.add_option('main', 'General', 'editor-on-startup', value)
def var_changed_autosave(self, *params):
"Store change to autosave."
value = self.autosave.get()
changes.add_option('main', 'General', 'autosave', value)
def var_changed_win_width(self, *params):
"Store change to window width."
value = self.win_width.get()
changes.add_option('main', 'EditorWindow', 'width', value)
def var_changed_win_height(self, *params):
"Store change to window height."
value = self.win_height.get()
changes.add_option('main', 'EditorWindow', 'height', value)
def help_source_selected(self, event):
"Handle event for selecting additional help."
self.set_add_delete_state()
def set_add_delete_state(self):
"Toggle the state for the help list buttons based on list entries."
if self.helplist.size() < 1: # No entries in list.
self.button_helplist_edit['state'] = DISABLED
self.button_helplist_remove['state'] = DISABLED
else: # Some entries.
if self.helplist.curselection(): # There currently is a selection.
self.button_helplist_edit['state'] = NORMAL
self.button_helplist_remove['state'] = NORMAL
else: # There currently is not a selection.
self.button_helplist_edit['state'] = DISABLED
self.button_helplist_remove['state'] = DISABLED
def helplist_item_add(self):
"""Handle add button for the help list.
Query for name and location of new help sources and add
them to the list.
"""
help_source = HelpSource(self, 'New Help Source').result
if help_source:
self.user_helplist.append(help_source)
self.helplist.insert(END, help_source[0])
self.update_help_changes()
def helplist_item_edit(self):
"""Handle edit button for the help list.
Query with existing help source information and update
config if the values are changed.
"""
item_index = self.helplist.index(ANCHOR)
help_source = self.user_helplist[item_index]
new_help_source = HelpSource(
self, 'Edit Help Source',
menuitem=help_source[0],
filepath=help_source[1],
).result
if new_help_source and new_help_source != help_source:
self.user_helplist[item_index] = new_help_source
self.helplist.delete(item_index)
self.helplist.insert(item_index, new_help_source[0])
self.update_help_changes()
self.set_add_delete_state() # Selected will be un-selected
def helplist_item_remove(self):
"""Handle remove button for the help list.
Delete the help list item from config.
"""
item_index = self.helplist.index(ANCHOR)
del(self.user_helplist[item_index])
self.helplist.delete(item_index)
self.update_help_changes()
self.set_add_delete_state()
def update_help_changes(self):
"Clear and rebuild the HelpFiles section in changes"
changes['main']['HelpFiles'] = {}
for num in range(1, len(self.user_helplist) + 1):
changes.add_option(
'main', 'HelpFiles', str(num),
';'.join(self.user_helplist[num-1][:2]))
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):
"Remove callbacks to prevent memory leaks."
for var in (
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 var_changed_color(self, *params):
"Process change to color choice."
self.on_new_color_set()
def var_changed_builtin_theme(self, *params):
"""Process new builtin theme selection.
Add the changed theme's name to the changed_items and recreate Add the changed theme's name to the changed_items and recreate
the sample with the values from the selected theme. the sample with the values from the selected theme.
...@@ -966,68 +712,23 @@ class ConfigDialog(Toplevel): ...@@ -966,68 +712,23 @@ class ConfigDialog(Toplevel):
def var_changed_is_builtin_theme(self, *params): def var_changed_is_builtin_theme(self, *params):
"""Process toggle between builtin and custom theme. """Process toggle between builtin and custom theme.
Update the default toggle value and apply the newly Update the default toggle value and apply the newly
selected theme type. selected theme type.
""" """
value = self.is_builtin_theme.get() value = self.is_builtin_theme.get()
changes.add_option('main', 'Theme', 'default', value) changes.add_option('main', 'Theme', 'default', value)
if value:
self.var_changed_builtin_theme()
else:
self.var_changed_custom_theme()
def var_changed_highlight_target(self, *params):
"Process selection of new target tag for highlighting."
self.set_highlight_target()
def var_changed_keybinding(self, *params):
"Store change to a keybinding."
value = self.keybinding.get()
key_set = self.custom_keys.get()
event = self.list_bindings.get(ANCHOR).split()[0]
if idleConf.IsCoreBinding(event):
changes.add_option('keys', key_set, event, value)
else: # Event is an extension binding.
ext_name = idleConf.GetExtnNameForEvent(event)
ext_keybind_section = ext_name + '_cfgBindings'
changes.add_option('extensions', ext_keybind_section, event, value)
def var_changed_builtin_keys(self, *params):
"Process selection of builtin key set."
old_keys = (
'IDLE Classic Windows',
'IDLE Classic Unix',
'IDLE Classic Mac',
'IDLE Classic OSX',
)
value = self.builtin_keys.get()
if value not in old_keys:
if idleConf.GetOption('main', 'Keys', 'name') not in old_keys:
changes.add_option('main', 'Keys', 'name', old_keys[0])
changes.add_option('main', 'Keys', 'name2', value)
self.new_custom_keys.config(text='New key set, see Help',
fg='#500000')
else:
changes.add_option('main', 'Keys', 'name', value)
changes.add_option('main', 'Keys', 'name2', '')
self.new_custom_keys.config(text='', fg='black')
self.load_keys_list(value)
def var_changed_custom_keys(self, *params):
"Process selection of custom key set."
value = self.custom_keys.get()
if value != '- no custom keys -':
changes.add_option('main', 'Keys', 'name', value)
self.load_keys_list(value)
def var_changed_are_keys_builtin(self, *params):
"Process toggle between builtin key set and custom key set."
value = self.are_keys_builtin.get()
changes.add_option('main', 'Keys', 'default', value)
if value: if value:
self.var_changed_builtin_keys() self.var_changed_builtin_theme()
else: else:
self.var_changed_custom_keys() self.var_changed_custom_theme()
def var_changed_color(self, *params):
"Process change to color choice."
self.on_new_color_set()
def var_changed_highlight_target(self, *params):
"Process selection of new target tag for highlighting."
self.set_highlight_target()
def set_theme_type(self): def set_theme_type(self):
"""Set available screen options based on builtin or custom theme. """Set available screen options based on builtin or custom theme.
...@@ -1057,170 +758,218 @@ class ConfigDialog(Toplevel): ...@@ -1057,170 +758,218 @@ class ConfigDialog(Toplevel):
self.opt_menu_theme_custom['state'] = NORMAL self.opt_menu_theme_custom['state'] = NORMAL
self.button_delete_custom_theme['state'] = NORMAL self.button_delete_custom_theme['state'] = NORMAL
def set_keys_type(self): def get_color(self):
"Set available screen options based on builtin or custom key set." """Handle button to select a new color for the target tag.
if self.are_keys_builtin.get():
self.opt_menu_keys_builtin['state'] = NORMAL
self.opt_menu_keys_custom['state'] = DISABLED
self.button_delete_custom_keys['state'] = DISABLED
else:
self.opt_menu_keys_builtin['state'] = DISABLED
self.radio_keys_custom['state'] = NORMAL
self.opt_menu_keys_custom['state'] = NORMAL
self.button_delete_custom_keys['state'] = NORMAL
def get_new_keys(self): If a new color is selected while using a builtin theme, a
"""Handle event to change key binding for selected line. name must be supplied to create a custom theme.
A selection of a key/binding in the list of current Attributes accessed:
bindings pops up a dialog to enter a new binding. If highlight_target
the current key set is builtin and a binding has frame_color_set
changed, then a name for a custom key set needs to be is_builtin_theme
entered for the change to be applied.
Attributes updated:
color
Methods:
get_new_theme_name
create_new_theme
""" """
list_index = self.list_bindings.index(ANCHOR) target = self.highlight_target.get()
binding = self.list_bindings.get(list_index) prev_color = self.frame_color_set.cget('bg')
bind_name = binding.split()[0] rgbTuplet, color_string = tkColorChooser.askcolor(
if self.are_keys_builtin.get(): parent=self, title='Pick new color for : '+target,
current_key_set_name = self.builtin_keys.get() initialcolor=prev_color)
else: if color_string and (color_string != prev_color):
current_key_set_name = self.custom_keys.get() # User didn't cancel and they chose a new color.
current_bindings = idleConf.GetCurrentKeySet() if self.is_builtin_theme.get(): # Current theme is a built-in.
if current_key_set_name in changes['keys']: # unsaved changes message = ('Your changes will be saved as a new Custom Theme. '
key_set_changes = changes['keys'][current_key_set_name] 'Enter a name for your new Custom Theme below.')
for event in key_set_changes: new_theme = self.get_new_theme_name(message)
current_bindings[event] = key_set_changes[event].split() if not new_theme: # User cancelled custom theme creation.
current_key_sequences = list(current_bindings.values())
new_keys = GetKeysDialog(self, 'Get New Keys', bind_name,
current_key_sequences).result
if new_keys:
if self.are_keys_builtin.get(): # Current key set is a built-in.
message = ('Your changes will be saved as a new Custom Key Set.'
' Enter a name for your new Custom Key Set below.')
new_keyset = self.get_new_keys_name(message)
if not new_keyset: # User cancelled custom key set creation.
self.list_bindings.select_set(list_index)
self.list_bindings.select_anchor(list_index)
return return
else: # Create new custom key set based on previously active key set. else: # Create new custom theme based on previously active theme.
self.create_new_key_set(new_keyset) self.create_new_theme(new_theme)
self.list_bindings.delete(list_index) self.color.set(color_string)
self.list_bindings.insert(list_index, bind_name+' - '+new_keys) else: # Current theme is user defined.
self.list_bindings.select_set(list_index) self.color.set(color_string)
self.list_bindings.select_anchor(list_index)
self.keybinding.set(new_keys)
else:
self.list_bindings.select_set(list_index)
self.list_bindings.select_anchor(list_index)
def get_new_keys_name(self, message): def on_new_color_set(self):
"Return new key set name from query popup." "Display sample of new color selection on the dialog."
used_names = (idleConf.GetSectionList('user', 'keys') + new_color=self.color.get()
idleConf.GetSectionList('default', 'keys')) self.frame_color_set.config(bg=new_color) # Set sample.
new_keyset = SectionName( plane ='foreground' if self.fg_bg_toggle.get() else 'background'
self, 'New Custom Key Set', message, used_names).result sample_element = self.theme_elements[self.highlight_target.get()][0]
return new_keyset self.highlight_sample.tag_config(sample_element, **{plane:new_color})
theme = self.custom_theme.get()
theme_element = sample_element + '-' + plane
changes.add_option('highlight', theme, theme_element, new_color)
def save_as_new_key_set(self): def get_new_theme_name(self, message):
"Prompt for name of new key set and save changes using that name." "Return name of new theme from query popup."
new_keys_name = self.get_new_keys_name('New Key Set Name:') used_names = (idleConf.GetSectionList('user', 'highlight') +
if new_keys_name: idleConf.GetSectionList('default', 'highlight'))
self.create_new_key_set(new_keys_name) new_theme = SectionName(
self, 'New Custom Theme', message, used_names).result
return new_theme
def keybinding_selected(self, event): def save_as_new_theme(self):
"Activate button to assign new keys to selected action." """Prompt for new theme name and create the theme.
self.button_new_keys['state'] = NORMAL
def create_new_key_set(self, new_key_set_name): Methods:
"""Create a new custom key set with the given name. get_new_theme_name
create_new_theme
"""
new_theme_name = self.get_new_theme_name('New Theme Name:')
if new_theme_name:
self.create_new_theme(new_theme_name)
Create the new key set based on the previously active set def create_new_theme(self, new_theme_name):
"""Create a new custom theme with the given name.
Create the new theme based on the previously active theme
with the current changes applied. Once it is saved, then with the current changes applied. Once it is saved, then
activate the new key set. activate the new theme.
Attributes accessed:
builtin_theme
custom_theme
Attributes updated:
opt_menu_theme_custom
is_builtin_theme
Method:
save_new_theme
set_theme_type
""" """
if self.are_keys_builtin.get(): if self.is_builtin_theme.get():
prev_key_set_name = self.builtin_keys.get() theme_type = 'default'
theme_name = self.builtin_theme.get()
else: else:
prev_key_set_name = self.custom_keys.get() theme_type = 'user'
prev_keys = idleConf.GetCoreKeys(prev_key_set_name) theme_name = self.custom_theme.get()
new_keys = {} new_theme = idleConf.GetThemeDict(theme_type, theme_name)
for event in prev_keys: # Add key set to changed items. # Apply any of the old theme's unsaved changes to the new theme.
event_name = event[2:-2] # Trim off the angle brackets. if theme_name in changes['highlight']:
binding = ' '.join(prev_keys[event]) theme_changes = changes['highlight'][theme_name]
new_keys[event_name] = binding for element in theme_changes:
# Handle any unsaved changes to prev key set. new_theme[element] = theme_changes[element]
if prev_key_set_name in changes['keys']: # Save the new theme.
key_set_changes = changes['keys'][prev_key_set_name] self.save_new_theme(new_theme_name, new_theme)
for event in key_set_changes: # Change GUI over to the new theme.
new_keys[event] = key_set_changes[event] custom_theme_list = idleConf.GetSectionList('user', 'highlight')
# Save the new key set. custom_theme_list.sort()
self.save_new_key_set(new_key_set_name, new_keys) self.opt_menu_theme_custom.SetMenu(custom_theme_list, new_theme_name)
# Change GUI over to the new key set. self.is_builtin_theme.set(0)
custom_key_list = idleConf.GetSectionList('user', 'keys') self.set_theme_type()
custom_key_list.sort()
self.opt_menu_keys_custom.SetMenu(custom_key_list, new_key_set_name) def set_highlight_target(self):
self.are_keys_builtin.set(0) """Set fg/bg toggle and color based on highlight tag target.
self.set_keys_type()
Instance variables accessed:
highlight_target
Attributes updated:
radio_fg
radio_bg
fg_bg_toggle
Methods:
set_color_sample
Called from:
var_changed_highlight_target
load_theme_cfg
"""
if self.highlight_target.get() == 'Cursor': # bg not possible
self.radio_fg['state'] = DISABLED
self.radio_bg['state'] = DISABLED
self.fg_bg_toggle.set(1)
else: # Both fg and bg can be set.
self.radio_fg['state'] = NORMAL
self.radio_bg['state'] = NORMAL
self.fg_bg_toggle.set(1)
self.set_color_sample()
def set_color_sample_binding(self, *args):
"""Change color sample based on foreground/background toggle.
Methods:
set_color_sample
"""
self.set_color_sample()
def set_color_sample(self):
"""Set the color of the frame background to reflect the selected target.
Instance variables accessed:
theme_elements
highlight_target
fg_bg_toggle
highlight_sample
Attributes updated:
frame_color_set
"""
# Set the color sample area.
tag = self.theme_elements[self.highlight_target.get()][0]
plane = 'foreground' if self.fg_bg_toggle.get() else 'background'
color = self.highlight_sample.tag_cget(tag, plane)
self.frame_color_set.config(bg=color)
def load_keys_list(self, keyset_name): def paint_theme_sample(self):
"""Reload the list of action/key binding pairs for the active key set. """Apply the theme colors to each element tag in the sample text.
An action/key binding can be selected to change the key binding. Instance attributes accessed:
theme_elements
is_builtin_theme
builtin_theme
custom_theme
Attributes updated:
highlight_sample: Set the tag elements to the theme.
Methods:
set_color_sample
Called from:
var_changed_builtin_theme
var_changed_custom_theme
load_theme_cfg
""" """
reselect = 0 if self.is_builtin_theme.get(): # Default theme
if self.list_bindings.curselection(): theme = self.builtin_theme.get()
reselect = 1 else: # User theme
list_index = self.list_bindings.index(ANCHOR) theme = self.custom_theme.get()
keyset = idleConf.GetKeySet(keyset_name) for element_title in self.theme_elements:
bind_names = list(keyset.keys()) element = self.theme_elements[element_title][0]
bind_names.sort() colors = idleConf.GetHighlight(theme, element)
self.list_bindings.delete(0, END) if element == 'cursor': # Cursor sample needs special painting.
for bind_name in bind_names: colors['background'] = idleConf.GetHighlight(
key = ' '.join(keyset[bind_name]) theme, 'normal', fgBg='bg')
bind_name = bind_name[2:-2] # Trim off the angle brackets. # Handle any unsaved changes to this theme.
if keyset_name in changes['keys']: if theme in changes['highlight']:
# Handle any unsaved changes to this key set. theme_dict = changes['highlight'][theme]
if bind_name in changes['keys'][keyset_name]: if element + '-foreground' in theme_dict:
key = changes['keys'][keyset_name][bind_name] colors['foreground'] = theme_dict[element + '-foreground']
self.list_bindings.insert(END, bind_name+' - '+key) if element + '-background' in theme_dict:
if reselect: colors['background'] = theme_dict[element + '-background']
self.list_bindings.see(list_index) self.highlight_sample.tag_config(element, **colors)
self.list_bindings.select_set(list_index) self.set_color_sample()
self.list_bindings.select_anchor(list_index)
def delete_custom_keys(self): def save_new_theme(self, theme_name, theme):
"""Handle event to delete a custom key set. """Save a newly created theme to idleConf.
Applying the delete deactivates the current configuration and theme_name - string, the name of the new theme
reverts to the default. The custom key set is permanently theme - dictionary containing the new theme
deleted from the config file.
""" """
keyset_name=self.custom_keys.get() if not idleConf.userCfg['highlight'].has_section(theme_name):
delmsg = 'Are you sure you wish to delete the key set %r ?' idleConf.userCfg['highlight'].add_section(theme_name)
if not tkMessageBox.askyesno( for element in theme:
'Delete Key Set', delmsg % keyset_name, parent=self): value = theme[element]
return idleConf.userCfg['highlight'].SetOption(theme_name, element, value)
self.deactivate_current_config()
# Remove key set from changes, config, and file.
changes.delete_section('keys', keyset_name)
# Reload user key set list.
item_list = idleConf.GetSectionList('user', 'keys')
item_list.sort()
if not item_list:
self.radio_keys_custom['state'] = DISABLED
self.opt_menu_keys_custom.SetMenu(item_list, '- no custom keys -')
else:
self.opt_menu_keys_custom.SetMenu(item_list, item_list[0])
# Revert to default key set.
self.are_keys_builtin.set(idleConf.defaultCfg['main']
.Get('Keys', 'default'))
self.builtin_keys.set(idleConf.defaultCfg['main'].Get('Keys', 'name')
or idleConf.default_keys())
# User can't back out of these changes, they must be applied now.
changes.save_all()
self.save_all_changed_extensions()
self.activate_config_changes()
self.set_keys_type()
def delete_custom_theme(self): def delete_custom_theme(self):
"""Handle event to delete custom theme. """Handle event to delete custom theme.
...@@ -1269,403 +1018,658 @@ class ConfigDialog(Toplevel): ...@@ -1269,403 +1018,658 @@ class ConfigDialog(Toplevel):
self.activate_config_changes() self.activate_config_changes()
self.set_theme_type() self.set_theme_type()
def get_color(self):
"""Handle button to select a new color for the target tag.
If a new color is selected while using a builtin theme, a
name must be supplied to create a custom theme.
Attributes accessed: def create_page_keys(self):
highlight_target """Return frame of widgets for Keys tab.
frame_color_set
is_builtin_theme
Attributes updated: Tk Variables:
color builtin_keys: Menu variable for built-in keybindings.
custom_keys: Menu variable for custom keybindings.
are_keys_builtin: Selector for built-in or custom keybindings.
keybinding: Action/key bindings.
Methods: Methods:
get_new_theme_name load_key_config: Set table.
create_new_theme load_keys_list: Reload active set.
keybinding_selected: Bound to list_bindings button release.
get_new_keys: Command for button_new_keys.
get_new_keys_name: Call popup.
create_new_key_set: Combine active keyset and changes.
set_keys_type: Command for are_keys_builtin.
delete_custom_keys: Command for button_delete_custom_keys.
save_as_new_key_set: Command for button_save_custom_keys.
save_new_key_set: Save to idleConf.userCfg['keys'] (is function).
deactivate_current_config: Remove keys bindings in editors.
Widget Structure: (*) widgets bound to self
frame
frame_custom: LabelFrame
frame_target: Frame
target_title: Label
scroll_target_y: Scrollbar
scroll_target_x: Scrollbar
(*)list_bindings: ListBox
(*)button_new_keys: Button
frame_key_sets: LabelFrame
frames[0]: Frame
(*)radio_keys_builtin: Radiobutton - are_keys_builtin
(*)radio_keys_custom: Radiobutton - are_keys_builtin
(*)opt_menu_keys_builtin: DynOptionMenu - builtin_keys
(*)opt_menu_keys_custom: DynOptionMenu - custom_keys
(*)new_custom_keys: Label
frames[1]: Frame
(*)button_delete_custom_keys: Button
button_save_custom_keys: Button
""" """
target = self.highlight_target.get() parent = self.parent
prev_color = self.frame_color_set.cget('bg') self.builtin_keys = StringVar(parent)
rgbTuplet, color_string = tkColorChooser.askcolor( self.custom_keys = StringVar(parent)
parent=self, title='Pick new color for : '+target, self.are_keys_builtin = BooleanVar(parent)
initialcolor=prev_color) self.keybinding = StringVar(parent)
if color_string and (color_string != prev_color):
# User didn't cancel and they chose a new color.
if self.is_builtin_theme.get(): # Current theme is a built-in.
message = ('Your changes will be saved as a new Custom Theme. '
'Enter a name for your new Custom Theme below.')
new_theme = self.get_new_theme_name(message)
if not new_theme: # User cancelled custom theme creation.
return
else: # Create new custom theme based on previously active theme.
self.create_new_theme(new_theme)
self.color.set(color_string)
else: # Current theme is user defined.
self.color.set(color_string)
def on_new_color_set(self): ##widget creation
"Display sample of new color selection on the dialog." #body frame
new_color=self.color.get() frame = self.tab_pages.pages['Keys'].frame
self.frame_color_set.config(bg=new_color) # Set sample. #body section frames
plane ='foreground' if self.fg_bg_toggle.get() else 'background' frame_custom = LabelFrame(
sample_element = self.theme_elements[self.highlight_target.get()][0] frame, borderwidth=2, relief=GROOVE,
self.highlight_sample.tag_config(sample_element, **{plane:new_color}) text=' Custom Key Bindings ')
theme = self.custom_theme.get() frame_key_sets = LabelFrame(
theme_element = sample_element + '-' + plane frame, borderwidth=2, relief=GROOVE, text=' Key Set ')
changes.add_option('highlight', theme, theme_element, new_color) #frame_custom
frame_target = Frame(frame_custom)
target_title = Label(frame_target, text='Action - Key(s)')
scroll_target_y = Scrollbar(frame_target)
scroll_target_x = Scrollbar(frame_target, orient=HORIZONTAL)
self.list_bindings = Listbox(
frame_target, takefocus=FALSE, exportselection=FALSE)
self.list_bindings.bind('<ButtonRelease-1>', self.keybinding_selected)
scroll_target_y.config(command=self.list_bindings.yview)
scroll_target_x.config(command=self.list_bindings.xview)
self.list_bindings.config(yscrollcommand=scroll_target_y.set)
self.list_bindings.config(xscrollcommand=scroll_target_x.set)
self.button_new_keys = Button(
frame_custom, text='Get New Keys for Selection',
command=self.get_new_keys, state=DISABLED)
#frame_key_sets
frames = [Frame(frame_key_sets, padx=2, pady=2, borderwidth=0)
for i in range(2)]
self.radio_keys_builtin = Radiobutton(
frames[0], variable=self.are_keys_builtin, value=1,
command=self.set_keys_type, text='Use a Built-in Key Set')
self.radio_keys_custom = Radiobutton(
frames[0], variable=self.are_keys_builtin, value=0,
command=self.set_keys_type, text='Use a Custom Key Set')
self.opt_menu_keys_builtin = DynOptionMenu(
frames[0], self.builtin_keys, None, command=None)
self.opt_menu_keys_custom = DynOptionMenu(
frames[0], self.custom_keys, None, command=None)
self.button_delete_custom_keys = Button(
frames[1], text='Delete Custom Key Set',
command=self.delete_custom_keys)
button_save_custom_keys = Button(
frames[1], text='Save as New Custom Key Set',
command=self.save_as_new_key_set)
self.new_custom_keys = Label(frames[0], bd=2)
def get_new_theme_name(self, message): ##widget packing
"Return name of new theme from query popup." #body
used_names = (idleConf.GetSectionList('user', 'highlight') + frame_custom.pack(side=BOTTOM, padx=5, pady=5, expand=TRUE, fill=BOTH)
idleConf.GetSectionList('default', 'highlight')) frame_key_sets.pack(side=BOTTOM, padx=5, pady=5, fill=BOTH)
new_theme = SectionName( #frame_custom
self, 'New Custom Theme', message, used_names).result self.button_new_keys.pack(side=BOTTOM, fill=X, padx=5, pady=5)
return new_theme frame_target.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
#frame target
frame_target.columnconfigure(0, weight=1)
frame_target.rowconfigure(1, weight=1)
target_title.grid(row=0, column=0, columnspan=2, sticky=W)
self.list_bindings.grid(row=1, column=0, sticky=NSEW)
scroll_target_y.grid(row=1, column=1, sticky=NS)
scroll_target_x.grid(row=2, column=0, sticky=EW)
#frame_key_sets
self.radio_keys_builtin.grid(row=0, column=0, sticky=W+NS)
self.radio_keys_custom.grid(row=1, column=0, sticky=W+NS)
self.opt_menu_keys_builtin.grid(row=0, column=1, sticky=NSEW)
self.opt_menu_keys_custom.grid(row=1, column=1, sticky=NSEW)
self.new_custom_keys.grid(row=0, column=2, sticky=NSEW, padx=5, pady=5)
self.button_delete_custom_keys.pack(side=LEFT, fill=X, expand=True, padx=2)
button_save_custom_keys.pack(side=LEFT, fill=X, expand=True, padx=2)
frames[0].pack(side=TOP, fill=BOTH, expand=True)
frames[1].pack(side=TOP, fill=X, expand=True, pady=2)
return frame
def save_as_new_theme(self): def load_key_cfg(self):
"""Prompt for new theme name and create the theme. "Load current configuration settings for the keybinding options."
# Set current keys type radiobutton.
self.are_keys_builtin.set(idleConf.GetOption(
'main', 'Keys', 'default', type='bool', default=1))
# Set current keys.
current_option = idleConf.CurrentKeys()
# Load available keyset option menus.
if self.are_keys_builtin.get(): # Default theme selected.
item_list = idleConf.GetSectionList('default', 'keys')
item_list.sort()
self.opt_menu_keys_builtin.SetMenu(item_list, current_option)
item_list = idleConf.GetSectionList('user', 'keys')
item_list.sort()
if not item_list:
self.radio_keys_custom['state'] = DISABLED
self.custom_keys.set('- no custom keys -')
else:
self.opt_menu_keys_custom.SetMenu(item_list, item_list[0])
else: # User key set selected.
item_list = idleConf.GetSectionList('user', 'keys')
item_list.sort()
self.opt_menu_keys_custom.SetMenu(item_list, current_option)
item_list = idleConf.GetSectionList('default', 'keys')
item_list.sort()
self.opt_menu_keys_builtin.SetMenu(item_list, idleConf.default_keys())
self.set_keys_type()
# Load keyset element list.
keyset_name = idleConf.CurrentKeys()
self.load_keys_list(keyset_name)
Methods:
get_new_theme_name
create_new_theme
"""
new_theme_name = self.get_new_theme_name('New Theme Name:')
if new_theme_name:
self.create_new_theme(new_theme_name)
def create_new_theme(self, new_theme_name):
"""Create a new custom theme with the given name.
Create the new theme based on the previously active theme
with the current changes applied. Once it is saved, then
activate the new theme.
Attributes accessed: def var_changed_builtin_keys(self, *params):
builtin_theme "Process selection of builtin key set."
custom_theme old_keys = (
'IDLE Classic Windows',
'IDLE Classic Unix',
'IDLE Classic Mac',
'IDLE Classic OSX',
)
value = self.builtin_keys.get()
if value not in old_keys:
if idleConf.GetOption('main', 'Keys', 'name') not in old_keys:
changes.add_option('main', 'Keys', 'name', old_keys[0])
changes.add_option('main', 'Keys', 'name2', value)
self.new_custom_keys.config(text='New key set, see Help',
fg='#500000')
else:
changes.add_option('main', 'Keys', 'name', value)
changes.add_option('main', 'Keys', 'name2', '')
self.new_custom_keys.config(text='', fg='black')
self.load_keys_list(value)
Attributes updated: def var_changed_custom_keys(self, *params):
opt_menu_theme_custom "Process selection of custom key set."
is_builtin_theme value = self.custom_keys.get()
if value != '- no custom keys -':
changes.add_option('main', 'Keys', 'name', value)
self.load_keys_list(value)
Method: def var_changed_are_keys_builtin(self, *params):
save_new_theme "Process toggle between builtin key set and custom key set."
set_theme_type value = self.are_keys_builtin.get()
""" changes.add_option('main', 'Keys', 'default', value)
if self.is_builtin_theme.get(): if value:
theme_type = 'default' self.var_changed_builtin_keys()
theme_name = self.builtin_theme.get()
else: else:
theme_type = 'user' self.var_changed_custom_keys()
theme_name = self.custom_theme.get()
new_theme = idleConf.GetThemeDict(theme_type, theme_name)
# Apply any of the old theme's unsaved changes to the new theme.
if theme_name in changes['highlight']:
theme_changes = changes['highlight'][theme_name]
for element in theme_changes:
new_theme[element] = theme_changes[element]
# Save the new theme.
self.save_new_theme(new_theme_name, new_theme)
# Change GUI over to the new theme.
custom_theme_list = idleConf.GetSectionList('user', 'highlight')
custom_theme_list.sort()
self.opt_menu_theme_custom.SetMenu(custom_theme_list, new_theme_name)
self.is_builtin_theme.set(0)
self.set_theme_type()
def set_highlight_target(self):
"""Set fg/bg toggle and color based on highlight tag target.
Instance variables accessed: def var_changed_keybinding(self, *params):
highlight_target "Store change to a keybinding."
value = self.keybinding.get()
key_set = self.custom_keys.get()
event = self.list_bindings.get(ANCHOR).split()[0]
if idleConf.IsCoreBinding(event):
changes.add_option('keys', key_set, event, value)
else: # Event is an extension binding.
ext_name = idleConf.GetExtnNameForEvent(event)
ext_keybind_section = ext_name + '_cfgBindings'
changes.add_option('extensions', ext_keybind_section, event, value)
Attributes updated: def set_keys_type(self):
radio_fg "Set available screen options based on builtin or custom key set."
radio_bg if self.are_keys_builtin.get():
fg_bg_toggle self.opt_menu_keys_builtin['state'] = NORMAL
self.opt_menu_keys_custom['state'] = DISABLED
self.button_delete_custom_keys['state'] = DISABLED
else:
self.opt_menu_keys_builtin['state'] = DISABLED
self.radio_keys_custom['state'] = NORMAL
self.opt_menu_keys_custom['state'] = NORMAL
self.button_delete_custom_keys['state'] = NORMAL
Methods: def get_new_keys(self):
set_color_sample """Handle event to change key binding for selected line.
Called from: A selection of a key/binding in the list of current
var_changed_highlight_target bindings pops up a dialog to enter a new binding. If
load_theme_cfg the current key set is builtin and a binding has
changed, then a name for a custom key set needs to be
entered for the change to be applied.
""" """
if self.highlight_target.get() == 'Cursor': # bg not possible list_index = self.list_bindings.index(ANCHOR)
self.radio_fg['state'] = DISABLED binding = self.list_bindings.get(list_index)
self.radio_bg['state'] = DISABLED bind_name = binding.split()[0]
self.fg_bg_toggle.set(1) if self.are_keys_builtin.get():
else: # Both fg and bg can be set. current_key_set_name = self.builtin_keys.get()
self.radio_fg['state'] = NORMAL else:
self.radio_bg['state'] = NORMAL current_key_set_name = self.custom_keys.get()
self.fg_bg_toggle.set(1) current_bindings = idleConf.GetCurrentKeySet()
self.set_color_sample() if current_key_set_name in changes['keys']: # unsaved changes
key_set_changes = changes['keys'][current_key_set_name]
for event in key_set_changes:
current_bindings[event] = key_set_changes[event].split()
current_key_sequences = list(current_bindings.values())
new_keys = GetKeysDialog(self, 'Get New Keys', bind_name,
current_key_sequences).result
if new_keys:
if self.are_keys_builtin.get(): # Current key set is a built-in.
message = ('Your changes will be saved as a new Custom Key Set.'
' Enter a name for your new Custom Key Set below.')
new_keyset = self.get_new_keys_name(message)
if not new_keyset: # User cancelled custom key set creation.
self.list_bindings.select_set(list_index)
self.list_bindings.select_anchor(list_index)
return
else: # Create new custom key set based on previously active key set.
self.create_new_key_set(new_keyset)
self.list_bindings.delete(list_index)
self.list_bindings.insert(list_index, bind_name+' - '+new_keys)
self.list_bindings.select_set(list_index)
self.list_bindings.select_anchor(list_index)
self.keybinding.set(new_keys)
else:
self.list_bindings.select_set(list_index)
self.list_bindings.select_anchor(list_index)
def set_color_sample_binding(self, *args): def get_new_keys_name(self, message):
"""Change color sample based on foreground/background toggle. "Return new key set name from query popup."
used_names = (idleConf.GetSectionList('user', 'keys') +
idleConf.GetSectionList('default', 'keys'))
new_keyset = SectionName(
self, 'New Custom Key Set', message, used_names).result
return new_keyset
Methods: def save_as_new_key_set(self):
set_color_sample "Prompt for name of new key set and save changes using that name."
""" new_keys_name = self.get_new_keys_name('New Key Set Name:')
self.set_color_sample() if new_keys_name:
self.create_new_key_set(new_keys_name)
def set_color_sample(self): def keybinding_selected(self, event):
"""Set the color of the frame background to reflect the selected target. "Activate button to assign new keys to selected action."
self.button_new_keys['state'] = NORMAL
Instance variables accessed: def create_new_key_set(self, new_key_set_name):
theme_elements """Create a new custom key set with the given name.
highlight_target
fg_bg_toggle
highlight_sample
Attributes updated: Create the new key set based on the previously active set
frame_color_set with the current changes applied. Once it is saved, then
activate the new key set.
""" """
# Set the color sample area. if self.are_keys_builtin.get():
tag = self.theme_elements[self.highlight_target.get()][0] prev_key_set_name = self.builtin_keys.get()
plane = 'foreground' if self.fg_bg_toggle.get() else 'background' else:
color = self.highlight_sample.tag_cget(tag, plane) prev_key_set_name = self.custom_keys.get()
self.frame_color_set.config(bg=color) prev_keys = idleConf.GetCoreKeys(prev_key_set_name)
new_keys = {}
def paint_theme_sample(self): for event in prev_keys: # Add key set to changed items.
"""Apply the theme colors to each element tag in the sample text. event_name = event[2:-2] # Trim off the angle brackets.
binding = ' '.join(prev_keys[event])
Instance attributes accessed: new_keys[event_name] = binding
theme_elements # Handle any unsaved changes to prev key set.
is_builtin_theme if prev_key_set_name in changes['keys']:
builtin_theme key_set_changes = changes['keys'][prev_key_set_name]
custom_theme for event in key_set_changes:
new_keys[event] = key_set_changes[event]
Attributes updated: # Save the new key set.
highlight_sample: Set the tag elements to the theme. self.save_new_key_set(new_key_set_name, new_keys)
# Change GUI over to the new key set.
custom_key_list = idleConf.GetSectionList('user', 'keys')
custom_key_list.sort()
self.opt_menu_keys_custom.SetMenu(custom_key_list, new_key_set_name)
self.are_keys_builtin.set(0)
self.set_keys_type()
Methods: def load_keys_list(self, keyset_name):
set_color_sample """Reload the list of action/key binding pairs for the active key set.
Called from: An action/key binding can be selected to change the key binding.
var_changed_builtin_theme
var_changed_custom_theme
load_theme_cfg
""" """
if self.is_builtin_theme.get(): # Default theme reselect = 0
theme = self.builtin_theme.get() if self.list_bindings.curselection():
else: # User theme reselect = 1
theme = self.custom_theme.get() list_index = self.list_bindings.index(ANCHOR)
for element_title in self.theme_elements: keyset = idleConf.GetKeySet(keyset_name)
element = self.theme_elements[element_title][0] bind_names = list(keyset.keys())
colors = idleConf.GetHighlight(theme, element) bind_names.sort()
if element == 'cursor': # Cursor sample needs special painting. self.list_bindings.delete(0, END)
colors['background'] = idleConf.GetHighlight( for bind_name in bind_names:
theme, 'normal', fgBg='bg') key = ' '.join(keyset[bind_name])
# Handle any unsaved changes to this theme. bind_name = bind_name[2:-2] # Trim off the angle brackets.
if theme in changes['highlight']: if keyset_name in changes['keys']:
theme_dict = changes['highlight'][theme] # Handle any unsaved changes to this key set.
if element + '-foreground' in theme_dict: if bind_name in changes['keys'][keyset_name]:
colors['foreground'] = theme_dict[element + '-foreground'] key = changes['keys'][keyset_name][bind_name]
if element + '-background' in theme_dict: self.list_bindings.insert(END, bind_name+' - '+key)
colors['background'] = theme_dict[element + '-background'] if reselect:
self.highlight_sample.tag_config(element, **colors) self.list_bindings.see(list_index)
self.set_color_sample() self.list_bindings.select_set(list_index)
self.list_bindings.select_anchor(list_index)
def load_theme_cfg(self): def save_new_key_set(self, keyset_name, keyset):
"""Load current configuration settings for the theme options. """Save a newly created core key set.
Based on the is_builtin_theme toggle, the theme is set as keyset_name - string, the name of the new key set
either builtin or custom and the initial widget values keyset - dictionary containing the new key set
reflect the current settings from idleConf. """
if not idleConf.userCfg['keys'].has_section(keyset_name):
idleConf.userCfg['keys'].add_section(keyset_name)
for event in keyset:
value = keyset[event]
idleConf.userCfg['keys'].SetOption(keyset_name, event, value)
Attributes updated: def delete_custom_keys(self):
is_builtin_theme: Set from idleConf. """Handle event to delete a custom key set.
opt_menu_theme_builtin: List of default themes from idleConf.
opt_menu_theme_custom: List of custom themes from idleConf.
radio_theme_custom: Disabled if there are no custom themes.
custom_theme: Message with additional information.
opt_menu_highlight_target: Create menu from self.theme_elements.
Methods: Applying the delete deactivates the current configuration and
set_theme_type reverts to the default. The custom key set is permanently
paint_theme_sample deleted from the config file.
set_highlight_target
""" """
# Set current theme type radiobutton. keyset_name=self.custom_keys.get()
self.is_builtin_theme.set(idleConf.GetOption( delmsg = 'Are you sure you wish to delete the key set %r ?'
'main', 'Theme', 'default', type='bool', default=1)) if not tkMessageBox.askyesno(
# Set current theme. 'Delete Key Set', delmsg % keyset_name, parent=self):
current_option = idleConf.CurrentTheme() return
# Load available theme option menus. self.deactivate_current_config()
if self.is_builtin_theme.get(): # Default theme selected. # Remove key set from changes, config, and file.
item_list = idleConf.GetSectionList('default', 'highlight') changes.delete_section('keys', keyset_name)
item_list.sort() # Reload user key set list.
self.opt_menu_theme_builtin.SetMenu(item_list, current_option)
item_list = idleConf.GetSectionList('user', 'highlight')
item_list.sort()
if not item_list:
self.radio_theme_custom['state'] = DISABLED
self.custom_theme.set('- no custom themes -')
else:
self.opt_menu_theme_custom.SetMenu(item_list, item_list[0])
else: # User theme selected.
item_list = idleConf.GetSectionList('user', 'highlight')
item_list.sort()
self.opt_menu_theme_custom.SetMenu(item_list, current_option)
item_list = idleConf.GetSectionList('default', 'highlight')
item_list.sort()
self.opt_menu_theme_builtin.SetMenu(item_list, 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.opt_menu_highlight_target.SetMenu(theme_names, theme_names[0])
self.paint_theme_sample()
self.set_highlight_target()
def load_key_cfg(self):
"Load current configuration settings for the keybinding options."
# Set current keys type radiobutton.
self.are_keys_builtin.set(idleConf.GetOption(
'main', 'Keys', 'default', type='bool', default=1))
# Set current keys.
current_option = idleConf.CurrentKeys()
# Load available keyset option menus.
if self.are_keys_builtin.get(): # Default theme selected.
item_list = idleConf.GetSectionList('default', 'keys')
item_list.sort()
self.opt_menu_keys_builtin.SetMenu(item_list, current_option)
item_list = idleConf.GetSectionList('user', 'keys') item_list = idleConf.GetSectionList('user', 'keys')
item_list.sort() item_list.sort()
if not item_list: if not item_list:
self.radio_keys_custom['state'] = DISABLED self.radio_keys_custom['state'] = DISABLED
self.custom_keys.set('- no custom keys -') self.opt_menu_keys_custom.SetMenu(item_list, '- no custom keys -')
else: else:
self.opt_menu_keys_custom.SetMenu(item_list, item_list[0]) self.opt_menu_keys_custom.SetMenu(item_list, item_list[0])
else: # User key set selected. # Revert to default key set.
item_list = idleConf.GetSectionList('user', 'keys') self.are_keys_builtin.set(idleConf.defaultCfg['main']
item_list.sort() .Get('Keys', 'default'))
self.opt_menu_keys_custom.SetMenu(item_list, current_option) self.builtin_keys.set(idleConf.defaultCfg['main'].Get('Keys', 'name')
item_list = idleConf.GetSectionList('default', 'keys') or idleConf.default_keys())
item_list.sort() # User can't back out of these changes, they must be applied now.
self.opt_menu_keys_builtin.SetMenu(item_list, idleConf.default_keys()) changes.save_all()
self.save_all_changed_extensions()
self.activate_config_changes()
self.set_keys_type() self.set_keys_type()
# Load keyset element list.
keyset_name = idleConf.CurrentKeys()
self.load_keys_list(keyset_name)
def load_configs(self): def deactivate_current_config(self):
"""Load configuration for each page. """Remove current key bindings.
Load configuration from default and user config files and populate Iterate over window instances defined in parent and remove
the widgets on the config dialog pages. the keybindings.
"""
# Before a config is saved, some cleanup of current
# config must be done - remove the previous keybindings.
win_instances = self.parent.instance_dict.keys()
for instance in win_instances:
instance.RemoveKeybindings()
def activate_config_changes(self):
"""Apply configuration changes to current windows.
Dynamically update the current parent window instances
with some of the configuration changes.
"""
win_instances = self.parent.instance_dict.keys()
for instance in win_instances:
instance.ResetColorizer()
instance.ResetFont()
instance.set_notabs_indentwidth()
instance.ApplyKeybindings()
instance.reset_help_menu_entries()
def create_page_general(self):
"""Return frame of widgets for General tab.
Enable users to provisionally change general options. Function
load_general_cfg intializes tk variables and helplist using
idleConf. Radiobuttons startup_shell_on and startup_editor_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 win_width and win_height. Setting var_name invokes the
var_changed_var_name callback that adds option to changes.
Helplist: load_general_cfg loads list user_helplist with
name, position pairs and copies names to listbox helplist.
Clicking a name invokes help_source selected. Clicking
button_helplist_name invokes helplist_item_name, which also
changes user_helplist. These functions all call
set_add_delete_state. All but load call update_help_changes to
rewrite changes['main']['HelpFiles'].
Widget Structure: (*) widgets bound to self
frame
frame_run: LabelFrame
startup_title: Label
(*)startup_editor_on: Radiobutton - startup_edit
(*)startup_shell_on: Radiobutton - startup_edit
frame_save: LabelFrame
run_save_title: Label
(*)save_ask_on: Radiobutton - autosave
(*)save_auto_on: Radiobutton - autosave
frame_win_size: LabelFrame
win_size_title: Label
win_width_title: Label
(*)win_width_int: Entry - win_width
win_height_title: Label
(*)win_height_int: Entry - win_height
frame_help: LabelFrame
frame_helplist: Frame
frame_helplist_buttons: Frame
(*)button_helplist_edit
(*)button_helplist_add
(*)button_helplist_remove
(*)helplist: ListBox
scroll_helplist: Scrollbar
"""
parent = self.parent
self.startup_edit = IntVar(parent)
self.autosave = IntVar(parent)
self.win_width = StringVar(parent)
self.win_height = StringVar(parent)
# Create widgets:
# body.
frame = self.tab_pages.pages['General'].frame
# body section frames.
frame_run = LabelFrame(frame, borderwidth=2, relief=GROOVE,
text=' Startup Preferences ')
frame_save = LabelFrame(frame, borderwidth=2, relief=GROOVE,
text=' autosave Preferences ')
frame_win_size = Frame(frame, borderwidth=2, relief=GROOVE)
frame_help = LabelFrame(frame, borderwidth=2, relief=GROOVE,
text=' Additional Help Sources ')
# frame_run.
startup_title = Label(frame_run, text='At Startup')
self.startup_editor_on = Radiobutton(
frame_run, variable=self.startup_edit, value=1,
text="Open Edit Window")
self.startup_shell_on = Radiobutton(
frame_run, variable=self.startup_edit, value=0,
text='Open Shell Window')
# frame_save.
run_save_title = Label(frame_save, text='At Start of Run (F5) ')
self.save_ask_on = Radiobutton(
frame_save, variable=self.autosave, value=0,
text="Prompt to Save")
self.save_auto_on = Radiobutton(
frame_save, variable=self.autosave, value=1,
text='No Prompt')
# frame_win_size.
win_size_title = Label(
frame_win_size, text='Initial Window Size (in characters)')
win_width_title = Label(frame_win_size, text='Width')
self.win_width_int = Entry(
frame_win_size, textvariable=self.win_width, width=3)
win_height_title = Label(frame_win_size, text='Height')
self.win_height_int = Entry(
frame_win_size, textvariable=self.win_height, width=3)
# frame_help.
frame_helplist = Frame(frame_help)
frame_helplist_buttons = Frame(frame_helplist)
self.helplist = Listbox(
frame_helplist, height=5, takefocus=FALSE,
exportselection=FALSE)
scroll_helplist = Scrollbar(frame_helplist)
scroll_helplist['command'] = self.helplist.yview
self.helplist['yscrollcommand'] = scroll_helplist.set
self.helplist.bind('<ButtonRelease-1>', self.help_source_selected)
self.button_helplist_edit = Button(
frame_helplist_buttons, text='Edit', state=DISABLED,
width=8, command=self.helplist_item_edit)
self.button_helplist_add = Button(
frame_helplist_buttons, text='Add',
width=8, command=self.helplist_item_add)
self.button_helplist_remove = Button(
frame_helplist_buttons, text='Remove', state=DISABLED,
width=8, command=self.helplist_item_remove)
Methods: # Pack widgets:
load_font_cfg # body.
load_tab_cfg frame_run.pack(side=TOP, padx=5, pady=5, fill=X)
load_theme_cfg frame_save.pack(side=TOP, padx=5, pady=5, fill=X)
load_key_cfg frame_win_size.pack(side=TOP, padx=5, pady=5, fill=X)
load_general_cfg frame_help.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
""" # frame_run.
self.load_font_cfg() startup_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
self.load_tab_cfg() self.startup_shell_on.pack(side=RIGHT, anchor=W, padx=5, pady=5)
self.load_theme_cfg() self.startup_editor_on.pack(side=RIGHT, anchor=W, padx=5, pady=5)
self.load_key_cfg() # frame_save.
self.load_general_cfg() run_save_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
# note: extension page handled separately self.save_auto_on.pack(side=RIGHT, anchor=W, padx=5, pady=5)
self.save_ask_on.pack(side=RIGHT, anchor=W, padx=5, pady=5)
# frame_win_size.
win_size_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
self.win_height_int.pack(side=RIGHT, anchor=E, padx=10, pady=5)
win_height_title.pack(side=RIGHT, anchor=E, pady=5)
self.win_width_int.pack(side=RIGHT, anchor=E, padx=10, pady=5)
win_width_title.pack(side=RIGHT, anchor=E, pady=5)
# frame_help.
frame_helplist_buttons.pack(side=RIGHT, padx=5, pady=5, fill=Y)
frame_helplist.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
scroll_helplist.pack(side=RIGHT, anchor=W, fill=Y)
self.helplist.pack(side=LEFT, anchor=E, expand=TRUE, fill=BOTH)
self.button_helplist_edit.pack(side=TOP, anchor=W, pady=5)
self.button_helplist_add.pack(side=TOP, anchor=W)
self.button_helplist_remove.pack(side=TOP, anchor=W, pady=5)
def save_new_key_set(self, keyset_name, keyset): return frame
"""Save a newly created core key set.
keyset_name - string, the name of the new key set def load_general_cfg(self):
keyset - dictionary containing the new key set "Load current configuration settings for the general options."
""" # Set startup state.
if not idleConf.userCfg['keys'].has_section(keyset_name): self.startup_edit.set(idleConf.GetOption(
idleConf.userCfg['keys'].add_section(keyset_name) 'main', 'General', 'editor-on-startup', default=0, type='bool'))
for event in keyset: # Set autosave state.
value = keyset[event] self.autosave.set(idleConf.GetOption(
idleConf.userCfg['keys'].SetOption(keyset_name, event, value) 'main', 'General', 'autosave', default=0, type='bool'))
# Set initial window size.
self.win_width.set(idleConf.GetOption(
'main', 'EditorWindow', 'width', type='int'))
self.win_height.set(idleConf.GetOption(
'main', 'EditorWindow', 'height', type='int'))
# Set additional help sources.
self.user_helplist = idleConf.GetAllExtraHelpSourcesList()
self.helplist.delete(0, 'end')
for help_item in self.user_helplist:
self.helplist.insert(END, help_item[0])
self.set_add_delete_state()
def save_new_theme(self, theme_name, theme): def var_changed_startup_edit(self, *params):
"""Save a newly created theme to idleConf. "Store change to toggle for starting IDLE in the editor or shell."
value = self.startup_edit.get()
changes.add_option('main', 'General', 'editor-on-startup', value)
theme_name - string, the name of the new theme def var_changed_autosave(self, *params):
theme - dictionary containing the new theme "Store change to autosave."
""" value = self.autosave.get()
if not idleConf.userCfg['highlight'].has_section(theme_name): changes.add_option('main', 'General', 'autosave', value)
idleConf.userCfg['highlight'].add_section(theme_name)
for element in theme:
value = theme[element]
idleConf.userCfg['highlight'].SetOption(theme_name, element, value)
def deactivate_current_config(self): def var_changed_win_width(self, *params):
"""Remove current key bindings. "Store change to window width."
value = self.win_width.get()
changes.add_option('main', 'EditorWindow', 'width', value)
Iterate over window instances defined in parent and remove def var_changed_win_height(self, *params):
the keybindings. "Store change to window height."
""" value = self.win_height.get()
# Before a config is saved, some cleanup of current changes.add_option('main', 'EditorWindow', 'height', value)
# config must be done - remove the previous keybindings.
win_instances = self.parent.instance_dict.keys()
for instance in win_instances:
instance.RemoveKeybindings()
def activate_config_changes(self): def help_source_selected(self, event):
"""Apply configuration changes to current windows. "Handle event for selecting additional help."
self.set_add_delete_state()
Dynamically update the current parent window instances def set_add_delete_state(self):
with some of the configuration changes. "Toggle the state for the help list buttons based on list entries."
""" if self.helplist.size() < 1: # No entries in list.
win_instances = self.parent.instance_dict.keys() self.button_helplist_edit['state'] = DISABLED
for instance in win_instances: self.button_helplist_remove['state'] = DISABLED
instance.ResetColorizer() else: # Some entries.
instance.ResetFont() if self.helplist.curselection(): # There currently is a selection.
instance.set_notabs_indentwidth() self.button_helplist_edit['state'] = NORMAL
instance.ApplyKeybindings() self.button_helplist_remove['state'] = NORMAL
instance.reset_help_menu_entries() else: # There currently is not a selection.
self.button_helplist_edit['state'] = DISABLED
self.button_helplist_remove['state'] = DISABLED
def cancel(self): def helplist_item_add(self):
"""Dismiss config dialog. """Handle add button for the help list.
Methods: Query for name and location of new help sources and add
destroy: inherited them to the list.
""" """
self.destroy() help_source = HelpSource(self, 'New Help Source').result
if help_source:
self.user_helplist.append(help_source)
self.helplist.insert(END, help_source[0])
self.update_help_changes()
def ok(self): def helplist_item_edit(self):
"""Apply config changes, then dismiss dialog. """Handle edit button for the help list.
Methods: Query with existing help source information and update
apply config if the values are changed.
destroy: inherited
""" """
self.apply() item_index = self.helplist.index(ANCHOR)
self.destroy() help_source = self.user_helplist[item_index]
new_help_source = HelpSource(
self, 'Edit Help Source',
menuitem=help_source[0],
filepath=help_source[1],
).result
if new_help_source and new_help_source != help_source:
self.user_helplist[item_index] = new_help_source
self.helplist.delete(item_index)
self.helplist.insert(item_index, new_help_source[0])
self.update_help_changes()
self.set_add_delete_state() # Selected will be un-selected
def apply(self): def helplist_item_remove(self):
"""Apply config changes and leave dialog open. """Handle remove button for the help list.
Methods: Delete the help list item from config.
deactivate_current_config
save_all_changed_extensions
activate_config_changes
""" """
self.deactivate_current_config() item_index = self.helplist.index(ANCHOR)
changes.save_all() del(self.user_helplist[item_index])
self.save_all_changed_extensions() self.helplist.delete(item_index)
self.activate_config_changes() self.update_help_changes()
self.set_add_delete_state()
def help(self):
"""Create textview for config dialog help.
Attrbutes accessed: def update_help_changes(self):
tab_pages "Clear and rebuild the HelpFiles section in changes"
changes['main']['HelpFiles'] = {}
for num in range(1, len(self.user_helplist) + 1):
changes.add_option(
'main', 'HelpFiles', str(num),
';'.join(self.user_helplist[num-1][:2]))
Methods:
view_text: Method from textview module.
"""
page = self.tab_pages._current_page
view_text(self, title='Help for IDLE preferences',
text=help_common+help_pages.get(page, ''))
def create_page_extensions(self): def create_page_extensions(self):
"""Part of the config dialog used for configuring IDLE extensions. """Part of the config dialog used for configuring IDLE extensions.
......
IDLE - Finish rearranging methods of ConfigDialog Grouping methods
pertaining to each tab and the buttons will aid writing tests and improving
the tabs and will enable splitting the groups into classes.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment