bpo-31001: IDLE: Add tests for configdialog highlight tab (#3123)
This commit is contained in:
parent
f6ebd838f0
commit
82aff62462
|
@ -222,13 +222,79 @@ class ConfigDialog(Toplevel):
|
||||||
def create_page_highlight(self):
|
def create_page_highlight(self):
|
||||||
"""Return frame of widgets for Highlighting tab.
|
"""Return frame of widgets for Highlighting tab.
|
||||||
|
|
||||||
|
Enable users to provisionally change foreground and background
|
||||||
|
colors applied to textual tags. Color mappings are stored in
|
||||||
|
complete listings called themes. Built-in themes in
|
||||||
|
idlelib/config-highlight.def are fixed as far as the dialog is
|
||||||
|
concerned. Any theme can be used as the base for a new custom
|
||||||
|
theme, stored in .idlerc/config-highlight.cfg.
|
||||||
|
|
||||||
|
Function load_theme_cfg() initializes tk variables and theme
|
||||||
|
lists and calls paint_theme_sample() and set_highlight_target()
|
||||||
|
for the current theme. Radiobuttons builtin_theme_on and
|
||||||
|
custom_theme_on toggle var theme_source, which controls if the
|
||||||
|
current set of colors are from a builtin or custom theme.
|
||||||
|
DynOptionMenus builtinlist and customlist contain lists of the
|
||||||
|
builtin and custom themes, respectively, and the current item
|
||||||
|
from each list is stored in vars builtin_name and custom_name.
|
||||||
|
|
||||||
|
Function paint_theme_sample() applies the colors from the theme
|
||||||
|
to the tags in text widget highlight_sample and then invokes
|
||||||
|
set_color_sample(). Function set_highlight_target() sets the state
|
||||||
|
of the radiobuttons fg_on and bg_on based on the tag and it also
|
||||||
|
invokes set_color_sample().
|
||||||
|
|
||||||
|
Function set_color_sample() sets the background color for the frame
|
||||||
|
holding the color selector. This provides a larger visual of the
|
||||||
|
color for the current tag and plane (foreground/background).
|
||||||
|
|
||||||
|
Note: set_color_sample() is called from many places and is often
|
||||||
|
called more than once when a change is made. It is invoked when
|
||||||
|
foreground or background is selected (radiobuttons), from
|
||||||
|
paint_theme_sample() (theme is changed or load_cfg is called), and
|
||||||
|
from set_highlight_target() (target tag is changed or load_cfg called).
|
||||||
|
|
||||||
|
Button delete_custom invokes delete_custom() to delete
|
||||||
|
a custom theme from idleConf.userCfg['highlight'] and changes.
|
||||||
|
Button save_custom invokes save_as_new_theme() which calls
|
||||||
|
get_new_theme_name() and create_new() to save a custom theme
|
||||||
|
and its colors to idleConf.userCfg['highlight'].
|
||||||
|
|
||||||
|
Radiobuttons fg_on and bg_on toggle var fg_bg_toggle to control
|
||||||
|
if the current selected color for a tag is for the foreground or
|
||||||
|
background.
|
||||||
|
|
||||||
|
DynOptionMenu targetlist contains a readable description of the
|
||||||
|
tags applied to Python source within IDLE. Selecting one of the
|
||||||
|
tags from this list populates highlight_target, which has a callback
|
||||||
|
function set_highlight_target().
|
||||||
|
|
||||||
|
Text widget highlight_sample displays a block of text (which is
|
||||||
|
mock Python code) in which is embedded the defined tags and reflects
|
||||||
|
the color attributes of the current theme and changes for those tags.
|
||||||
|
Mouse button 1 allows for selection of a tag and updates
|
||||||
|
highlight_target with that tag value.
|
||||||
|
|
||||||
|
Note: The font in highlight_sample is set through the config in
|
||||||
|
the fonts tab.
|
||||||
|
|
||||||
|
In other words, a tag can be selected either from targetlist or
|
||||||
|
by clicking on the sample text within highlight_sample. The
|
||||||
|
plane (foreground/background) is selected via the radiobutton.
|
||||||
|
Together, these two (tag and plane) control what color is
|
||||||
|
shown in set_color_sample() for the current theme. Button set_color
|
||||||
|
invokes get_color() which displays a ColorChooser to change the
|
||||||
|
color for the selected tag/plane. If a new color is picked,
|
||||||
|
it will be saved to changes and the highlight_sample and
|
||||||
|
frame background will be updated.
|
||||||
|
|
||||||
Tk Variables:
|
Tk Variables:
|
||||||
color: Color of selected target.
|
color: Color of selected target.
|
||||||
builtin_theme: Menu variable for built-in theme.
|
builtin_name: Menu variable for built-in theme.
|
||||||
custom_theme: Menu variable for custom theme.
|
custom_name: Menu variable for custom theme.
|
||||||
fg_bg_toggle: Toggle for foreground/background color.
|
fg_bg_toggle: Toggle for foreground/background color.
|
||||||
Note: this has no callback.
|
Note: this has no callback.
|
||||||
is_builtin_theme: Selector for built-in or custom theme.
|
theme_source: Selector for built-in or custom theme.
|
||||||
highlight_target: Menu variable for the highlight tag target.
|
highlight_target: Menu variable for the highlight tag target.
|
||||||
|
|
||||||
Instance Data Attributes:
|
Instance Data Attributes:
|
||||||
|
@ -245,30 +311,30 @@ class ConfigDialog(Toplevel):
|
||||||
on_new_color_set: Set new color and add option.
|
on_new_color_set: Set new color and add option.
|
||||||
paint_theme_sample: Recolor sample.
|
paint_theme_sample: Recolor sample.
|
||||||
get_new_theme_name: Get from popup.
|
get_new_theme_name: Get from popup.
|
||||||
create_new_theme: Combine theme with changes and save.
|
create_new: Combine theme with changes and save.
|
||||||
save_as_new_theme: Save [button_save_custom_theme].
|
save_as_new_theme: Save [button_save_custom].
|
||||||
set_theme_type: Command for [is_builtin_theme].
|
set_theme_type: Command for [theme_source].
|
||||||
delete_custom_theme: Ativate default [button_delete_custom_theme].
|
delete_custom: Activate default [button_delete_custom].
|
||||||
save_new_theme: Save to userCfg['theme'] (is function).
|
save_new: Save to userCfg['theme'] (is function).
|
||||||
|
|
||||||
Widgets of highlights page frame: (*) widgets bound to self
|
Widgets of highlights page frame: (*) widgets bound to self
|
||||||
frame_custom: LabelFrame
|
frame_custom: LabelFrame
|
||||||
(*)highlight_sample: Text
|
(*)highlight_sample: Text
|
||||||
(*)frame_color_set: Frame
|
(*)frame_color_set: Frame
|
||||||
button_set_color: Button
|
(*)button_set_color: Button
|
||||||
(*)opt_menu_highlight_target: DynOptionMenu - highlight_target
|
(*)targetlist: DynOptionMenu - highlight_target
|
||||||
frame_fg_bg_toggle: Frame
|
frame_fg_bg_toggle: Frame
|
||||||
(*)radio_fg: Radiobutton - fg_bg_toggle
|
(*)fg_on: Radiobutton - fg_bg_toggle
|
||||||
(*)radio_bg: Radiobutton - fg_bg_toggle
|
(*)bg_on: Radiobutton - fg_bg_toggle
|
||||||
button_save_custom_theme: Button
|
(*)button_save_custom: Button
|
||||||
frame_theme: LabelFrame
|
frame_theme: LabelFrame
|
||||||
theme_type_title: Label
|
theme_type_title: Label
|
||||||
(*)radio_theme_builtin: Radiobutton - is_builtin_theme
|
(*)builtin_theme_on: Radiobutton - theme_source
|
||||||
(*)radio_theme_custom: Radiobutton - is_builtin_theme
|
(*)custom_theme_on: Radiobutton - theme_source
|
||||||
(*)opt_menu_theme_builtin: DynOptionMenu - builtin_theme
|
(*)builtinlist: DynOptionMenu - builtin_name
|
||||||
(*)opt_menu_theme_custom: DynOptionMenu - custom_theme
|
(*)customlist: DynOptionMenu - custom_name
|
||||||
(*)button_delete_custom_theme: Button
|
(*)button_delete_custom: Button
|
||||||
(*)new_custom_theme: Label
|
(*)theme_message: Label
|
||||||
"""
|
"""
|
||||||
self.theme_elements={
|
self.theme_elements={
|
||||||
'Normal Text': ('normal', '00'),
|
'Normal Text': ('normal', '00'),
|
||||||
|
@ -287,31 +353,30 @@ class ConfigDialog(Toplevel):
|
||||||
'Shell Stderr Text': ('stderr', '13'),
|
'Shell Stderr Text': ('stderr', '13'),
|
||||||
}
|
}
|
||||||
parent = self.parent
|
parent = self.parent
|
||||||
self.builtin_theme = tracers.add(
|
self.builtin_name = tracers.add(
|
||||||
StringVar(parent), self.var_changed_builtin_theme)
|
StringVar(parent), self.var_changed_builtin_name)
|
||||||
self.custom_theme = tracers.add(
|
self.custom_name = tracers.add(
|
||||||
StringVar(parent), self.var_changed_custom_theme)
|
StringVar(parent), self.var_changed_custom_name)
|
||||||
self.fg_bg_toggle = BooleanVar(parent)
|
self.fg_bg_toggle = BooleanVar(parent)
|
||||||
self.color = tracers.add(
|
self.color = tracers.add(
|
||||||
StringVar(parent), self.var_changed_color)
|
StringVar(parent), self.var_changed_color)
|
||||||
self.is_builtin_theme = tracers.add(
|
self.theme_source = tracers.add(
|
||||||
BooleanVar(parent), self.var_changed_is_builtin_theme)
|
BooleanVar(parent), self.var_changed_theme_source)
|
||||||
self.highlight_target = tracers.add(
|
self.highlight_target = tracers.add(
|
||||||
StringVar(parent), self.var_changed_highlight_target)
|
StringVar(parent), self.var_changed_highlight_target)
|
||||||
|
|
||||||
# Widget creation:
|
# Create widgets:
|
||||||
# body frame and section frames
|
# body frame and section frames.
|
||||||
frame = Frame(self.note)
|
frame = Frame(self.note)
|
||||||
frame_custom = LabelFrame(frame, borderwidth=2, relief=GROOVE,
|
frame_custom = LabelFrame(frame, borderwidth=2, relief=GROOVE,
|
||||||
text=' Custom Highlighting ')
|
text=' Custom Highlighting ')
|
||||||
frame_theme = LabelFrame(frame, borderwidth=2, relief=GROOVE,
|
frame_theme = LabelFrame(frame, borderwidth=2, relief=GROOVE,
|
||||||
text=' Highlighting Theme ')
|
text=' Highlighting Theme ')
|
||||||
#frame_custom
|
# frame_custom.
|
||||||
text = self.highlight_sample = frame.highlight_sample = Text(
|
text = self.highlight_sample = frame.highlight_sample = Text(
|
||||||
frame_custom, relief=SOLID, borderwidth=1,
|
frame_custom, relief=SOLID, borderwidth=1,
|
||||||
font=('courier', 12, ''), cursor='hand2', width=21, height=13,
|
font=('courier', 12, ''), cursor='hand2', width=21, height=13,
|
||||||
takefocus=FALSE, highlightthickness=0, wrap=NONE)
|
takefocus=FALSE, highlightthickness=0, wrap=NONE)
|
||||||
text=self.highlight_sample
|
|
||||||
text.bind('<Double-Button-1>', lambda e: 'break')
|
text.bind('<Double-Button-1>', lambda e: 'break')
|
||||||
text.bind('<B1-Motion>', lambda e: 'break')
|
text.bind('<B1-Motion>', lambda e: 'break')
|
||||||
text_and_tags=(('\n', 'normal'),
|
text_and_tags=(('\n', 'normal'),
|
||||||
|
@ -341,78 +406,77 @@ class ConfigDialog(Toplevel):
|
||||||
text['state'] = DISABLED
|
text['state'] = DISABLED
|
||||||
self.frame_color_set = Frame(frame_custom, relief=SOLID, borderwidth=1)
|
self.frame_color_set = Frame(frame_custom, relief=SOLID, borderwidth=1)
|
||||||
frame_fg_bg_toggle = Frame(frame_custom)
|
frame_fg_bg_toggle = Frame(frame_custom)
|
||||||
button_set_color = Button(
|
self.button_set_color = Button(
|
||||||
self.frame_color_set, text='Choose Color for :',
|
self.frame_color_set, text='Choose Color for :',
|
||||||
command=self.get_color, highlightthickness=0)
|
command=self.get_color, highlightthickness=0)
|
||||||
self.opt_menu_highlight_target = DynOptionMenu(
|
self.targetlist = DynOptionMenu(
|
||||||
self.frame_color_set, self.highlight_target, None,
|
self.frame_color_set, self.highlight_target, None,
|
||||||
highlightthickness=0) #, command=self.set_highlight_targetBinding
|
highlightthickness=0) #, command=self.set_highlight_targetBinding
|
||||||
self.radio_fg = Radiobutton(
|
self.fg_on = Radiobutton(
|
||||||
frame_fg_bg_toggle, variable=self.fg_bg_toggle, value=1,
|
frame_fg_bg_toggle, variable=self.fg_bg_toggle, value=1,
|
||||||
text='Foreground', command=self.set_color_sample_binding)
|
text='Foreground', command=self.set_color_sample_binding)
|
||||||
self.radio_bg=Radiobutton(
|
self.bg_on = Radiobutton(
|
||||||
frame_fg_bg_toggle, variable=self.fg_bg_toggle, value=0,
|
frame_fg_bg_toggle, variable=self.fg_bg_toggle, value=0,
|
||||||
text='Background', command=self.set_color_sample_binding)
|
text='Background', command=self.set_color_sample_binding)
|
||||||
self.fg_bg_toggle.set(1)
|
self.fg_bg_toggle.set(1)
|
||||||
button_save_custom_theme = Button(
|
self.button_save_custom = Button(
|
||||||
frame_custom, text='Save as New Custom Theme',
|
frame_custom, text='Save as New Custom Theme',
|
||||||
command=self.save_as_new_theme)
|
command=self.save_as_new_theme)
|
||||||
#frame_theme
|
# frame_theme.
|
||||||
theme_type_title = Label(frame_theme, text='Select : ')
|
theme_type_title = Label(frame_theme, text='Select : ')
|
||||||
self.radio_theme_builtin = Radiobutton(
|
self.builtin_theme_on = Radiobutton(
|
||||||
frame_theme, variable=self.is_builtin_theme, value=1,
|
frame_theme, variable=self.theme_source, value=1,
|
||||||
command=self.set_theme_type, text='a Built-in Theme')
|
command=self.set_theme_type, text='a Built-in Theme')
|
||||||
self.radio_theme_custom = Radiobutton(
|
self.custom_theme_on = Radiobutton(
|
||||||
frame_theme, variable=self.is_builtin_theme, value=0,
|
frame_theme, variable=self.theme_source, value=0,
|
||||||
command=self.set_theme_type, text='a Custom Theme')
|
command=self.set_theme_type, text='a Custom Theme')
|
||||||
self.opt_menu_theme_builtin = DynOptionMenu(
|
self.builtinlist = DynOptionMenu(
|
||||||
frame_theme, self.builtin_theme, None, command=None)
|
frame_theme, self.builtin_name, None, command=None)
|
||||||
self.opt_menu_theme_custom=DynOptionMenu(
|
self.customlist = DynOptionMenu(
|
||||||
frame_theme, self.custom_theme, None, command=None)
|
frame_theme, self.custom_name, None, command=None)
|
||||||
self.button_delete_custom_theme=Button(
|
self.button_delete_custom = Button(
|
||||||
frame_theme, text='Delete Custom Theme',
|
frame_theme, text='Delete Custom Theme',
|
||||||
command=self.delete_custom_theme)
|
command=self.delete_custom)
|
||||||
self.new_custom_theme = Label(frame_theme, bd=2)
|
self.theme_message = Label(frame_theme, bd=2)
|
||||||
|
|
||||||
##widget packing
|
# Pack widgets:
|
||||||
#body
|
# body.
|
||||||
frame_custom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
|
frame_custom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
|
||||||
frame_theme.pack(side=LEFT, padx=5, pady=5, fill=Y)
|
frame_theme.pack(side=LEFT, padx=5, pady=5, fill=Y)
|
||||||
#frame_custom
|
# frame_custom.
|
||||||
self.frame_color_set.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X)
|
self.frame_color_set.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X)
|
||||||
frame_fg_bg_toggle.pack(side=TOP, padx=5, pady=0)
|
frame_fg_bg_toggle.pack(side=TOP, padx=5, pady=0)
|
||||||
self.highlight_sample.pack(
|
self.highlight_sample.pack(
|
||||||
side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
|
side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
|
||||||
button_set_color.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=4)
|
self.button_set_color.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=4)
|
||||||
self.opt_menu_highlight_target.pack(
|
self.targetlist.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=3)
|
||||||
side=TOP, expand=TRUE, fill=X, padx=8, pady=3)
|
self.fg_on.pack(side=LEFT, anchor=E)
|
||||||
self.radio_fg.pack(side=LEFT, anchor=E)
|
self.bg_on.pack(side=RIGHT, anchor=W)
|
||||||
self.radio_bg.pack(side=RIGHT, anchor=W)
|
self.button_save_custom.pack(side=BOTTOM, fill=X, padx=5, pady=5)
|
||||||
button_save_custom_theme.pack(side=BOTTOM, fill=X, padx=5, pady=5)
|
# frame_theme.
|
||||||
#frame_theme
|
|
||||||
theme_type_title.pack(side=TOP, anchor=W, padx=5, pady=5)
|
theme_type_title.pack(side=TOP, anchor=W, padx=5, pady=5)
|
||||||
self.radio_theme_builtin.pack(side=TOP, anchor=W, padx=5)
|
self.builtin_theme_on.pack(side=TOP, anchor=W, padx=5)
|
||||||
self.radio_theme_custom.pack(side=TOP, anchor=W, padx=5, pady=2)
|
self.custom_theme_on.pack(side=TOP, anchor=W, padx=5, pady=2)
|
||||||
self.opt_menu_theme_builtin.pack(side=TOP, fill=X, padx=5, pady=5)
|
self.builtinlist.pack(side=TOP, fill=X, padx=5, pady=5)
|
||||||
self.opt_menu_theme_custom.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5)
|
self.customlist.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5)
|
||||||
self.button_delete_custom_theme.pack(side=TOP, fill=X, padx=5, pady=5)
|
self.button_delete_custom.pack(side=TOP, fill=X, padx=5, pady=5)
|
||||||
self.new_custom_theme.pack(side=TOP, fill=X, pady=5)
|
self.theme_message.pack(side=TOP, fill=X, pady=5)
|
||||||
return frame
|
return frame
|
||||||
|
|
||||||
def load_theme_cfg(self):
|
def load_theme_cfg(self):
|
||||||
"""Load current configuration settings for the theme options.
|
"""Load current configuration settings for the theme options.
|
||||||
|
|
||||||
Based on the is_builtin_theme toggle, the theme is set as
|
Based on the theme_source toggle, the theme is set as
|
||||||
either builtin or custom and the initial widget values
|
either builtin or custom and the initial widget values
|
||||||
reflect the current settings from idleConf.
|
reflect the current settings from idleConf.
|
||||||
|
|
||||||
Attributes updated:
|
Attributes updated:
|
||||||
is_builtin_theme: Set from idleConf.
|
theme_source: Set from idleConf.
|
||||||
opt_menu_theme_builtin: List of default themes from idleConf.
|
builtinlist: List of default themes from idleConf.
|
||||||
opt_menu_theme_custom: List of custom themes from idleConf.
|
customlist: List of custom themes from idleConf.
|
||||||
radio_theme_custom: Disabled if there are no custom themes.
|
custom_theme_on: Disabled if there are no custom themes.
|
||||||
custom_theme: Message with additional information.
|
custom_theme: Message with additional information.
|
||||||
opt_menu_highlight_target: Create menu from self.theme_elements.
|
targetlist: Create menu from self.theme_elements.
|
||||||
|
|
||||||
Methods:
|
Methods:
|
||||||
set_theme_type
|
set_theme_type
|
||||||
|
@ -420,80 +484,81 @@ class ConfigDialog(Toplevel):
|
||||||
set_highlight_target
|
set_highlight_target
|
||||||
"""
|
"""
|
||||||
# Set current theme type radiobutton.
|
# Set current theme type radiobutton.
|
||||||
self.is_builtin_theme.set(idleConf.GetOption(
|
self.theme_source.set(idleConf.GetOption(
|
||||||
'main', 'Theme', 'default', type='bool', default=1))
|
'main', 'Theme', 'default', type='bool', default=1))
|
||||||
# Set current theme.
|
# Set current theme.
|
||||||
current_option = idleConf.CurrentTheme()
|
current_option = idleConf.CurrentTheme()
|
||||||
# Load available theme option menus.
|
# Load available theme option menus.
|
||||||
if self.is_builtin_theme.get(): # Default theme selected.
|
if self.theme_source.get(): # Default theme selected.
|
||||||
item_list = idleConf.GetSectionList('default', 'highlight')
|
item_list = idleConf.GetSectionList('default', 'highlight')
|
||||||
item_list.sort()
|
item_list.sort()
|
||||||
self.opt_menu_theme_builtin.SetMenu(item_list, current_option)
|
self.builtinlist.SetMenu(item_list, current_option)
|
||||||
item_list = idleConf.GetSectionList('user', 'highlight')
|
item_list = idleConf.GetSectionList('user', 'highlight')
|
||||||
item_list.sort()
|
item_list.sort()
|
||||||
if not item_list:
|
if not item_list:
|
||||||
self.radio_theme_custom['state'] = DISABLED
|
self.custom_theme_on['state'] = DISABLED
|
||||||
self.custom_theme.set('- no custom themes -')
|
self.custom_name.set('- no custom themes -')
|
||||||
else:
|
else:
|
||||||
self.opt_menu_theme_custom.SetMenu(item_list, item_list[0])
|
self.customlist.SetMenu(item_list, item_list[0])
|
||||||
else: # User theme selected.
|
else: # User theme selected.
|
||||||
item_list = idleConf.GetSectionList('user', 'highlight')
|
item_list = idleConf.GetSectionList('user', 'highlight')
|
||||||
item_list.sort()
|
item_list.sort()
|
||||||
self.opt_menu_theme_custom.SetMenu(item_list, current_option)
|
self.customlist.SetMenu(item_list, current_option)
|
||||||
item_list = idleConf.GetSectionList('default', 'highlight')
|
item_list = idleConf.GetSectionList('default', 'highlight')
|
||||||
item_list.sort()
|
item_list.sort()
|
||||||
self.opt_menu_theme_builtin.SetMenu(item_list, item_list[0])
|
self.builtinlist.SetMenu(item_list, item_list[0])
|
||||||
self.set_theme_type()
|
self.set_theme_type()
|
||||||
# Load theme element option menu.
|
# Load theme element option menu.
|
||||||
theme_names = list(self.theme_elements.keys())
|
theme_names = list(self.theme_elements.keys())
|
||||||
theme_names.sort(key=lambda x: self.theme_elements[x][1])
|
theme_names.sort(key=lambda x: self.theme_elements[x][1])
|
||||||
self.opt_menu_highlight_target.SetMenu(theme_names, theme_names[0])
|
self.targetlist.SetMenu(theme_names, theme_names[0])
|
||||||
self.paint_theme_sample()
|
self.paint_theme_sample()
|
||||||
self.set_highlight_target()
|
self.set_highlight_target()
|
||||||
|
|
||||||
def var_changed_builtin_theme(self, *params):
|
def var_changed_builtin_name(self, *params):
|
||||||
"""Process new builtin theme selection.
|
"""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.
|
||||||
"""
|
"""
|
||||||
old_themes = ('IDLE Classic', 'IDLE New')
|
old_themes = ('IDLE Classic', 'IDLE New')
|
||||||
value = self.builtin_theme.get()
|
value = self.builtin_name.get()
|
||||||
if value not in old_themes:
|
if value not in old_themes:
|
||||||
if idleConf.GetOption('main', 'Theme', 'name') not in old_themes:
|
if idleConf.GetOption('main', 'Theme', 'name') not in old_themes:
|
||||||
changes.add_option('main', 'Theme', 'name', old_themes[0])
|
changes.add_option('main', 'Theme', 'name', old_themes[0])
|
||||||
changes.add_option('main', 'Theme', 'name2', value)
|
changes.add_option('main', 'Theme', 'name2', value)
|
||||||
self.new_custom_theme.config(text='New theme, see Help',
|
self.theme_message['text'] = 'New theme, see Help'
|
||||||
fg='#500000')
|
self.theme_message['fg'] = '#500000'
|
||||||
else:
|
else:
|
||||||
changes.add_option('main', 'Theme', 'name', value)
|
changes.add_option('main', 'Theme', 'name', value)
|
||||||
changes.add_option('main', 'Theme', 'name2', '')
|
changes.add_option('main', 'Theme', 'name2', '')
|
||||||
self.new_custom_theme.config(text='', fg='black')
|
self.theme_message['text'] = ''
|
||||||
|
self.theme_message['fg'] = 'black'
|
||||||
self.paint_theme_sample()
|
self.paint_theme_sample()
|
||||||
|
|
||||||
def var_changed_custom_theme(self, *params):
|
def var_changed_custom_name(self, *params):
|
||||||
"""Process new custom theme selection.
|
"""Process new custom theme selection.
|
||||||
|
|
||||||
If a new custom theme is selected, add the name to the
|
If a new custom theme is selected, add the name to the
|
||||||
changed_items and apply the theme to the sample.
|
changed_items and apply the theme to the sample.
|
||||||
"""
|
"""
|
||||||
value = self.custom_theme.get()
|
value = self.custom_name.get()
|
||||||
if value != '- no custom themes -':
|
if value != '- no custom themes -':
|
||||||
changes.add_option('main', 'Theme', 'name', value)
|
changes.add_option('main', 'Theme', 'name', value)
|
||||||
self.paint_theme_sample()
|
self.paint_theme_sample()
|
||||||
|
|
||||||
def var_changed_is_builtin_theme(self, *params):
|
def var_changed_theme_source(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.theme_source.get()
|
||||||
changes.add_option('main', 'Theme', 'default', value)
|
changes.add_option('main', 'Theme', 'default', value)
|
||||||
if value:
|
if value:
|
||||||
self.var_changed_builtin_theme()
|
self.var_changed_builtin_name()
|
||||||
else:
|
else:
|
||||||
self.var_changed_custom_theme()
|
self.var_changed_custom_name()
|
||||||
|
|
||||||
def var_changed_color(self, *params):
|
def var_changed_color(self, *params):
|
||||||
"Process change to color choice."
|
"Process change to color choice."
|
||||||
|
@ -507,29 +572,29 @@ class ConfigDialog(Toplevel):
|
||||||
"""Set available screen options based on builtin or custom theme.
|
"""Set available screen options based on builtin or custom theme.
|
||||||
|
|
||||||
Attributes accessed:
|
Attributes accessed:
|
||||||
is_builtin_theme
|
theme_source
|
||||||
|
|
||||||
Attributes updated:
|
Attributes updated:
|
||||||
opt_menu_theme_builtin
|
builtinlist
|
||||||
opt_menu_theme_custom
|
customlist
|
||||||
button_delete_custom_theme
|
button_delete_custom
|
||||||
radio_theme_custom
|
custom_theme_on
|
||||||
|
|
||||||
Called from:
|
Called from:
|
||||||
handler for radio_theme_builtin and radio_theme_custom
|
handler for builtin_theme_on and custom_theme_on
|
||||||
delete_custom_theme
|
delete_custom
|
||||||
create_new_theme
|
create_new
|
||||||
load_theme_cfg
|
load_theme_cfg
|
||||||
"""
|
"""
|
||||||
if self.is_builtin_theme.get():
|
if self.theme_source.get():
|
||||||
self.opt_menu_theme_builtin['state'] = NORMAL
|
self.builtinlist['state'] = NORMAL
|
||||||
self.opt_menu_theme_custom['state'] = DISABLED
|
self.customlist['state'] = DISABLED
|
||||||
self.button_delete_custom_theme['state'] = DISABLED
|
self.button_delete_custom['state'] = DISABLED
|
||||||
else:
|
else:
|
||||||
self.opt_menu_theme_builtin['state'] = DISABLED
|
self.builtinlist['state'] = DISABLED
|
||||||
self.radio_theme_custom['state'] = NORMAL
|
self.custom_theme_on['state'] = NORMAL
|
||||||
self.opt_menu_theme_custom['state'] = NORMAL
|
self.customlist['state'] = NORMAL
|
||||||
self.button_delete_custom_theme['state'] = NORMAL
|
self.button_delete_custom['state'] = NORMAL
|
||||||
|
|
||||||
def get_color(self):
|
def get_color(self):
|
||||||
"""Handle button to select a new color for the target tag.
|
"""Handle button to select a new color for the target tag.
|
||||||
|
@ -540,14 +605,14 @@ class ConfigDialog(Toplevel):
|
||||||
Attributes accessed:
|
Attributes accessed:
|
||||||
highlight_target
|
highlight_target
|
||||||
frame_color_set
|
frame_color_set
|
||||||
is_builtin_theme
|
theme_source
|
||||||
|
|
||||||
Attributes updated:
|
Attributes updated:
|
||||||
color
|
color
|
||||||
|
|
||||||
Methods:
|
Methods:
|
||||||
get_new_theme_name
|
get_new_theme_name
|
||||||
create_new_theme
|
create_new
|
||||||
"""
|
"""
|
||||||
target = self.highlight_target.get()
|
target = self.highlight_target.get()
|
||||||
prev_color = self.frame_color_set.cget('bg')
|
prev_color = self.frame_color_set.cget('bg')
|
||||||
|
@ -556,26 +621,26 @@ class ConfigDialog(Toplevel):
|
||||||
initialcolor=prev_color)
|
initialcolor=prev_color)
|
||||||
if color_string and (color_string != prev_color):
|
if color_string and (color_string != prev_color):
|
||||||
# User didn't cancel and they chose a new color.
|
# User didn't cancel and they chose a new color.
|
||||||
if self.is_builtin_theme.get(): # Current theme is a built-in.
|
if self.theme_source.get(): # Current theme is a built-in.
|
||||||
message = ('Your changes will be saved as a new Custom Theme. '
|
message = ('Your changes will be saved as a new Custom Theme. '
|
||||||
'Enter a name for your new Custom Theme below.')
|
'Enter a name for your new Custom Theme below.')
|
||||||
new_theme = self.get_new_theme_name(message)
|
new_theme = self.get_new_theme_name(message)
|
||||||
if not new_theme: # User cancelled custom theme creation.
|
if not new_theme: # User cancelled custom theme creation.
|
||||||
return
|
return
|
||||||
else: # Create new custom theme based on previously active theme.
|
else: # Create new custom theme based on previously active theme.
|
||||||
self.create_new_theme(new_theme)
|
self.create_new(new_theme)
|
||||||
self.color.set(color_string)
|
self.color.set(color_string)
|
||||||
else: # Current theme is user defined.
|
else: # Current theme is user defined.
|
||||||
self.color.set(color_string)
|
self.color.set(color_string)
|
||||||
|
|
||||||
def on_new_color_set(self):
|
def on_new_color_set(self):
|
||||||
"Display sample of new color selection on the dialog."
|
"Display sample of new color selection on the dialog."
|
||||||
new_color=self.color.get()
|
new_color = self.color.get()
|
||||||
self.frame_color_set.config(bg=new_color) # Set sample.
|
self.frame_color_set['bg'] = new_color # Set sample.
|
||||||
plane ='foreground' if self.fg_bg_toggle.get() else 'background'
|
plane = 'foreground' if self.fg_bg_toggle.get() else 'background'
|
||||||
sample_element = self.theme_elements[self.highlight_target.get()][0]
|
sample_element = self.theme_elements[self.highlight_target.get()][0]
|
||||||
self.highlight_sample.tag_config(sample_element, **{plane:new_color})
|
self.highlight_sample.tag_config(sample_element, **{plane: new_color})
|
||||||
theme = self.custom_theme.get()
|
theme = self.custom_name.get()
|
||||||
theme_element = sample_element + '-' + plane
|
theme_element = sample_element + '-' + plane
|
||||||
changes.add_option('highlight', theme, theme_element, new_color)
|
changes.add_option('highlight', theme, theme_element, new_color)
|
||||||
|
|
||||||
|
@ -592,13 +657,13 @@ class ConfigDialog(Toplevel):
|
||||||
|
|
||||||
Methods:
|
Methods:
|
||||||
get_new_theme_name
|
get_new_theme_name
|
||||||
create_new_theme
|
create_new
|
||||||
"""
|
"""
|
||||||
new_theme_name = self.get_new_theme_name('New Theme Name:')
|
new_theme_name = self.get_new_theme_name('New Theme Name:')
|
||||||
if new_theme_name:
|
if new_theme_name:
|
||||||
self.create_new_theme(new_theme_name)
|
self.create_new(new_theme_name)
|
||||||
|
|
||||||
def create_new_theme(self, new_theme_name):
|
def create_new(self, new_theme_name):
|
||||||
"""Create a new custom theme with the given name.
|
"""Create a new custom theme with the given name.
|
||||||
|
|
||||||
Create the new theme based on the previously active theme
|
Create the new theme based on the previously active theme
|
||||||
|
@ -606,23 +671,23 @@ class ConfigDialog(Toplevel):
|
||||||
activate the new theme.
|
activate the new theme.
|
||||||
|
|
||||||
Attributes accessed:
|
Attributes accessed:
|
||||||
builtin_theme
|
builtin_name
|
||||||
custom_theme
|
custom_name
|
||||||
|
|
||||||
Attributes updated:
|
Attributes updated:
|
||||||
opt_menu_theme_custom
|
customlist
|
||||||
is_builtin_theme
|
theme_source
|
||||||
|
|
||||||
Method:
|
Method:
|
||||||
save_new_theme
|
save_new
|
||||||
set_theme_type
|
set_theme_type
|
||||||
"""
|
"""
|
||||||
if self.is_builtin_theme.get():
|
if self.theme_source.get():
|
||||||
theme_type = 'default'
|
theme_type = 'default'
|
||||||
theme_name = self.builtin_theme.get()
|
theme_name = self.builtin_name.get()
|
||||||
else:
|
else:
|
||||||
theme_type = 'user'
|
theme_type = 'user'
|
||||||
theme_name = self.custom_theme.get()
|
theme_name = self.custom_name.get()
|
||||||
new_theme = idleConf.GetThemeDict(theme_type, theme_name)
|
new_theme = idleConf.GetThemeDict(theme_type, theme_name)
|
||||||
# Apply any of the old theme's unsaved changes to the new theme.
|
# Apply any of the old theme's unsaved changes to the new theme.
|
||||||
if theme_name in changes['highlight']:
|
if theme_name in changes['highlight']:
|
||||||
|
@ -630,12 +695,12 @@ class ConfigDialog(Toplevel):
|
||||||
for element in theme_changes:
|
for element in theme_changes:
|
||||||
new_theme[element] = theme_changes[element]
|
new_theme[element] = theme_changes[element]
|
||||||
# Save the new theme.
|
# Save the new theme.
|
||||||
self.save_new_theme(new_theme_name, new_theme)
|
self.save_new(new_theme_name, new_theme)
|
||||||
# Change GUI over to the new theme.
|
# Change GUI over to the new theme.
|
||||||
custom_theme_list = idleConf.GetSectionList('user', 'highlight')
|
custom_theme_list = idleConf.GetSectionList('user', 'highlight')
|
||||||
custom_theme_list.sort()
|
custom_theme_list.sort()
|
||||||
self.opt_menu_theme_custom.SetMenu(custom_theme_list, new_theme_name)
|
self.customlist.SetMenu(custom_theme_list, new_theme_name)
|
||||||
self.is_builtin_theme.set(0)
|
self.theme_source.set(0)
|
||||||
self.set_theme_type()
|
self.set_theme_type()
|
||||||
|
|
||||||
def set_highlight_target(self):
|
def set_highlight_target(self):
|
||||||
|
@ -645,8 +710,8 @@ class ConfigDialog(Toplevel):
|
||||||
highlight_target
|
highlight_target
|
||||||
|
|
||||||
Attributes updated:
|
Attributes updated:
|
||||||
radio_fg
|
fg_on
|
||||||
radio_bg
|
bg_on
|
||||||
fg_bg_toggle
|
fg_bg_toggle
|
||||||
|
|
||||||
Methods:
|
Methods:
|
||||||
|
@ -657,12 +722,12 @@ class ConfigDialog(Toplevel):
|
||||||
load_theme_cfg
|
load_theme_cfg
|
||||||
"""
|
"""
|
||||||
if self.highlight_target.get() == 'Cursor': # bg not possible
|
if self.highlight_target.get() == 'Cursor': # bg not possible
|
||||||
self.radio_fg['state'] = DISABLED
|
self.fg_on['state'] = DISABLED
|
||||||
self.radio_bg['state'] = DISABLED
|
self.bg_on['state'] = DISABLED
|
||||||
self.fg_bg_toggle.set(1)
|
self.fg_bg_toggle.set(1)
|
||||||
else: # Both fg and bg can be set.
|
else: # Both fg and bg can be set.
|
||||||
self.radio_fg['state'] = NORMAL
|
self.fg_on['state'] = NORMAL
|
||||||
self.radio_bg['state'] = NORMAL
|
self.bg_on['state'] = NORMAL
|
||||||
self.fg_bg_toggle.set(1)
|
self.fg_bg_toggle.set(1)
|
||||||
self.set_color_sample()
|
self.set_color_sample()
|
||||||
|
|
||||||
|
@ -690,16 +755,16 @@ class ConfigDialog(Toplevel):
|
||||||
tag = self.theme_elements[self.highlight_target.get()][0]
|
tag = self.theme_elements[self.highlight_target.get()][0]
|
||||||
plane = 'foreground' if self.fg_bg_toggle.get() else 'background'
|
plane = 'foreground' if self.fg_bg_toggle.get() else 'background'
|
||||||
color = self.highlight_sample.tag_cget(tag, plane)
|
color = self.highlight_sample.tag_cget(tag, plane)
|
||||||
self.frame_color_set.config(bg=color)
|
self.frame_color_set['bg'] = color
|
||||||
|
|
||||||
def paint_theme_sample(self):
|
def paint_theme_sample(self):
|
||||||
"""Apply the theme colors to each element tag in the sample text.
|
"""Apply the theme colors to each element tag in the sample text.
|
||||||
|
|
||||||
Instance attributes accessed:
|
Instance attributes accessed:
|
||||||
theme_elements
|
theme_elements
|
||||||
is_builtin_theme
|
theme_source
|
||||||
builtin_theme
|
builtin_name
|
||||||
custom_theme
|
custom_name
|
||||||
|
|
||||||
Attributes updated:
|
Attributes updated:
|
||||||
highlight_sample: Set the tag elements to the theme.
|
highlight_sample: Set the tag elements to the theme.
|
||||||
|
@ -708,14 +773,14 @@ class ConfigDialog(Toplevel):
|
||||||
set_color_sample
|
set_color_sample
|
||||||
|
|
||||||
Called from:
|
Called from:
|
||||||
var_changed_builtin_theme
|
var_changed_builtin_name
|
||||||
var_changed_custom_theme
|
var_changed_custom_name
|
||||||
load_theme_cfg
|
load_theme_cfg
|
||||||
"""
|
"""
|
||||||
if self.is_builtin_theme.get(): # Default theme
|
if self.theme_source.get(): # Default theme
|
||||||
theme = self.builtin_theme.get()
|
theme = self.builtin_name.get()
|
||||||
else: # User theme
|
else: # User theme
|
||||||
theme = self.custom_theme.get()
|
theme = self.custom_name.get()
|
||||||
for element_title in self.theme_elements:
|
for element_title in self.theme_elements:
|
||||||
element = self.theme_elements[element_title][0]
|
element = self.theme_elements[element_title][0]
|
||||||
colors = idleConf.GetHighlight(theme, element)
|
colors = idleConf.GetHighlight(theme, element)
|
||||||
|
@ -732,7 +797,7 @@ class ConfigDialog(Toplevel):
|
||||||
self.highlight_sample.tag_config(element, **colors)
|
self.highlight_sample.tag_config(element, **colors)
|
||||||
self.set_color_sample()
|
self.set_color_sample()
|
||||||
|
|
||||||
def save_new_theme(self, theme_name, theme):
|
def save_new(self, theme_name, theme):
|
||||||
"""Save a newly created theme to idleConf.
|
"""Save a newly created theme to idleConf.
|
||||||
|
|
||||||
theme_name - string, the name of the new theme
|
theme_name - string, the name of the new theme
|
||||||
|
@ -744,7 +809,7 @@ class ConfigDialog(Toplevel):
|
||||||
value = theme[element]
|
value = theme[element]
|
||||||
idleConf.userCfg['highlight'].SetOption(theme_name, element, value)
|
idleConf.userCfg['highlight'].SetOption(theme_name, element, value)
|
||||||
|
|
||||||
def delete_custom_theme(self):
|
def delete_custom(self):
|
||||||
"""Handle event to delete custom theme.
|
"""Handle event to delete custom theme.
|
||||||
|
|
||||||
The current theme is deactivated and the default theme is
|
The current theme is deactivated and the default theme is
|
||||||
|
@ -752,13 +817,13 @@ class ConfigDialog(Toplevel):
|
||||||
the config file.
|
the config file.
|
||||||
|
|
||||||
Attributes accessed:
|
Attributes accessed:
|
||||||
custom_theme
|
custom_name
|
||||||
|
|
||||||
Attributes updated:
|
Attributes updated:
|
||||||
radio_theme_custom
|
custom_theme_on
|
||||||
opt_menu_theme_custom
|
customlist
|
||||||
is_builtin_theme
|
theme_source
|
||||||
builtin_theme
|
builtin_name
|
||||||
|
|
||||||
Methods:
|
Methods:
|
||||||
deactivate_current_config
|
deactivate_current_config
|
||||||
|
@ -766,7 +831,7 @@ class ConfigDialog(Toplevel):
|
||||||
activate_config_changes
|
activate_config_changes
|
||||||
set_theme_type
|
set_theme_type
|
||||||
"""
|
"""
|
||||||
theme_name = self.custom_theme.get()
|
theme_name = self.custom_name.get()
|
||||||
delmsg = 'Are you sure you wish to delete the theme %r ?'
|
delmsg = 'Are you sure you wish to delete the theme %r ?'
|
||||||
if not tkMessageBox.askyesno(
|
if not tkMessageBox.askyesno(
|
||||||
'Delete Theme', delmsg % theme_name, parent=self):
|
'Delete Theme', delmsg % theme_name, parent=self):
|
||||||
|
@ -778,13 +843,13 @@ class ConfigDialog(Toplevel):
|
||||||
item_list = idleConf.GetSectionList('user', 'highlight')
|
item_list = idleConf.GetSectionList('user', 'highlight')
|
||||||
item_list.sort()
|
item_list.sort()
|
||||||
if not item_list:
|
if not item_list:
|
||||||
self.radio_theme_custom['state'] = DISABLED
|
self.custom_theme_on['state'] = DISABLED
|
||||||
self.opt_menu_theme_custom.SetMenu(item_list, '- no custom themes -')
|
self.customlist.SetMenu(item_list, '- no custom themes -')
|
||||||
else:
|
else:
|
||||||
self.opt_menu_theme_custom.SetMenu(item_list, item_list[0])
|
self.customlist.SetMenu(item_list, item_list[0])
|
||||||
# Revert to default theme.
|
# Revert to default theme.
|
||||||
self.is_builtin_theme.set(idleConf.defaultCfg['main'].Get('Theme', 'default'))
|
self.theme_source.set(idleConf.defaultCfg['main'].Get('Theme', 'default'))
|
||||||
self.builtin_theme.set(idleConf.defaultCfg['main'].Get('Theme', 'name'))
|
self.builtin_name.set(idleConf.defaultCfg['main'].Get('Theme', 'name'))
|
||||||
# User can't back out of these changes, they must be applied now.
|
# User can't back out of these changes, they must be applied now.
|
||||||
changes.save_all()
|
changes.save_all()
|
||||||
self.save_all_changed_extensions()
|
self.save_all_changed_extensions()
|
||||||
|
@ -1270,7 +1335,7 @@ class KeysPage(Frame):
|
||||||
get_new_keys(). Function get_new_keys() gets the key mappings from the
|
get_new_keys(). Function get_new_keys() gets the key mappings from the
|
||||||
current keyset for the binding event item that was selected. The
|
current keyset for the binding event item that was selected. The
|
||||||
function then displays another dialog, GetKeysDialog, with the
|
function then displays another dialog, GetKeysDialog, with the
|
||||||
selected binding event and current keys and always new key sequences
|
selected binding event and current keys and allows new key sequences
|
||||||
to be entered for that binding event. If the keys aren't
|
to be entered for that binding event. If the keys aren't
|
||||||
changed, nothing happens. If the keys are changed and the keyset
|
changed, nothing happens. If the keys are changed and the keyset
|
||||||
is a builtin, function get_new_keys_name() will be called
|
is a builtin, function get_new_keys_name() will be called
|
||||||
|
|
|
@ -139,7 +139,7 @@ class FontPageTest(unittest.TestCase):
|
||||||
self.assertIn(d.font_name.get(), font1.lower())
|
self.assertIn(d.font_name.get(), font1.lower())
|
||||||
|
|
||||||
def test_sizelist(self):
|
def test_sizelist(self):
|
||||||
# Click on number shouod select that number
|
# Click on number should select that number
|
||||||
d = self.page
|
d = self.page
|
||||||
d.sizelist.variable.set(40)
|
d.sizelist.variable.set(40)
|
||||||
self.assertEqual(d.font_size.get(), '40')
|
self.assertEqual(d.font_size.get(), '40')
|
||||||
|
@ -227,9 +227,457 @@ class IndentTest(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class HighlightTest(unittest.TestCase):
|
class HighlightTest(unittest.TestCase):
|
||||||
|
"""Test that highlight tab widgets enable users to make changes.
|
||||||
|
|
||||||
|
Test that widget actions set vars, that var changes add
|
||||||
|
options to changes and that themes work correctly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
d = dialog
|
||||||
|
dialog.note.select(d.highpage)
|
||||||
|
d.set_theme_type = Func()
|
||||||
|
d.paint_theme_sample = Func()
|
||||||
|
d.set_highlight_target = Func()
|
||||||
|
d.set_color_sample = Func()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
d = dialog
|
||||||
|
del d.set_theme_type, d.paint_theme_sample
|
||||||
|
del d.set_highlight_target, d.set_color_sample
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
d = dialog
|
||||||
|
# The following is needed for test_load_key_cfg, _delete_custom_keys.
|
||||||
|
# This may indicate a defect in some test or function.
|
||||||
|
for section in idleConf.GetSectionList('user', 'highlight'):
|
||||||
|
idleConf.userCfg['highlight'].remove_section(section)
|
||||||
changes.clear()
|
changes.clear()
|
||||||
|
d.set_theme_type.called = 0
|
||||||
|
d.paint_theme_sample.called = 0
|
||||||
|
d.set_highlight_target.called = 0
|
||||||
|
d.set_color_sample.called = 0
|
||||||
|
|
||||||
|
def test_load_theme_cfg(self):
|
||||||
|
tracers.detach()
|
||||||
|
d = dialog
|
||||||
|
eq = self.assertEqual
|
||||||
|
|
||||||
|
# Use builtin theme with no user themes created.
|
||||||
|
idleConf.CurrentTheme = mock.Mock(return_value='IDLE Classic')
|
||||||
|
d.load_theme_cfg()
|
||||||
|
self.assertTrue(d.theme_source.get())
|
||||||
|
# builtinlist sets variable builtin_name to the CurrentTheme default.
|
||||||
|
eq(d.builtin_name.get(), 'IDLE Classic')
|
||||||
|
eq(d.custom_name.get(), '- no custom themes -')
|
||||||
|
eq(d.custom_theme_on['state'], DISABLED)
|
||||||
|
eq(d.set_theme_type.called, 1)
|
||||||
|
eq(d.paint_theme_sample.called, 1)
|
||||||
|
eq(d.set_highlight_target.called, 1)
|
||||||
|
|
||||||
|
# Builtin theme with non-empty user theme list.
|
||||||
|
idleConf.SetOption('highlight', 'test1', 'option', 'value')
|
||||||
|
idleConf.SetOption('highlight', 'test2', 'option2', 'value2')
|
||||||
|
d.load_theme_cfg()
|
||||||
|
eq(d.builtin_name.get(), 'IDLE Classic')
|
||||||
|
eq(d.custom_name.get(), 'test1')
|
||||||
|
eq(d.set_theme_type.called, 2)
|
||||||
|
eq(d.paint_theme_sample.called, 2)
|
||||||
|
eq(d.set_highlight_target.called, 2)
|
||||||
|
|
||||||
|
# Use custom theme.
|
||||||
|
idleConf.CurrentTheme = mock.Mock(return_value='test2')
|
||||||
|
idleConf.SetOption('main', 'Theme', 'default', '0')
|
||||||
|
d.load_theme_cfg()
|
||||||
|
self.assertFalse(d.theme_source.get())
|
||||||
|
eq(d.builtin_name.get(), 'IDLE Classic')
|
||||||
|
eq(d.custom_name.get(), 'test2')
|
||||||
|
eq(d.set_theme_type.called, 3)
|
||||||
|
eq(d.paint_theme_sample.called, 3)
|
||||||
|
eq(d.set_highlight_target.called, 3)
|
||||||
|
|
||||||
|
del idleConf.CurrentTheme
|
||||||
|
tracers.attach()
|
||||||
|
|
||||||
|
def test_theme_source(self):
|
||||||
|
eq = self.assertEqual
|
||||||
|
d = dialog
|
||||||
|
# Test these separately.
|
||||||
|
d.var_changed_builtin_name = Func()
|
||||||
|
d.var_changed_custom_name = Func()
|
||||||
|
# Builtin selected.
|
||||||
|
d.builtin_theme_on.invoke()
|
||||||
|
eq(mainpage, {'Theme': {'default': 'True'}})
|
||||||
|
eq(d.var_changed_builtin_name.called, 1)
|
||||||
|
eq(d.var_changed_custom_name.called, 0)
|
||||||
|
changes.clear()
|
||||||
|
|
||||||
|
# Custom selected.
|
||||||
|
d.custom_theme_on['state'] = NORMAL
|
||||||
|
d.custom_theme_on.invoke()
|
||||||
|
self.assertEqual(mainpage, {'Theme': {'default': 'False'}})
|
||||||
|
eq(d.var_changed_builtin_name.called, 1)
|
||||||
|
eq(d.var_changed_custom_name.called, 1)
|
||||||
|
del d.var_changed_builtin_name, d.var_changed_custom_name
|
||||||
|
|
||||||
|
def test_builtin_name(self):
|
||||||
|
eq = self.assertEqual
|
||||||
|
d = dialog
|
||||||
|
item_list = ['IDLE Classic', 'IDLE Dark', 'IDLE New']
|
||||||
|
|
||||||
|
# Not in old_themes, defaults name to first item.
|
||||||
|
idleConf.SetOption('main', 'Theme', 'name', 'spam')
|
||||||
|
d.builtinlist.SetMenu(item_list, 'IDLE Dark')
|
||||||
|
eq(mainpage, {'Theme': {'name': 'IDLE Classic',
|
||||||
|
'name2': 'IDLE Dark'}})
|
||||||
|
eq(d.theme_message['text'], 'New theme, see Help')
|
||||||
|
eq(d.paint_theme_sample.called, 1)
|
||||||
|
|
||||||
|
# Not in old themes - uses name2.
|
||||||
|
changes.clear()
|
||||||
|
idleConf.SetOption('main', 'Theme', 'name', 'IDLE New')
|
||||||
|
d.builtinlist.SetMenu(item_list, 'IDLE Dark')
|
||||||
|
eq(mainpage, {'Theme': {'name2': 'IDLE Dark'}})
|
||||||
|
eq(d.theme_message['text'], 'New theme, see Help')
|
||||||
|
eq(d.paint_theme_sample.called, 2)
|
||||||
|
|
||||||
|
# Builtin name in old_themes.
|
||||||
|
changes.clear()
|
||||||
|
d.builtinlist.SetMenu(item_list, 'IDLE Classic')
|
||||||
|
eq(mainpage, {'Theme': {'name': 'IDLE Classic', 'name2': ''}})
|
||||||
|
eq(d.theme_message['text'], '')
|
||||||
|
eq(d.paint_theme_sample.called, 3)
|
||||||
|
|
||||||
|
def test_custom_name(self):
|
||||||
|
d = dialog
|
||||||
|
|
||||||
|
# If no selections, doesn't get added.
|
||||||
|
d.customlist.SetMenu([], '- no custom themes -')
|
||||||
|
self.assertNotIn('Theme', mainpage)
|
||||||
|
self.assertEqual(d.paint_theme_sample.called, 0)
|
||||||
|
|
||||||
|
# Custom name selected.
|
||||||
|
changes.clear()
|
||||||
|
d.customlist.SetMenu(['a', 'b', 'c'], 'c')
|
||||||
|
self.assertEqual(mainpage, {'Theme': {'name': 'c'}})
|
||||||
|
self.assertEqual(d.paint_theme_sample.called, 1)
|
||||||
|
|
||||||
|
def test_color(self):
|
||||||
|
d = dialog
|
||||||
|
d.on_new_color_set = Func()
|
||||||
|
# self.color is only set in get_color through ColorChooser.
|
||||||
|
d.color.set('green')
|
||||||
|
self.assertEqual(d.on_new_color_set.called, 1)
|
||||||
|
del d.on_new_color_set
|
||||||
|
|
||||||
|
def test_highlight_target_list_mouse(self):
|
||||||
|
# Set highlight_target through targetlist.
|
||||||
|
eq = self.assertEqual
|
||||||
|
d = dialog
|
||||||
|
|
||||||
|
d.targetlist.SetMenu(['a', 'b', 'c'], 'c')
|
||||||
|
eq(d.highlight_target.get(), 'c')
|
||||||
|
eq(d.set_highlight_target.called, 1)
|
||||||
|
|
||||||
|
def test_highlight_target_text_mouse(self):
|
||||||
|
# Set highlight_target through clicking highlight_sample.
|
||||||
|
eq = self.assertEqual
|
||||||
|
d = dialog
|
||||||
|
|
||||||
|
elem = {}
|
||||||
|
count = 0
|
||||||
|
hs = d.highlight_sample
|
||||||
|
hs.focus_force()
|
||||||
|
hs.see(1.0)
|
||||||
|
hs.update_idletasks()
|
||||||
|
|
||||||
|
def tag_to_element(elem):
|
||||||
|
for element, tag in d.theme_elements.items():
|
||||||
|
elem[tag[0]] = element
|
||||||
|
|
||||||
|
def click_it(start):
|
||||||
|
x, y, dx, dy = hs.bbox(start)
|
||||||
|
x += dx // 2
|
||||||
|
y += dy // 2
|
||||||
|
hs.event_generate('<Enter>', x=0, y=0)
|
||||||
|
hs.event_generate('<Motion>', x=x, y=y)
|
||||||
|
hs.event_generate('<ButtonPress-1>', x=x, y=y)
|
||||||
|
hs.event_generate('<ButtonRelease-1>', x=x, y=y)
|
||||||
|
|
||||||
|
# Flip theme_elements to make the tag the key.
|
||||||
|
tag_to_element(elem)
|
||||||
|
|
||||||
|
# If highlight_sample has a tag that isn't in theme_elements, there
|
||||||
|
# will be a KeyError in the test run.
|
||||||
|
for tag in hs.tag_names():
|
||||||
|
for start_index in hs.tag_ranges(tag)[0::2]:
|
||||||
|
count += 1
|
||||||
|
click_it(start_index)
|
||||||
|
eq(d.highlight_target.get(), elem[tag])
|
||||||
|
eq(d.set_highlight_target.called, count)
|
||||||
|
|
||||||
|
def test_set_theme_type(self):
|
||||||
|
eq = self.assertEqual
|
||||||
|
d = dialog
|
||||||
|
del d.set_theme_type
|
||||||
|
|
||||||
|
# Builtin theme selected.
|
||||||
|
d.theme_source.set(True)
|
||||||
|
d.set_theme_type()
|
||||||
|
eq(d.builtinlist['state'], NORMAL)
|
||||||
|
eq(d.customlist['state'], DISABLED)
|
||||||
|
eq(d.button_delete_custom['state'], DISABLED)
|
||||||
|
|
||||||
|
# Custom theme selected.
|
||||||
|
d.theme_source.set(False)
|
||||||
|
d.set_theme_type()
|
||||||
|
eq(d.builtinlist['state'], DISABLED)
|
||||||
|
eq(d.custom_theme_on['state'], NORMAL)
|
||||||
|
eq(d.customlist['state'], NORMAL)
|
||||||
|
eq(d.button_delete_custom['state'], NORMAL)
|
||||||
|
d.set_theme_type = Func()
|
||||||
|
|
||||||
|
def test_get_color(self):
|
||||||
|
eq = self.assertEqual
|
||||||
|
d = dialog
|
||||||
|
orig_chooser = configdialog.tkColorChooser.askcolor
|
||||||
|
chooser = configdialog.tkColorChooser.askcolor = Func()
|
||||||
|
gntn = d.get_new_theme_name = Func()
|
||||||
|
|
||||||
|
d.highlight_target.set('Editor Breakpoint')
|
||||||
|
d.color.set('#ffffff')
|
||||||
|
|
||||||
|
# Nothing selected.
|
||||||
|
chooser.result = (None, None)
|
||||||
|
d.button_set_color.invoke()
|
||||||
|
eq(d.color.get(), '#ffffff')
|
||||||
|
|
||||||
|
# Selection same as previous color.
|
||||||
|
chooser.result = ('', d.frame_color_set.cget('bg'))
|
||||||
|
d.button_set_color.invoke()
|
||||||
|
eq(d.color.get(), '#ffffff')
|
||||||
|
|
||||||
|
# Select different color.
|
||||||
|
chooser.result = ((222.8671875, 0.0, 0.0), '#de0000')
|
||||||
|
|
||||||
|
# Default theme.
|
||||||
|
d.color.set('#ffffff')
|
||||||
|
d.theme_source.set(True)
|
||||||
|
|
||||||
|
# No theme name selected therefore color not saved.
|
||||||
|
gntn.result = ''
|
||||||
|
d.button_set_color.invoke()
|
||||||
|
eq(gntn.called, 1)
|
||||||
|
eq(d.color.get(), '#ffffff')
|
||||||
|
# Theme name selected.
|
||||||
|
gntn.result = 'My New Theme'
|
||||||
|
d.button_set_color.invoke()
|
||||||
|
eq(d.custom_name.get(), gntn.result)
|
||||||
|
eq(d.color.get(), '#de0000')
|
||||||
|
|
||||||
|
# Custom theme.
|
||||||
|
d.color.set('#ffffff')
|
||||||
|
d.theme_source.set(False)
|
||||||
|
d.button_set_color.invoke()
|
||||||
|
eq(d.color.get(), '#de0000')
|
||||||
|
|
||||||
|
del d.get_new_theme_name
|
||||||
|
configdialog.tkColorChooser.askcolor = orig_chooser
|
||||||
|
|
||||||
|
def test_on_new_color_set(self):
|
||||||
|
d = dialog
|
||||||
|
color = '#3f7cae'
|
||||||
|
d.custom_name.set('Python')
|
||||||
|
d.highlight_target.set('Selected Text')
|
||||||
|
d.fg_bg_toggle.set(True)
|
||||||
|
|
||||||
|
d.color.set(color)
|
||||||
|
self.assertEqual(d.frame_color_set.cget('bg'), color)
|
||||||
|
self.assertEqual(d.highlight_sample.tag_cget('hilite', 'foreground'), color)
|
||||||
|
self.assertEqual(highpage,
|
||||||
|
{'Python': {'hilite-foreground': color}})
|
||||||
|
|
||||||
|
def test_get_new_theme_name(self):
|
||||||
|
orig_sectionname = configdialog.SectionName
|
||||||
|
sn = configdialog.SectionName = Func(return_self=True)
|
||||||
|
d = dialog
|
||||||
|
|
||||||
|
sn.result = 'New Theme'
|
||||||
|
self.assertEqual(d.get_new_theme_name(''), 'New Theme')
|
||||||
|
|
||||||
|
configdialog.SectionName = orig_sectionname
|
||||||
|
|
||||||
|
def test_save_as_new_theme(self):
|
||||||
|
d = dialog
|
||||||
|
gntn = d.get_new_theme_name = Func()
|
||||||
|
d.theme_source.set(True)
|
||||||
|
|
||||||
|
# No name entered.
|
||||||
|
gntn.result = ''
|
||||||
|
d.button_save_custom.invoke()
|
||||||
|
self.assertNotIn(gntn.result, idleConf.userCfg['highlight'])
|
||||||
|
|
||||||
|
# Name entered.
|
||||||
|
gntn.result = 'my new theme'
|
||||||
|
gntn.called = 0
|
||||||
|
self.assertNotIn(gntn.result, idleConf.userCfg['highlight'])
|
||||||
|
d.button_save_custom.invoke()
|
||||||
|
self.assertIn(gntn.result, idleConf.userCfg['highlight'])
|
||||||
|
|
||||||
|
del d.get_new_theme_name
|
||||||
|
|
||||||
|
def test_create_new_and_save_new(self):
|
||||||
|
eq = self.assertEqual
|
||||||
|
d = dialog
|
||||||
|
|
||||||
|
# Use default as previously active theme.
|
||||||
|
d.theme_source.set(True)
|
||||||
|
d.builtin_name.set('IDLE Classic')
|
||||||
|
first_new = 'my new custom theme'
|
||||||
|
second_new = 'my second custom theme'
|
||||||
|
|
||||||
|
# No changes, so themes are an exact copy.
|
||||||
|
self.assertNotIn(first_new, idleConf.userCfg)
|
||||||
|
d.create_new(first_new)
|
||||||
|
eq(idleConf.GetSectionList('user', 'highlight'), [first_new])
|
||||||
|
eq(idleConf.GetThemeDict('default', 'IDLE Classic'),
|
||||||
|
idleConf.GetThemeDict('user', first_new))
|
||||||
|
eq(d.custom_name.get(), first_new)
|
||||||
|
self.assertFalse(d.theme_source.get()) # Use custom set.
|
||||||
|
eq(d.set_theme_type.called, 1)
|
||||||
|
|
||||||
|
# Test that changed targets are in new theme.
|
||||||
|
changes.add_option('highlight', first_new, 'hit-background', 'yellow')
|
||||||
|
self.assertNotIn(second_new, idleConf.userCfg)
|
||||||
|
d.create_new(second_new)
|
||||||
|
eq(idleConf.GetSectionList('user', 'highlight'), [first_new, second_new])
|
||||||
|
self.assertNotEqual(idleConf.GetThemeDict('user', first_new),
|
||||||
|
idleConf.GetThemeDict('user', second_new))
|
||||||
|
# Check that difference in themes was in `hit-background` from `changes`.
|
||||||
|
idleConf.SetOption('highlight', first_new, 'hit-background', 'yellow')
|
||||||
|
eq(idleConf.GetThemeDict('user', first_new),
|
||||||
|
idleConf.GetThemeDict('user', second_new))
|
||||||
|
|
||||||
|
def test_set_highlight_target(self):
|
||||||
|
eq = self.assertEqual
|
||||||
|
d = dialog
|
||||||
|
del d.set_highlight_target
|
||||||
|
|
||||||
|
# Target is cursor.
|
||||||
|
d.highlight_target.set('Cursor')
|
||||||
|
eq(d.fg_on['state'], DISABLED)
|
||||||
|
eq(d.bg_on['state'], DISABLED)
|
||||||
|
self.assertTrue(d.fg_bg_toggle)
|
||||||
|
eq(d.set_color_sample.called, 1)
|
||||||
|
|
||||||
|
# Target is not cursor.
|
||||||
|
d.highlight_target.set('Comment')
|
||||||
|
eq(d.fg_on['state'], NORMAL)
|
||||||
|
eq(d.bg_on['state'], NORMAL)
|
||||||
|
self.assertTrue(d.fg_bg_toggle)
|
||||||
|
eq(d.set_color_sample.called, 2)
|
||||||
|
|
||||||
|
d.set_highlight_target = Func()
|
||||||
|
|
||||||
|
def test_set_color_sample_binding(self):
|
||||||
|
d = dialog
|
||||||
|
scs = d.set_color_sample
|
||||||
|
|
||||||
|
d.fg_on.invoke()
|
||||||
|
self.assertEqual(scs.called, 1)
|
||||||
|
|
||||||
|
d.bg_on.invoke()
|
||||||
|
self.assertEqual(scs.called, 2)
|
||||||
|
|
||||||
|
def test_set_color_sample(self):
|
||||||
|
d = dialog
|
||||||
|
del d.set_color_sample
|
||||||
|
d.highlight_target.set('Selected Text')
|
||||||
|
d.fg_bg_toggle.set(True)
|
||||||
|
d.set_color_sample()
|
||||||
|
self.assertEqual(d.frame_color_set.cget('bg'),
|
||||||
|
d.highlight_sample.tag_cget('hilite', 'foreground'))
|
||||||
|
d.set_color_sample = Func()
|
||||||
|
|
||||||
|
def test_paint_theme_sample(self):
|
||||||
|
eq = self.assertEqual
|
||||||
|
d = dialog
|
||||||
|
del d.paint_theme_sample
|
||||||
|
hs_tag = d.highlight_sample.tag_cget
|
||||||
|
gh = idleConf.GetHighlight
|
||||||
|
fg = 'foreground'
|
||||||
|
bg = 'background'
|
||||||
|
|
||||||
|
# Create custom theme based on IDLE Dark.
|
||||||
|
d.theme_source.set(True)
|
||||||
|
d.builtin_name.set('IDLE Dark')
|
||||||
|
theme = 'IDLE Test'
|
||||||
|
d.create_new(theme)
|
||||||
|
d.set_color_sample.called = 0
|
||||||
|
|
||||||
|
# Base theme with nothing in `changes`.
|
||||||
|
d.paint_theme_sample()
|
||||||
|
eq(hs_tag('break', fg), gh(theme, 'break', fgBg='fg'))
|
||||||
|
eq(hs_tag('cursor', bg), gh(theme, 'normal', fgBg='bg'))
|
||||||
|
self.assertNotEqual(hs_tag('console', fg), 'blue')
|
||||||
|
self.assertNotEqual(hs_tag('console', bg), 'yellow')
|
||||||
|
eq(d.set_color_sample.called, 1)
|
||||||
|
|
||||||
|
# Apply changes.
|
||||||
|
changes.add_option('highlight', theme, 'console-foreground', 'blue')
|
||||||
|
changes.add_option('highlight', theme, 'console-background', 'yellow')
|
||||||
|
d.paint_theme_sample()
|
||||||
|
|
||||||
|
eq(hs_tag('break', fg), gh(theme, 'break', fgBg='fg'))
|
||||||
|
eq(hs_tag('cursor', bg), gh(theme, 'normal', fgBg='bg'))
|
||||||
|
eq(hs_tag('console', fg), 'blue')
|
||||||
|
eq(hs_tag('console', bg), 'yellow')
|
||||||
|
eq(d.set_color_sample.called, 2)
|
||||||
|
|
||||||
|
d.paint_theme_sample = Func()
|
||||||
|
|
||||||
|
def test_delete_custom(self):
|
||||||
|
eq = self.assertEqual
|
||||||
|
d = dialog
|
||||||
|
d.button_delete_custom['state'] = NORMAL
|
||||||
|
yesno = configdialog.tkMessageBox.askyesno = Func()
|
||||||
|
dialog.deactivate_current_config = Func()
|
||||||
|
dialog.activate_config_changes = Func()
|
||||||
|
|
||||||
|
theme_name = 'spam theme'
|
||||||
|
idleConf.userCfg['highlight'].SetOption(theme_name, 'name', 'value')
|
||||||
|
highpage[theme_name] = {'option': 'True'}
|
||||||
|
|
||||||
|
# Force custom theme.
|
||||||
|
d.theme_source.set(False)
|
||||||
|
d.custom_name.set(theme_name)
|
||||||
|
|
||||||
|
# Cancel deletion.
|
||||||
|
yesno.result = False
|
||||||
|
d.button_delete_custom.invoke()
|
||||||
|
eq(yesno.called, 1)
|
||||||
|
eq(highpage[theme_name], {'option': 'True'})
|
||||||
|
eq(idleConf.GetSectionList('user', 'highlight'), ['spam theme'])
|
||||||
|
eq(dialog.deactivate_current_config.called, 0)
|
||||||
|
eq(dialog.activate_config_changes.called, 0)
|
||||||
|
eq(d.set_theme_type.called, 0)
|
||||||
|
|
||||||
|
# Confirm deletion.
|
||||||
|
yesno.result = True
|
||||||
|
d.button_delete_custom.invoke()
|
||||||
|
eq(yesno.called, 2)
|
||||||
|
self.assertNotIn(theme_name, highpage)
|
||||||
|
eq(idleConf.GetSectionList('user', 'highlight'), [])
|
||||||
|
eq(d.custom_theme_on['state'], DISABLED)
|
||||||
|
eq(d.custom_name.get(), '- no custom themes -')
|
||||||
|
eq(dialog.deactivate_current_config.called, 1)
|
||||||
|
eq(dialog.activate_config_changes.called, 1)
|
||||||
|
eq(d.set_theme_type.called, 1)
|
||||||
|
|
||||||
|
del dialog.activate_config_changes, dialog.deactivate_current_config
|
||||||
|
del configdialog.tkMessageBox.askyesno
|
||||||
|
|
||||||
|
|
||||||
class KeysPageTest(unittest.TestCase):
|
class KeysPageTest(unittest.TestCase):
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add tests for configdialog highlight tab. Patch by Cheryl Sabella.
|
Loading…
Reference in New Issue