Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 42d5a4f

Browse files
rosemanterryjreedy
andauthored
bpo-33962: Use ttk spinbox for IDLE indent space config (GH-22954)
If ttk.Spinbox is not available (Tk < 8.5.9) use readonly ttk.Combobox. Co-authored-by: Terry Jan Reedy <[email protected]>
1 parent f82262b commit 42d5a4f

File tree

3 files changed

+73
-118
lines changed

3 files changed

+73
-118
lines changed

Lib/idlelib/configdialog.py

Lines changed: 62 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
StringVar, BooleanVar, IntVar, TRUE, FALSE,
1616
TOP, BOTTOM, RIGHT, LEFT, SOLID, GROOVE,
1717
NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW,
18-
HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END)
18+
HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END, TclError)
1919
from tkinter.ttk import (Frame, LabelFrame, Button, Checkbutton, Entry, Label,
20-
OptionMenu, Notebook, Radiobutton, Scrollbar, Style)
20+
OptionMenu, Notebook, Radiobutton, Scrollbar, Style,
21+
Spinbox, Combobox)
2122
from tkinter import colorchooser
2223
import tkinter.font as tkfont
2324
from 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
106108
107109
Methods:
108110
create_action_buttons
@@ -170,26 +172,15 @@ def create_action_buttons(self):
170172
return outer
171173

172174
def 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."""
179176
self.apply()
180177
self.destroy()
181178

182179
def 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."""
190181
self.deactivate_current_config()
191182
changes.save_all()
192-
self.save_all_changed_extensions()
183+
self.extpage.save_all_changed_extensions()
193184
self.activate_config_changes()
194185

195186
def cancel(self):
@@ -299,12 +290,11 @@ class FontPage(Frame):
299290
def __init__(self, master, highpage):
300291
super().__init__(master)
301292
self.highlight_sample = highpage.highlight_sample
302-
self.create_page_font_tab()
293+
self.create_page_font()
303294
self.load_font_cfg()
304-
self.load_tab_cfg()
305295

306-
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.
308298
309299
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.
330320
331-
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
"""
352334
self.font_name = tracers.add(StringVar(self), self.var_changed_font)
353335
self.font_size = tracers.add(StringVar(self), self.var_changed_font)
354336
self.font_bold = tracers.add(BooleanVar(self), self.var_changed_font)
355-
self.space_num = tracers.add(IntVar(self), ('main', 'Indent', 'num-spaces'))
356337

357338
# 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.
366344
frame_font_name = Frame(frame_font)
367345
frame_font_param = Frame(frame_font)
@@ -385,21 +363,13 @@ def create_page_font_tab(self):
385363
self.font_sample = font_sample_frame.text
386364
self.font_sample.config(wrap=NONE, width=1, height=1)
387365
self.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)
395366

396367
# Grid and pack widgets:
397368
self.columnconfigure(1, weight=1)
398369
self.rowconfigure(2, weight=1)
399370
frame_font.grid(row=0, column=0, padx=5, pady=5)
400371
frame_sample.grid(row=0, column=1, rowspan=3, padx=5, pady=5,
401372
sticky='nsew')
402-
frame_indent.grid(row=1, column=0, padx=5, pady=5, sticky='ew')
403373
# frame_font.
404374
frame_font_name.pack(side=TOP, padx=5, pady=5, fill=X)
405375
frame_font_param.pack(side=TOP, padx=5, pady=5, fill=X)
@@ -411,9 +381,6 @@ def create_page_font_tab(self):
411381
self.bold_toggle.pack(side=LEFT, anchor=W, padx=20)
412382
# frame_sample.
413383
font_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)
417384

418385
def load_font_cfg(self):
419386
"""Load current configuration settings for the font options.
@@ -487,22 +454,6 @@ def set_samples(self, event=None):
487454
self.font_sample['font'] = new_font
488455
self.highlight_sample['font'] = new_font
489456

490-
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-
506457

507458
class HighPage(Frame):
508459

@@ -515,7 +466,7 @@ def __init__(self, master, extpage):
515466
self.load_theme_cfg()
516467

517468
def create_page_highlight(self):
518-
"""Return frame of widgets for Highlighting tab.
469+
"""Return frame of widgets for Highlights tab.
519470
520471
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.
16181569
16191570
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.
16251576
1626-
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.
16561608
self.startup_edit = tracers.add(
@@ -1659,6 +1611,8 @@ def create_page_windows(self):
16591611
StringVar(self), ('main', 'EditorWindow', 'width'))
16601612
self.win_height = tracers.add(
16611613
StringVar(self), ('main', 'EditorWindow', 'height'))
1614+
self.indent_spaces = tracers.add(
1615+
StringVar(self), ('main', 'Indent', 'num-spaces'))
16621616
self.cursor_blink = tracers.add(
16631617
BooleanVar(self), ('main', 'EditorWindow', 'cursor-blink'))
16641618
self.autocomplete_wait = tracers.add(
@@ -1699,18 +1653,28 @@ def create_page_windows(self):
16991653
validatecommand=self.digits_only, validate='key',
17001654
)
17011655

1702-
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)
17061671

17071672
frame_autocomplete = Frame(frame_window, borderwidth=0,)
17081673
auto_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')
17141678

17151679
frame_paren1 = Frame(frame_window, borderwidth=0)
17161680
paren_style_title = Label(frame_paren1, text='Paren Match Style')
@@ -1722,7 +1686,8 @@ def create_page_windows(self):
17221686
frame_paren2, text='Time Match Displayed (milliseconds)\n'
17231687
'(0 is until next input)')
17241688
self.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')
17261691
self.bell_on = Checkbutton(
17271692
frame_paren2, text="Bell on Mismatch", variable=self.paren_bell)
17281693
frame_format = Frame(frame_window, borderwidth=0)
@@ -1747,10 +1712,11 @@ def create_page_windows(self):
17471712
win_height_title.pack(side=RIGHT, anchor=E, pady=5)
17481713
self.win_width_int.pack(side=RIGHT, anchor=E, padx=10, pady=5)
17491714
win_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.
17551721
frame_autocomplete.pack(side=TOP, padx=5, pady=0, fill=X)
17561722
auto_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'))
17771743
self.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'))
17791747
self.cursor_blink.set(idleConf.GetOption(
17801748
'main', 'EditorWindow', 'cursor-blink', type='bool'))
17811749
self.autocomplete_wait.set(idleConf.GetOption(

Lib/idlelib/idle_test/test_configdialog.py

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@ def test_click_ok(self):
7373
def test_click_apply(self):
7474
d = dialog
7575
deactivate = d.deactivate_current_config = mock.Mock()
76-
save_ext = d.save_all_changed_extensions = mock.Mock()
76+
save_ext = d.extpage.save_all_changed_extensions = mock.Mock()
7777
activate = d.activate_config_changes = mock.Mock()
7878
d.buttons['Apply'].invoke()
7979
deactivate.assert_called_once()
8080
save_ext.assert_called_once()
8181
activate.assert_called_once()
82-
del d.save_all_changed_extensions
82+
del d.extpage.save_all_changed_extensions
8383
del d.activate_config_changes, d.deactivate_current_config
8484

8585
def test_click_cancel(self):
@@ -260,27 +260,6 @@ def test_set_samples(self):
260260
d.set_samples = Func() # Re-mask for other tests.
261261

262262

263-
class IndentTest(unittest.TestCase):
264-
265-
@classmethod
266-
def setUpClass(cls):
267-
cls.page = dialog.fontpage
268-
cls.page.update()
269-
270-
def test_load_tab_cfg(self):
271-
d = self.page
272-
d.space_num.set(16)
273-
d.load_tab_cfg()
274-
self.assertEqual(d.space_num.get(), 4)
275-
276-
def test_indent_scale(self):
277-
d = self.page
278-
changes.clear()
279-
d.indent_scale.set(20)
280-
self.assertEqual(d.space_num.get(), 16)
281-
self.assertEqual(mainpage, {'Indent': {'num-spaces': '16'}})
282-
283-
284263
class HighPageTest(unittest.TestCase):
285264
"""Test that highlight tab widgets enable users to make changes.
286265
@@ -1250,6 +1229,12 @@ def test_editor_size(self):
12501229
d.win_width_int.insert(0, '11')
12511230
self.assertEqual(mainpage, {'EditorWindow': {'width': '11'}})
12521231

1232+
def test_indent_spaces(self):
1233+
d = self.page
1234+
d.indent_chooser.set(6)
1235+
self.assertEqual(d.indent_spaces.get(), '6')
1236+
self.assertEqual(mainpage, {'Indent': {'num-spaces': '6'}})
1237+
12531238
def test_cursor_blink(self):
12541239
self.page.cursor_blink_bool.invoke()
12551240
self.assertEqual(mainpage, {'EditorWindow': {'cursor-blink': 'False'}})
@@ -1278,7 +1263,7 @@ def test_paragraph(self):
12781263
self.assertEqual(extpage, {'FormatParagraph': {'max-width': '11'}})
12791264

12801265

1281-
class GenPageTest(unittest.TestCase):
1266+
class ShedPageTest(unittest.TestCase):
12821267
"""Test that shed tab widgets enable users to make changes.
12831268
12841269
Test that widget actions set vars, that var changes add
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Move the indent space setting from the Font tab to the new Windows tab.
2+
Patch by Mark Roseman and Terry Jan Reedy.

0 commit comments

Comments
 (0)