bpo-33962: Use ttk spinbox for IDLE indent space config (GH-22954) · python/cpython@9b88943
@@ -15,9 +15,10 @@
1515StringVar, BooleanVar, IntVar, TRUE, FALSE,
1616TOP, BOTTOM, RIGHT, LEFT, SOLID, GROOVE,
1717NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW,
18-HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END)
18+HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END, TclError)
1919from tkinter.ttk import (Frame, LabelFrame, Button, Checkbutton, Entry, Label,
20-OptionMenu, Notebook, Radiobutton, Scrollbar, Style)
20+OptionMenu, Notebook, Radiobutton, Scrollbar, Style,
21+Spinbox, Combobox)
2122from tkinter import colorchooser
2223import tkinter.font as tkfont
2324from tkinter import messagebox
@@ -101,8 +102,9 @@ def create_widgets(self):
101102 highpage: HighPage
102103 fontpage: FontPage
103104 keyspage: KeysPage
104- genpage: GenPage
105- extpage: self.create_page_extensions
105+ winpage: WinPage
106+ shedpage: ShedPage
107+ extpage: ExtPage
106108107109 Methods:
108110 create_action_buttons
@@ -170,26 +172,15 @@ def create_action_buttons(self):
170172return outer
171173172174def ok(self):
173-"""Apply config changes, then dismiss dialog.
174-175- Methods:
176- apply
177- destroy: inherited
178- """
175+"""Apply config changes, then dismiss dialog."""
179176self.apply()
180177self.destroy()
181178182179def apply(self):
183-"""Apply config changes and leave dialog open.
184-185- Methods:
186- deactivate_current_config
187- save_all_changed_extensions
188- activate_config_changes
189- """
180+"""Apply config changes and leave dialog open."""
190181self.deactivate_current_config()
191182changes.save_all()
192-self.save_all_changed_extensions()
183+self.extpage.save_all_changed_extensions()
193184self.activate_config_changes()
194185195186def cancel(self):
@@ -299,12 +290,11 @@ class FontPage(Frame):
299290def __init__(self, master, highpage):
300291super().__init__(master)
301292self.highlight_sample = highpage.highlight_sample
302-self.create_page_font_tab()
293+self.create_page_font()
303294self.load_font_cfg()
304-self.load_tab_cfg()
305295306-def create_page_font_tab(self):
307-"""Return frame of widgets for Font/Tabs tab.
296+def create_page_font(self):
297+"""Return frame of widgets for Font tab.
308298309299 Fonts: Enable users to provisionally change font face, size, or
310300 boldness and to see the consequence of proposed choices. Each
@@ -328,11 +318,6 @@ def create_page_font_tab(self):
328318 Set_samples applies a new font constructed from the font vars to
329319 font_sample and to highlight_sample on the highlight page.
330320331- Tabs: Enable users to change spaces entered for indent tabs.
332- Changing indent_scale value with the mouse sets Var space_num,
333- which invokes the default callback to add an entry to
334- changes. Load_tab_cfg initializes space_num to default.
335-336321 Widgets for FontPage(Frame): (*) widgets bound to self
337322 frame_font: LabelFrame
338323 frame_font_name: Frame
@@ -345,23 +330,16 @@ def create_page_font_tab(self):
345330 (*)bold_toggle: Checkbutton - font_bold
346331 frame_sample: LabelFrame
347332 (*)font_sample: Label
348- frame_indent: LabelFrame
349- indent_title: Label
350- (*)indent_scale: Scale - space_num
351333 """
352334self.font_name = tracers.add(StringVar(self), self.var_changed_font)
353335self.font_size = tracers.add(StringVar(self), self.var_changed_font)
354336self.font_bold = tracers.add(BooleanVar(self), self.var_changed_font)
355-self.space_num = tracers.add(IntVar(self), ('main', 'Indent', 'num-spaces'))
356337357338# Define frames and widgets.
358-frame_font = LabelFrame(
359-self, borderwidth=2, relief=GROOVE, text=' Shell/Editor Font ')
360-frame_sample = LabelFrame(
361-self, borderwidth=2, relief=GROOVE,
362-text=' Font Sample (Editable) ')
363-frame_indent = LabelFrame(
364-self, borderwidth=2, relief=GROOVE, text=' Indentation Width ')
339+frame_font = LabelFrame(self, borderwidth=2, relief=GROOVE,
340+text=' Shell/Editor Font ')
341+frame_sample = LabelFrame(self, borderwidth=2, relief=GROOVE,
342+text=' Font Sample (Editable) ')
365343# frame_font.
366344frame_font_name = Frame(frame_font)
367345frame_font_param = Frame(frame_font)
@@ -385,21 +363,13 @@ def create_page_font_tab(self):
385363self.font_sample = font_sample_frame.text
386364self.font_sample.config(wrap=NONE, width=1, height=1)
387365self.font_sample.insert(END, font_sample_text)
388-# frame_indent.
389-indent_title = Label(
390-frame_indent, justify=LEFT,
391-text='Python Standard: 4 Spaces!')
392-self.indent_scale = Scale(
393-frame_indent, variable=self.space_num,
394-orient='horizontal', tickinterval=2, from_=2, to=16)
395366396367# Grid and pack widgets:
397368self.columnconfigure(1, weight=1)
398369self.rowconfigure(2, weight=1)
399370frame_font.grid(row=0, column=0, padx=5, pady=5)
400371frame_sample.grid(row=0, column=1, rowspan=3, padx=5, pady=5,
401372sticky='nsew')
402-frame_indent.grid(row=1, column=0, padx=5, pady=5, sticky='ew')
403373# frame_font.
404374frame_font_name.pack(side=TOP, padx=5, pady=5, fill=X)
405375frame_font_param.pack(side=TOP, padx=5, pady=5, fill=X)
@@ -411,9 +381,6 @@ def create_page_font_tab(self):
411381self.bold_toggle.pack(side=LEFT, anchor=W, padx=20)
412382# frame_sample.
413383font_sample_frame.pack(expand=TRUE, fill=BOTH)
414-# frame_indent.
415-indent_title.pack(side=TOP, anchor=W, padx=5)
416-self.indent_scale.pack(side=TOP, padx=5, fill=X)
417384418385def load_font_cfg(self):
419386"""Load current configuration settings for the font options.
@@ -487,22 +454,6 @@ def set_samples(self, event=None):
487454self.font_sample['font'] = new_font
488455self.highlight_sample['font'] = new_font
489456490-def load_tab_cfg(self):
491-"""Load current configuration settings for the tab options.
492-493- Attributes updated:
494- space_num: Set to value from idleConf.
495- """
496-# Set indent sizes.
497-space_num = idleConf.GetOption(
498-'main', 'Indent', 'num-spaces', default=4, type='int')
499-self.space_num.set(space_num)
500-501-def var_changed_space_num(self, *params):
502-"Store change to indentation size."
503-value = self.space_num.get()
504-changes.add_option('main', 'Indent', 'num-spaces', value)
505-506457507458class HighPage(Frame):
508459@@ -515,7 +466,7 @@ def __init__(self, master, extpage):
515466self.load_theme_cfg()
516467517468def create_page_highlight(self):
518-"""Return frame of widgets for Highlighting tab.
469+"""Return frame of widgets for Highlights tab.
519470520471 Enable users to provisionally change foreground and background
521472 colors applied to textual tags. Color mappings are stored in
@@ -1617,40 +1568,41 @@ def create_page_windows(self):
16171568"""Return frame of widgets for Windows tab.
1618156916191570 Enable users to provisionally change general window options.
1620- Function load_windows_cfg initializes tk variables idleConf.
1571+ Function load_windows_cfg initializes tk variable idleConf.
16211572 Radiobuttons startup_shell_on and startup_editor_on set var
16221573 startup_edit. Entry boxes win_width_int and win_height_int set var
16231574 win_width and win_height. Setting var_name invokes the default
16241575 callback that adds option to changes.
162515761626- Widgets for WinPage(Frame): (*) widgets bound to self
1577+ Widgets for WinPage(Frame): > vars, bound to self
16271578 frame_window: LabelFrame
16281579 frame_run: Frame
16291580 startup_title: Label
1630- (*)startup_editor_on: Radiobutton - startup_edit
1631- (*)startup_shell_on: Radiobutton - startup_edit
1581+ startup_editor_on: Radiobutton > startup_edit
1582+ startup_shell_on: Radiobutton > startup_edit
16321583 frame_win_size: Frame
16331584 win_size_title: Label
16341585 win_width_title: Label
1635- (*)win_width_int: Entry - win_width
1586+ win_width_int: Entry > win_width
16361587 win_height_title: Label
1637- (*)win_height_int: Entry - win_height
1638- frame_cursor_blink: Frame
1639- cursor_blink_title: Label
1640- (*)cursor_blink_bool: Checkbutton - cursor_blink
1588+ win_height_int: Entry > win_height
1589+ frame_cursor: Frame
1590+ indent_title: Label
1591+ indent_chooser: Spinbox (Combobox < 8.5.9) > indent_spaces
1592+ blink_on: Checkbutton > cursor_blink
16411593 frame_autocomplete: Frame
16421594 auto_wait_title: Label
1643- (*)auto_wait_int: Entry - autocomplete_wait
1595+ auto_wait_int: Entry > autocomplete_wait
16441596 frame_paren1: Frame
16451597 paren_style_title: Label
1646- (*)paren_style_type: OptionMenu - paren_style
1598+ paren_style_type: OptionMenu > paren_style
16471599 frame_paren2: Frame
16481600 paren_time_title: Label
1649- (*)paren_flash_time: Entry - flash_delay
1650- (*)bell_on: Checkbutton - paren_bell
1601+ paren_flash_time: Entry > flash_delay
1602+ bell_on: Checkbutton > paren_bell
16511603 frame_format: Frame
16521604 format_width_title: Label
1653- (*)format_width_int: Entry - format_width
1605+ format_width_int: Entry > format_width
16541606 """
16551607# Integer values need StringVar because int('') raises.
16561608self.startup_edit = tracers.add(
@@ -1659,6 +1611,8 @@ def create_page_windows(self):
16591611StringVar(self), ('main', 'EditorWindow', 'width'))
16601612self.win_height = tracers.add(
16611613StringVar(self), ('main', 'EditorWindow', 'height'))
1614+self.indent_spaces = tracers.add(
1615+StringVar(self), ('main', 'Indent', 'num-spaces'))
16621616self.cursor_blink = tracers.add(
16631617BooleanVar(self), ('main', 'EditorWindow', 'cursor-blink'))
16641618self.autocomplete_wait = tracers.add(
@@ -1699,18 +1653,28 @@ def create_page_windows(self):
16991653validatecommand=self.digits_only, validate='key',
17001654 )
170116551702-frame_cursor_blink = Frame(frame_window, borderwidth=0)
1703-cursor_blink_title = Label(frame_cursor_blink, text='Cursor Blink')
1704-self.cursor_blink_bool = Checkbutton(frame_cursor_blink,
1705-variable=self.cursor_blink, width=1)
1656+frame_cursor = Frame(frame_window, borderwidth=0)
1657+indent_title = Label(frame_cursor,
1658+text='Indent spaces (4 is standard)')
1659+try:
1660+self.indent_chooser = Spinbox(
1661+frame_cursor, textvariable=self.indent_spaces,
1662+from_=1, to=10, width=2,
1663+validatecommand=self.digits_only, validate='key')
1664+except TclError:
1665+self.indent_chooser = Combobox(
1666+frame_cursor, textvariable=self.indent_spaces,
1667+state="readonly", values=list(range(1,11)), width=3)
1668+cursor_blink_title = Label(frame_cursor, text='Cursor Blink')
1669+self.cursor_blink_bool = Checkbutton(frame_cursor, text="Cursor blink",
1670+variable=self.cursor_blink)
1706167117071672frame_autocomplete = Frame(frame_window, borderwidth=0,)
17081673auto_wait_title = Label(frame_autocomplete,
1709-text='Completions Popup Wait (milliseconds)')
1710-self.auto_wait_int = Entry(frame_autocomplete, width=6,
1711-textvariable=self.autocomplete_wait,
1712-validatecommand=self.digits_only,
1713-validate='key')
1674+text='Completions Popup Wait (milliseconds)')
1675+self.auto_wait_int = Entry(
1676+frame_autocomplete, textvariable=self.autocomplete_wait,
1677+width=6, validatecommand=self.digits_only, validate='key')
1714167817151679frame_paren1 = Frame(frame_window, borderwidth=0)
17161680paren_style_title = Label(frame_paren1, text='Paren Match Style')
@@ -1722,7 +1686,8 @@ def create_page_windows(self):
17221686frame_paren2, text='Time Match Displayed (milliseconds)\n'
17231687'(0 is until next input)')
17241688self.paren_flash_time = Entry(
1725-frame_paren2, textvariable=self.flash_delay, width=6)
1689+frame_paren2, textvariable=self.flash_delay, width=6,
1690+validatecommand=self.digits_only, validate='key')
17261691self.bell_on = Checkbutton(
17271692frame_paren2, text="Bell on Mismatch", variable=self.paren_bell)
17281693frame_format = Frame(frame_window, borderwidth=0)
@@ -1747,10 +1712,11 @@ def create_page_windows(self):
17471712win_height_title.pack(side=RIGHT, anchor=E, pady=5)
17481713self.win_width_int.pack(side=RIGHT, anchor=E, padx=10, pady=5)
17491714win_width_title.pack(side=RIGHT, anchor=E, pady=5)
1750-# frame_cursor_blink.
1751-frame_cursor_blink.pack(side=TOP, padx=5, pady=0, fill=X)
1752-cursor_blink_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
1753-self.cursor_blink_bool.pack(side=LEFT, padx=5, pady=5)
1715+# frame_cursor.
1716+frame_cursor.pack(side=TOP, padx=5, pady=0, fill=X)
1717+indent_title.pack(side=LEFT, anchor=W, padx=5)
1718+self.indent_chooser.pack(side=LEFT, anchor=W, padx=10)
1719+self.cursor_blink_bool.pack(side=RIGHT, anchor=E, padx=15, pady=5)
17541720# frame_autocomplete.
17551721frame_autocomplete.pack(side=TOP, padx=5, pady=0, fill=X)
17561722auto_wait_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
@@ -1776,6 +1742,8 @@ def load_windows_cfg(self):
17761742'main', 'EditorWindow', 'width', type='int'))
17771743self.win_height.set(idleConf.GetOption(
17781744'main', 'EditorWindow', 'height', type='int'))
1745+self.indent_spaces.set(idleConf.GetOption(
1746+'main', 'Indent', 'num-spaces', type='int'))
17791747self.cursor_blink.set(idleConf.GetOption(
17801748'main', 'EditorWindow', 'cursor-blink', type='bool'))
17811749self.autocomplete_wait.set(idleConf.GetOption(