bpo-33962: Use ttk spinbox for IDLE indent space config (GH-22954) · python/cpython@9b88943

@@ -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

106108107109

Methods:

108110

create_action_buttons

@@ -170,26 +172,15 @@ def create_action_buttons(self):

170172

return outer

171173172174

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()

181178182179

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()

194185195186

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()

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

"""

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'))

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.

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)

395366396367

# 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)

417384418385

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

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-506457507458

class HighPage(Frame):

508459

@@ -515,7 +466,7 @@ def __init__(self, master, extpage):

515466

self.load_theme_cfg()

516467517468

def 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.

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

)

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)

1706167117071672

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')

1714167817151679

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(