diff options
Diffstat (limited to 'Lib/idlelib/configDialog.py')
| -rw-r--r-- | Lib/idlelib/configDialog.py | 1439 | 
1 files changed, 0 insertions, 1439 deletions
| diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py deleted file mode 100644 index d19749a07e..0000000000 --- a/Lib/idlelib/configDialog.py +++ /dev/null @@ -1,1439 +0,0 @@ -"""IDLE Configuration Dialog: support user customization of IDLE by GUI - -Customize font faces, sizes, and colorization attributes.  Set indentation -defaults.  Customize keybindings.  Colorization and keybindings can be -saved as user defined sets.  Select startup options including shell/editor -and default window size.  Define additional help sources. - -Note that tab width in IDLE is currently fixed at eight due to Tk issues. -Refer to comments in EditorWindow autoindent code for details. - -""" -from tkinter import * -from tkinter.ttk import Scrollbar -import tkinter.messagebox as tkMessageBox -import tkinter.colorchooser as tkColorChooser -import tkinter.font as tkFont - -from idlelib.config import idleConf -from idlelib.dynoption import DynOptionMenu -from idlelib.config_key import GetKeysDialog -from idlelib.config_sec import GetCfgSectionNameDialog -from idlelib.config_help import GetHelpSourceDialog -from idlelib.tabbedpages import TabbedPageSet -from idlelib.textview import view_text -from idlelib import macosx - -class ConfigDialog(Toplevel): - -    def __init__(self, parent, title='', _htest=False, _utest=False): -        """ -        _htest - bool, change box location when running htest -        _utest - bool, don't wait_window when running unittest -        """ -        Toplevel.__init__(self, parent) -        self.parent = parent -        if _htest: -            parent.instance_dict = {} -        self.wm_withdraw() - -        self.configure(borderwidth=5) -        self.title(title or 'IDLE Preferences') -        self.geometry( -                "+%d+%d" % (parent.winfo_rootx() + 20, -                parent.winfo_rooty() + (30 if not _htest else 150))) -        #Theme Elements. Each theme element key is its display name. -        #The first value of the tuple is the sample area tag name. -        #The second value is the display name list sort index. -        self.themeElements={ -            'Normal Text': ('normal', '00'), -            'Python Keywords': ('keyword', '01'), -            'Python Definitions': ('definition', '02'), -            'Python Builtins': ('builtin', '03'), -            'Python Comments': ('comment', '04'), -            'Python Strings': ('string', '05'), -            'Selected Text': ('hilite', '06'), -            'Found Text': ('hit', '07'), -            'Cursor': ('cursor', '08'), -            'Editor Breakpoint': ('break', '09'), -            'Shell Normal Text': ('console', '10'), -            'Shell Error Text': ('error', '11'), -            'Shell Stdout Text': ('stdout', '12'), -            'Shell Stderr Text': ('stderr', '13'), -            } -        self.ResetChangedItems() #load initial values in changed items dict -        self.CreateWidgets() -        self.resizable(height=FALSE, width=FALSE) -        self.transient(parent) -        self.grab_set() -        self.protocol("WM_DELETE_WINDOW", self.Cancel) -        self.tabPages.focus_set() -        #key bindings for this dialog -        #self.bind('<Escape>', self.Cancel) #dismiss dialog, no save -        #self.bind('<Alt-a>', self.Apply) #apply changes, save -        #self.bind('<F1>', self.Help) #context help -        self.LoadConfigs() -        self.AttachVarCallbacks() #avoid callbacks during LoadConfigs - -        if not _utest: -            self.wm_deiconify() -            self.wait_window() - -    def CreateWidgets(self): -        self.tabPages = TabbedPageSet(self, -                page_names=['Fonts/Tabs', 'Highlighting', 'Keys', 'General', -                            'Extensions']) -        self.tabPages.pack(side=TOP, expand=TRUE, fill=BOTH) -        self.CreatePageFontTab() -        self.CreatePageHighlight() -        self.CreatePageKeys() -        self.CreatePageGeneral() -        self.CreatePageExtensions() -        self.create_action_buttons().pack(side=BOTTOM) - -    def create_action_buttons(self): -        if macosx.isAquaTk(): -            # Changing the default padding on OSX results in unreadable -            # text in the buttons -            paddingArgs = {} -        else: -            paddingArgs = {'padx':6, 'pady':3} -        outer = Frame(self, pady=2) -        buttons = Frame(outer, pady=2) -        for txt, cmd in ( -            ('Ok', self.Ok), -            ('Apply', self.Apply), -            ('Cancel', self.Cancel), -            ('Help', self.Help)): -            Button(buttons, text=txt, command=cmd, takefocus=FALSE, -                   **paddingArgs).pack(side=LEFT, padx=5) -        # add space above buttons -        Frame(outer, height=2, borderwidth=0).pack(side=TOP) -        buttons.pack(side=BOTTOM) -        return outer - -    def CreatePageFontTab(self): -        parent = self.parent -        self.fontSize = StringVar(parent) -        self.fontBold = BooleanVar(parent) -        self.fontName = StringVar(parent) -        self.spaceNum = IntVar(parent) -        self.editFont = tkFont.Font(parent, ('courier', 10, 'normal')) - -        ##widget creation -        #body frame -        frame = self.tabPages.pages['Fonts/Tabs'].frame -        #body section frames -        frameFont = LabelFrame( -                frame, borderwidth=2, relief=GROOVE, text=' Base Editor Font ') -        frameIndent = LabelFrame( -                frame, borderwidth=2, relief=GROOVE, text=' Indentation Width ') -        #frameFont -        frameFontName = Frame(frameFont) -        frameFontParam = Frame(frameFont) -        labelFontNameTitle = Label( -                frameFontName, justify=LEFT, text='Font Face :') -        self.listFontName = Listbox( -                frameFontName, height=5, takefocus=FALSE, exportselection=FALSE) -        self.listFontName.bind( -                '<ButtonRelease-1>', self.OnListFontButtonRelease) -        scrollFont = Scrollbar(frameFontName) -        scrollFont.config(command=self.listFontName.yview) -        self.listFontName.config(yscrollcommand=scrollFont.set) -        labelFontSizeTitle = Label(frameFontParam, text='Size :') -        self.optMenuFontSize = DynOptionMenu( -                frameFontParam, self.fontSize, None, command=self.SetFontSample) -        checkFontBold = Checkbutton( -                frameFontParam, variable=self.fontBold, onvalue=1, -                offvalue=0, text='Bold', command=self.SetFontSample) -        frameFontSample = Frame(frameFont, relief=SOLID, borderwidth=1) -        self.labelFontSample = Label( -                frameFontSample, justify=LEFT, font=self.editFont, -                text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]') -        #frameIndent -        frameIndentSize = Frame(frameIndent) -        labelSpaceNumTitle = Label( -                frameIndentSize, justify=LEFT, -                text='Python Standard: 4 Spaces!') -        self.scaleSpaceNum = Scale( -                frameIndentSize, variable=self.spaceNum, -                orient='horizontal', tickinterval=2, from_=2, to=16) - -        #widget packing -        #body -        frameFont.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) -        frameIndent.pack(side=LEFT, padx=5, pady=5, fill=Y) -        #frameFont -        frameFontName.pack(side=TOP, padx=5, pady=5, fill=X) -        frameFontParam.pack(side=TOP, padx=5, pady=5, fill=X) -        labelFontNameTitle.pack(side=TOP, anchor=W) -        self.listFontName.pack(side=LEFT, expand=TRUE, fill=X) -        scrollFont.pack(side=LEFT, fill=Y) -        labelFontSizeTitle.pack(side=LEFT, anchor=W) -        self.optMenuFontSize.pack(side=LEFT, anchor=W) -        checkFontBold.pack(side=LEFT, anchor=W, padx=20) -        frameFontSample.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) -        self.labelFontSample.pack(expand=TRUE, fill=BOTH) -        #frameIndent -        frameIndentSize.pack(side=TOP, fill=X) -        labelSpaceNumTitle.pack(side=TOP, anchor=W, padx=5) -        self.scaleSpaceNum.pack(side=TOP, padx=5, fill=X) -        return frame - -    def CreatePageHighlight(self): -        parent = self.parent -        self.builtinTheme = StringVar(parent) -        self.customTheme = StringVar(parent) -        self.fgHilite = BooleanVar(parent) -        self.colour = StringVar(parent) -        self.fontName = StringVar(parent) -        self.themeIsBuiltin = BooleanVar(parent) -        self.highlightTarget = StringVar(parent) - -        ##widget creation -        #body frame -        frame = self.tabPages.pages['Highlighting'].frame -        #body section frames -        frameCustom = LabelFrame(frame, borderwidth=2, relief=GROOVE, -                                 text=' Custom Highlighting ') -        frameTheme = LabelFrame(frame, borderwidth=2, relief=GROOVE, -                                text=' Highlighting Theme ') -        #frameCustom -        self.textHighlightSample=Text( -                frameCustom, relief=SOLID, borderwidth=1, -                font=('courier', 12, ''), cursor='hand2', width=21, height=11, -                takefocus=FALSE, highlightthickness=0, wrap=NONE) -        text=self.textHighlightSample -        text.bind('<Double-Button-1>', lambda e: 'break') -        text.bind('<B1-Motion>', lambda e: 'break') -        textAndTags=( -            ('#you can click here', 'comment'), ('\n', 'normal'), -            ('#to choose items', 'comment'), ('\n', 'normal'), -            ('def', 'keyword'), (' ', 'normal'), -            ('func', 'definition'), ('(param):\n  ', 'normal'), -            ('"""string"""', 'string'), ('\n  var0 = ', 'normal'), -            ("'string'", 'string'), ('\n  var1 = ', 'normal'), -            ("'selected'", 'hilite'), ('\n  var2 = ', 'normal'), -            ("'found'", 'hit'), ('\n  var3 = ', 'normal'), -            ('list', 'builtin'), ('(', 'normal'), -            ('None', 'keyword'), (')\n', 'normal'), -            ('  breakpoint("line")', 'break'), ('\n\n', 'normal'), -            (' error ', 'error'), (' ', 'normal'), -            ('cursor |', 'cursor'), ('\n ', 'normal'), -            ('shell', 'console'), (' ', 'normal'), -            ('stdout', 'stdout'), (' ', 'normal'), -            ('stderr', 'stderr'), ('\n', 'normal')) -        for txTa in textAndTags: -            text.insert(END, txTa[0], txTa[1]) -        for element in self.themeElements: -            def tem(event, elem=element): -                event.widget.winfo_toplevel().highlightTarget.set(elem) -            text.tag_bind( -                    self.themeElements[element][0], '<ButtonPress-1>', tem) -        text.config(state=DISABLED) -        self.frameColourSet = Frame(frameCustom, relief=SOLID, borderwidth=1) -        frameFgBg = Frame(frameCustom) -        buttonSetColour = Button( -                self.frameColourSet, text='Choose Colour for :', -                command=self.GetColour, highlightthickness=0) -        self.optMenuHighlightTarget = DynOptionMenu( -                self.frameColourSet, self.highlightTarget, None, -                highlightthickness=0) #, command=self.SetHighlightTargetBinding -        self.radioFg = Radiobutton( -                frameFgBg, variable=self.fgHilite, value=1, -                text='Foreground', command=self.SetColourSampleBinding) -        self.radioBg=Radiobutton( -                frameFgBg, variable=self.fgHilite, value=0, -                text='Background', command=self.SetColourSampleBinding) -        self.fgHilite.set(1) -        buttonSaveCustomTheme = Button( -                frameCustom, text='Save as New Custom Theme', -                command=self.SaveAsNewTheme) -        #frameTheme -        labelTypeTitle = Label(frameTheme, text='Select : ') -        self.radioThemeBuiltin = Radiobutton( -                frameTheme, variable=self.themeIsBuiltin, value=1, -                command=self.SetThemeType, text='a Built-in Theme') -        self.radioThemeCustom = Radiobutton( -                frameTheme, variable=self.themeIsBuiltin, value=0, -                command=self.SetThemeType, text='a Custom Theme') -        self.optMenuThemeBuiltin = DynOptionMenu( -                frameTheme, self.builtinTheme, None, command=None) -        self.optMenuThemeCustom=DynOptionMenu( -                frameTheme, self.customTheme, None, command=None) -        self.buttonDeleteCustomTheme=Button( -                frameTheme, text='Delete Custom Theme', -                command=self.DeleteCustomTheme) -        self.new_custom_theme = Label(frameTheme, bd=2) - -        ##widget packing -        #body -        frameCustom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) -        frameTheme.pack(side=LEFT, padx=5, pady=5, fill=Y) -        #frameCustom -        self.frameColourSet.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X) -        frameFgBg.pack(side=TOP, padx=5, pady=0) -        self.textHighlightSample.pack( -                side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) -        buttonSetColour.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=4) -        self.optMenuHighlightTarget.pack( -                side=TOP, expand=TRUE, fill=X, padx=8, pady=3) -        self.radioFg.pack(side=LEFT, anchor=E) -        self.radioBg.pack(side=RIGHT, anchor=W) -        buttonSaveCustomTheme.pack(side=BOTTOM, fill=X, padx=5, pady=5) -        #frameTheme -        labelTypeTitle.pack(side=TOP, anchor=W, padx=5, pady=5) -        self.radioThemeBuiltin.pack(side=TOP, anchor=W, padx=5) -        self.radioThemeCustom.pack(side=TOP, anchor=W, padx=5, pady=2) -        self.optMenuThemeBuiltin.pack(side=TOP, fill=X, padx=5, pady=5) -        self.optMenuThemeCustom.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5) -        self.buttonDeleteCustomTheme.pack(side=TOP, fill=X, padx=5, pady=5) -        self.new_custom_theme.pack(side=TOP, fill=X, pady=5) -        return frame - -    def CreatePageKeys(self): -        parent = self.parent -        self.bindingTarget = StringVar(parent) -        self.builtinKeys = StringVar(parent) -        self.customKeys = StringVar(parent) -        self.keysAreBuiltin = BooleanVar(parent) -        self.keyBinding = StringVar(parent) - -        ##widget creation -        #body frame -        frame = self.tabPages.pages['Keys'].frame -        #body section frames -        frameCustom = LabelFrame( -                frame, borderwidth=2, relief=GROOVE, -                text=' Custom Key Bindings ') -        frameKeySets = LabelFrame( -                frame, borderwidth=2, relief=GROOVE, text=' Key Set ') -        #frameCustom -        frameTarget = Frame(frameCustom) -        labelTargetTitle = Label(frameTarget, text='Action - Key(s)') -        scrollTargetY = Scrollbar(frameTarget) -        scrollTargetX = Scrollbar(frameTarget, orient=HORIZONTAL) -        self.listBindings = Listbox( -                frameTarget, takefocus=FALSE, exportselection=FALSE) -        self.listBindings.bind('<ButtonRelease-1>', self.KeyBindingSelected) -        scrollTargetY.config(command=self.listBindings.yview) -        scrollTargetX.config(command=self.listBindings.xview) -        self.listBindings.config(yscrollcommand=scrollTargetY.set) -        self.listBindings.config(xscrollcommand=scrollTargetX.set) -        self.buttonNewKeys = Button( -                frameCustom, text='Get New Keys for Selection', -                command=self.GetNewKeys, state=DISABLED) -        #frameKeySets -        frames = [Frame(frameKeySets, padx=2, pady=2, borderwidth=0) -                  for i in range(2)] -        self.radioKeysBuiltin = Radiobutton( -                frames[0], variable=self.keysAreBuiltin, value=1, -                command=self.SetKeysType, text='Use a Built-in Key Set') -        self.radioKeysCustom = Radiobutton( -                frames[0], variable=self.keysAreBuiltin,  value=0, -                command=self.SetKeysType, text='Use a Custom Key Set') -        self.optMenuKeysBuiltin = DynOptionMenu( -                frames[0], self.builtinKeys, None, command=None) -        self.optMenuKeysCustom = DynOptionMenu( -                frames[0], self.customKeys, None, command=None) -        self.buttonDeleteCustomKeys = Button( -                frames[1], text='Delete Custom Key Set', -                command=self.DeleteCustomKeys) -        buttonSaveCustomKeys = Button( -                frames[1], text='Save as New Custom Key Set', -                command=self.SaveAsNewKeySet) - -        ##widget packing -        #body -        frameCustom.pack(side=BOTTOM, padx=5, pady=5, expand=TRUE, fill=BOTH) -        frameKeySets.pack(side=BOTTOM, padx=5, pady=5, fill=BOTH) -        #frameCustom -        self.buttonNewKeys.pack(side=BOTTOM, fill=X, padx=5, pady=5) -        frameTarget.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) -        #frame target -        frameTarget.columnconfigure(0, weight=1) -        frameTarget.rowconfigure(1, weight=1) -        labelTargetTitle.grid(row=0, column=0, columnspan=2, sticky=W) -        self.listBindings.grid(row=1, column=0, sticky=NSEW) -        scrollTargetY.grid(row=1, column=1, sticky=NS) -        scrollTargetX.grid(row=2, column=0, sticky=EW) -        #frameKeySets -        self.radioKeysBuiltin.grid(row=0, column=0, sticky=W+NS) -        self.radioKeysCustom.grid(row=1, column=0, sticky=W+NS) -        self.optMenuKeysBuiltin.grid(row=0, column=1, sticky=NSEW) -        self.optMenuKeysCustom.grid(row=1, column=1, sticky=NSEW) -        self.buttonDeleteCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2) -        buttonSaveCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2) -        frames[0].pack(side=TOP, fill=BOTH, expand=True) -        frames[1].pack(side=TOP, fill=X, expand=True, pady=2) -        return frame - -    def CreatePageGeneral(self): -        parent = self.parent -        self.winWidth = StringVar(parent) -        self.winHeight = StringVar(parent) -        self.startupEdit = IntVar(parent) -        self.autoSave = IntVar(parent) -        self.encoding = StringVar(parent) -        self.userHelpBrowser = BooleanVar(parent) -        self.helpBrowser = StringVar(parent) - -        #widget creation -        #body -        frame = self.tabPages.pages['General'].frame -        #body section frames -        frameRun = LabelFrame(frame, borderwidth=2, relief=GROOVE, -                              text=' Startup Preferences ') -        frameSave = LabelFrame(frame, borderwidth=2, relief=GROOVE, -                               text=' Autosave Preferences ') -        frameWinSize = Frame(frame, borderwidth=2, relief=GROOVE) -        frameHelp = LabelFrame(frame, borderwidth=2, relief=GROOVE, -                               text=' Additional Help Sources ') -        #frameRun -        labelRunChoiceTitle = Label(frameRun, text='At Startup') -        radioStartupEdit = Radiobutton( -                frameRun, variable=self.startupEdit, value=1, -                command=self.SetKeysType, text="Open Edit Window") -        radioStartupShell = Radiobutton( -                frameRun, variable=self.startupEdit, value=0, -                command=self.SetKeysType, text='Open Shell Window') -        #frameSave -        labelRunSaveTitle = Label(frameSave, text='At Start of Run (F5)  ') -        radioSaveAsk = Radiobutton( -                frameSave, variable=self.autoSave, value=0, -                command=self.SetKeysType, text="Prompt to Save") -        radioSaveAuto = Radiobutton( -                frameSave, variable=self.autoSave, value=1, -                command=self.SetKeysType, text='No Prompt') -        #frameWinSize -        labelWinSizeTitle = Label( -                frameWinSize, text='Initial Window Size  (in characters)') -        labelWinWidthTitle = Label(frameWinSize, text='Width') -        entryWinWidth = Entry( -                frameWinSize, textvariable=self.winWidth, width=3) -        labelWinHeightTitle = Label(frameWinSize, text='Height') -        entryWinHeight = Entry( -                frameWinSize, textvariable=self.winHeight, width=3) -        #frameHelp -        frameHelpList = Frame(frameHelp) -        frameHelpListButtons = Frame(frameHelpList) -        scrollHelpList = Scrollbar(frameHelpList) -        self.listHelp = Listbox( -                frameHelpList, height=5, takefocus=FALSE, -                exportselection=FALSE) -        scrollHelpList.config(command=self.listHelp.yview) -        self.listHelp.config(yscrollcommand=scrollHelpList.set) -        self.listHelp.bind('<ButtonRelease-1>', self.HelpSourceSelected) -        self.buttonHelpListEdit = Button( -                frameHelpListButtons, text='Edit', state=DISABLED, -                width=8, command=self.HelpListItemEdit) -        self.buttonHelpListAdd = Button( -                frameHelpListButtons, text='Add', -                width=8, command=self.HelpListItemAdd) -        self.buttonHelpListRemove = Button( -                frameHelpListButtons, text='Remove', state=DISABLED, -                width=8, command=self.HelpListItemRemove) - -        #widget packing -        #body -        frameRun.pack(side=TOP, padx=5, pady=5, fill=X) -        frameSave.pack(side=TOP, padx=5, pady=5, fill=X) -        frameWinSize.pack(side=TOP, padx=5, pady=5, fill=X) -        frameHelp.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) -        #frameRun -        labelRunChoiceTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) -        radioStartupShell.pack(side=RIGHT, anchor=W, padx=5, pady=5) -        radioStartupEdit.pack(side=RIGHT, anchor=W, padx=5, pady=5) -        #frameSave -        labelRunSaveTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) -        radioSaveAuto.pack(side=RIGHT, anchor=W, padx=5, pady=5) -        radioSaveAsk.pack(side=RIGHT, anchor=W, padx=5, pady=5) -        #frameWinSize -        labelWinSizeTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) -        entryWinHeight.pack(side=RIGHT, anchor=E, padx=10, pady=5) -        labelWinHeightTitle.pack(side=RIGHT, anchor=E, pady=5) -        entryWinWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5) -        labelWinWidthTitle.pack(side=RIGHT, anchor=E, pady=5) -        #frameHelp -        frameHelpListButtons.pack(side=RIGHT, padx=5, pady=5, fill=Y) -        frameHelpList.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) -        scrollHelpList.pack(side=RIGHT, anchor=W, fill=Y) -        self.listHelp.pack(side=LEFT, anchor=E, expand=TRUE, fill=BOTH) -        self.buttonHelpListEdit.pack(side=TOP, anchor=W, pady=5) -        self.buttonHelpListAdd.pack(side=TOP, anchor=W) -        self.buttonHelpListRemove.pack(side=TOP, anchor=W, pady=5) -        return frame - -    def AttachVarCallbacks(self): -        self.fontSize.trace_variable('w', self.VarChanged_font) -        self.fontName.trace_variable('w', self.VarChanged_font) -        self.fontBold.trace_variable('w', self.VarChanged_font) -        self.spaceNum.trace_variable('w', self.VarChanged_spaceNum) -        self.colour.trace_variable('w', self.VarChanged_colour) -        self.builtinTheme.trace_variable('w', self.VarChanged_builtinTheme) -        self.customTheme.trace_variable('w', self.VarChanged_customTheme) -        self.themeIsBuiltin.trace_variable('w', self.VarChanged_themeIsBuiltin) -        self.highlightTarget.trace_variable('w', self.VarChanged_highlightTarget) -        self.keyBinding.trace_variable('w', self.VarChanged_keyBinding) -        self.builtinKeys.trace_variable('w', self.VarChanged_builtinKeys) -        self.customKeys.trace_variable('w', self.VarChanged_customKeys) -        self.keysAreBuiltin.trace_variable('w', self.VarChanged_keysAreBuiltin) -        self.winWidth.trace_variable('w', self.VarChanged_winWidth) -        self.winHeight.trace_variable('w', self.VarChanged_winHeight) -        self.startupEdit.trace_variable('w', self.VarChanged_startupEdit) -        self.autoSave.trace_variable('w', self.VarChanged_autoSave) -        self.encoding.trace_variable('w', self.VarChanged_encoding) - -    def remove_var_callbacks(self): -        "Remove callbacks to prevent memory leaks." -        for var in ( -                self.fontSize, self.fontName, self.fontBold, -                self.spaceNum, self.colour, self.builtinTheme, -                self.customTheme, self.themeIsBuiltin, self.highlightTarget, -                self.keyBinding, self.builtinKeys, self.customKeys, -                self.keysAreBuiltin, self.winWidth, self.winHeight, -                self.startupEdit, self.autoSave, self.encoding,): -            var.trace_vdelete('w', var.trace_vinfo()[0][1]) - -    def VarChanged_font(self, *params): -        '''When one font attribute changes, save them all, as they are -        not independent from each other. In particular, when we are -        overriding the default font, we need to write out everything. -        ''' -        value = self.fontName.get() -        self.AddChangedItem('main', 'EditorWindow', 'font', value) -        value = self.fontSize.get() -        self.AddChangedItem('main', 'EditorWindow', 'font-size', value) -        value = self.fontBold.get() -        self.AddChangedItem('main', 'EditorWindow', 'font-bold', value) - -    def VarChanged_spaceNum(self, *params): -        value = self.spaceNum.get() -        self.AddChangedItem('main', 'Indent', 'num-spaces', value) - -    def VarChanged_colour(self, *params): -        self.OnNewColourSet() - -    def VarChanged_builtinTheme(self, *params): -        value = self.builtinTheme.get() -        if value == 'IDLE Dark': -            if idleConf.GetOption('main', 'Theme', 'name') != 'IDLE New': -                self.AddChangedItem('main', 'Theme', 'name', 'IDLE Classic') -            self.AddChangedItem('main', 'Theme', 'name2', value) -            self.new_custom_theme.config(text='New theme, see Help', -                                         fg='#500000') -        else: -            self.AddChangedItem('main', 'Theme', 'name', value) -            self.AddChangedItem('main', 'Theme', 'name2', '') -            self.new_custom_theme.config(text='', fg='black') -        self.PaintThemeSample() - -    def VarChanged_customTheme(self, *params): -        value = self.customTheme.get() -        if value != '- no custom themes -': -            self.AddChangedItem('main', 'Theme', 'name', value) -            self.PaintThemeSample() - -    def VarChanged_themeIsBuiltin(self, *params): -        value = self.themeIsBuiltin.get() -        self.AddChangedItem('main', 'Theme', 'default', value) -        if value: -            self.VarChanged_builtinTheme() -        else: -            self.VarChanged_customTheme() - -    def VarChanged_highlightTarget(self, *params): -        self.SetHighlightTarget() - -    def VarChanged_keyBinding(self, *params): -        value = self.keyBinding.get() -        keySet = self.customKeys.get() -        event = self.listBindings.get(ANCHOR).split()[0] -        if idleConf.IsCoreBinding(event): -            #this is a core keybinding -            self.AddChangedItem('keys', keySet, event, value) -        else: #this is an extension key binding -            extName = idleConf.GetExtnNameForEvent(event) -            extKeybindSection = extName + '_cfgBindings' -            self.AddChangedItem('extensions', extKeybindSection, event, value) - -    def VarChanged_builtinKeys(self, *params): -        value = self.builtinKeys.get() -        self.AddChangedItem('main', 'Keys', 'name', value) -        self.LoadKeysList(value) - -    def VarChanged_customKeys(self, *params): -        value = self.customKeys.get() -        if value != '- no custom keys -': -            self.AddChangedItem('main', 'Keys', 'name', value) -            self.LoadKeysList(value) - -    def VarChanged_keysAreBuiltin(self, *params): -        value = self.keysAreBuiltin.get() -        self.AddChangedItem('main', 'Keys', 'default', value) -        if value: -            self.VarChanged_builtinKeys() -        else: -            self.VarChanged_customKeys() - -    def VarChanged_winWidth(self, *params): -        value = self.winWidth.get() -        self.AddChangedItem('main', 'EditorWindow', 'width', value) - -    def VarChanged_winHeight(self, *params): -        value = self.winHeight.get() -        self.AddChangedItem('main', 'EditorWindow', 'height', value) - -    def VarChanged_startupEdit(self, *params): -        value = self.startupEdit.get() -        self.AddChangedItem('main', 'General', 'editor-on-startup', value) - -    def VarChanged_autoSave(self, *params): -        value = self.autoSave.get() -        self.AddChangedItem('main', 'General', 'autosave', value) - -    def VarChanged_encoding(self, *params): -        value = self.encoding.get() -        self.AddChangedItem('main', 'EditorWindow', 'encoding', value) - -    def ResetChangedItems(self): -        #When any config item is changed in this dialog, an entry -        #should be made in the relevant section (config type) of this -        #dictionary. The key should be the config file section name and the -        #value a dictionary, whose key:value pairs are item=value pairs for -        #that config file section. -        self.changedItems = {'main':{}, 'highlight':{}, 'keys':{}, -                             'extensions':{}} - -    def AddChangedItem(self, typ, section, item, value): -        value = str(value) #make sure we use a string -        if section not in self.changedItems[typ]: -            self.changedItems[typ][section] = {} -        self.changedItems[typ][section][item] = value - -    def GetDefaultItems(self): -        dItems={'main':{}, 'highlight':{}, 'keys':{}, 'extensions':{}} -        for configType in dItems: -            sections = idleConf.GetSectionList('default', configType) -            for section in sections: -                dItems[configType][section] = {} -                options = idleConf.defaultCfg[configType].GetOptionList(section) -                for option in options: -                    dItems[configType][section][option] = ( -                            idleConf.defaultCfg[configType].Get(section, option)) -        return dItems - -    def SetThemeType(self): -        if self.themeIsBuiltin.get(): -            self.optMenuThemeBuiltin.config(state=NORMAL) -            self.optMenuThemeCustom.config(state=DISABLED) -            self.buttonDeleteCustomTheme.config(state=DISABLED) -        else: -            self.optMenuThemeBuiltin.config(state=DISABLED) -            self.radioThemeCustom.config(state=NORMAL) -            self.optMenuThemeCustom.config(state=NORMAL) -            self.buttonDeleteCustomTheme.config(state=NORMAL) - -    def SetKeysType(self): -        if self.keysAreBuiltin.get(): -            self.optMenuKeysBuiltin.config(state=NORMAL) -            self.optMenuKeysCustom.config(state=DISABLED) -            self.buttonDeleteCustomKeys.config(state=DISABLED) -        else: -            self.optMenuKeysBuiltin.config(state=DISABLED) -            self.radioKeysCustom.config(state=NORMAL) -            self.optMenuKeysCustom.config(state=NORMAL) -            self.buttonDeleteCustomKeys.config(state=NORMAL) - -    def GetNewKeys(self): -        listIndex = self.listBindings.index(ANCHOR) -        binding = self.listBindings.get(listIndex) -        bindName = binding.split()[0] #first part, up to first space -        if self.keysAreBuiltin.get(): -            currentKeySetName = self.builtinKeys.get() -        else: -            currentKeySetName = self.customKeys.get() -        currentBindings = idleConf.GetCurrentKeySet() -        if currentKeySetName in self.changedItems['keys']: #unsaved changes -            keySetChanges = self.changedItems['keys'][currentKeySetName] -            for event in keySetChanges: -                currentBindings[event] = keySetChanges[event].split() -        currentKeySequences = list(currentBindings.values()) -        newKeys = GetKeysDialog(self, 'Get New Keys', bindName, -                currentKeySequences).result -        if newKeys: #new keys were specified -            if self.keysAreBuiltin.get(): #current key set is a built-in -                message = ('Your changes will be saved as a new Custom Key Set.' -                           ' Enter a name for your new Custom Key Set below.') -                newKeySet = self.GetNewKeysName(message) -                if not newKeySet: #user cancelled custom key set creation -                    self.listBindings.select_set(listIndex) -                    self.listBindings.select_anchor(listIndex) -                    return -                else: #create new custom key set based on previously active key set -                    self.CreateNewKeySet(newKeySet) -            self.listBindings.delete(listIndex) -            self.listBindings.insert(listIndex, bindName+' - '+newKeys) -            self.listBindings.select_set(listIndex) -            self.listBindings.select_anchor(listIndex) -            self.keyBinding.set(newKeys) -        else: -            self.listBindings.select_set(listIndex) -            self.listBindings.select_anchor(listIndex) - -    def GetNewKeysName(self, message): -        usedNames = (idleConf.GetSectionList('user', 'keys') + -                idleConf.GetSectionList('default', 'keys')) -        newKeySet = GetCfgSectionNameDialog( -                self, 'New Custom Key Set', message, usedNames).result -        return newKeySet - -    def SaveAsNewKeySet(self): -        newKeysName = self.GetNewKeysName('New Key Set Name:') -        if newKeysName: -            self.CreateNewKeySet(newKeysName) - -    def KeyBindingSelected(self, event): -        self.buttonNewKeys.config(state=NORMAL) - -    def CreateNewKeySet(self, newKeySetName): -        #creates new custom key set based on the previously active key set, -        #and makes the new key set active -        if self.keysAreBuiltin.get(): -            prevKeySetName = self.builtinKeys.get() -        else: -            prevKeySetName = self.customKeys.get() -        prevKeys = idleConf.GetCoreKeys(prevKeySetName) -        newKeys = {} -        for event in prevKeys: #add key set to changed items -            eventName = event[2:-2] #trim off the angle brackets -            binding = ' '.join(prevKeys[event]) -            newKeys[eventName] = binding -        #handle any unsaved changes to prev key set -        if prevKeySetName in self.changedItems['keys']: -            keySetChanges = self.changedItems['keys'][prevKeySetName] -            for event in keySetChanges: -                newKeys[event] = keySetChanges[event] -        #save the new theme -        self.SaveNewKeySet(newKeySetName, newKeys) -        #change gui over to the new key set -        customKeyList = idleConf.GetSectionList('user', 'keys') -        customKeyList.sort() -        self.optMenuKeysCustom.SetMenu(customKeyList, newKeySetName) -        self.keysAreBuiltin.set(0) -        self.SetKeysType() - -    def LoadKeysList(self, keySetName): -        reselect = 0 -        newKeySet = 0 -        if self.listBindings.curselection(): -            reselect = 1 -            listIndex = self.listBindings.index(ANCHOR) -        keySet = idleConf.GetKeySet(keySetName) -        bindNames = list(keySet.keys()) -        bindNames.sort() -        self.listBindings.delete(0, END) -        for bindName in bindNames: -            key = ' '.join(keySet[bindName]) #make key(s) into a string -            bindName = bindName[2:-2] #trim off the angle brackets -            if keySetName in self.changedItems['keys']: -                #handle any unsaved changes to this key set -                if bindName in self.changedItems['keys'][keySetName]: -                    key = self.changedItems['keys'][keySetName][bindName] -            self.listBindings.insert(END, bindName+' - '+key) -        if reselect: -            self.listBindings.see(listIndex) -            self.listBindings.select_set(listIndex) -            self.listBindings.select_anchor(listIndex) - -    def DeleteCustomKeys(self): -        keySetName=self.customKeys.get() -        delmsg = 'Are you sure you wish to delete the key set %r ?' -        if not tkMessageBox.askyesno( -                'Delete Key Set',  delmsg % keySetName, parent=self): -            return -        self.DeactivateCurrentConfig() -        #remove key set from config -        idleConf.userCfg['keys'].remove_section(keySetName) -        if keySetName in self.changedItems['keys']: -            del(self.changedItems['keys'][keySetName]) -        #write changes -        idleConf.userCfg['keys'].Save() -        #reload user key set list -        itemList = idleConf.GetSectionList('user', 'keys') -        itemList.sort() -        if not itemList: -            self.radioKeysCustom.config(state=DISABLED) -            self.optMenuKeysCustom.SetMenu(itemList, '- no custom keys -') -        else: -            self.optMenuKeysCustom.SetMenu(itemList, itemList[0]) -        #revert to default key set -        self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys', 'default')) -        self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys', 'name')) -        #user can't back out of these changes, they must be applied now -        self.SaveAllChangedConfigs() -        self.ActivateConfigChanges() -        self.SetKeysType() - -    def DeleteCustomTheme(self): -        themeName = self.customTheme.get() -        delmsg = 'Are you sure you wish to delete the theme %r ?' -        if not tkMessageBox.askyesno( -                'Delete Theme',  delmsg % themeName, parent=self): -            return -        self.DeactivateCurrentConfig() -        #remove theme from config -        idleConf.userCfg['highlight'].remove_section(themeName) -        if themeName in self.changedItems['highlight']: -            del(self.changedItems['highlight'][themeName]) -        #write changes -        idleConf.userCfg['highlight'].Save() -        #reload user theme list -        itemList = idleConf.GetSectionList('user', 'highlight') -        itemList.sort() -        if not itemList: -            self.radioThemeCustom.config(state=DISABLED) -            self.optMenuThemeCustom.SetMenu(itemList, '- no custom themes -') -        else: -            self.optMenuThemeCustom.SetMenu(itemList, itemList[0]) -        #revert to default theme -        self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme', 'default')) -        self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme', 'name')) -        #user can't back out of these changes, they must be applied now -        self.SaveAllChangedConfigs() -        self.ActivateConfigChanges() -        self.SetThemeType() - -    def GetColour(self): -        target = self.highlightTarget.get() -        prevColour = self.frameColourSet.cget('bg') -        rgbTuplet, colourString = tkColorChooser.askcolor( -                parent=self, title='Pick new colour for : '+target, -                initialcolor=prevColour) -        if colourString and (colourString != prevColour): -            #user didn't cancel, and they chose a new colour -            if self.themeIsBuiltin.get():  #current theme is a built-in -                message = ('Your changes will be saved as a new Custom Theme. ' -                           'Enter a name for your new Custom Theme below.') -                newTheme = self.GetNewThemeName(message) -                if not newTheme:  #user cancelled custom theme creation -                    return -                else:  #create new custom theme based on previously active theme -                    self.CreateNewTheme(newTheme) -                    self.colour.set(colourString) -            else:  #current theme is user defined -                self.colour.set(colourString) - -    def OnNewColourSet(self): -        newColour=self.colour.get() -        self.frameColourSet.config(bg=newColour)  #set sample -        plane ='foreground' if self.fgHilite.get() else 'background' -        sampleElement = self.themeElements[self.highlightTarget.get()][0] -        self.textHighlightSample.tag_config(sampleElement, **{plane:newColour}) -        theme = self.customTheme.get() -        themeElement = sampleElement + '-' + plane -        self.AddChangedItem('highlight', theme, themeElement, newColour) - -    def GetNewThemeName(self, message): -        usedNames = (idleConf.GetSectionList('user', 'highlight') + -                idleConf.GetSectionList('default', 'highlight')) -        newTheme = GetCfgSectionNameDialog( -                self, 'New Custom Theme', message, usedNames).result -        return newTheme - -    def SaveAsNewTheme(self): -        newThemeName = self.GetNewThemeName('New Theme Name:') -        if newThemeName: -            self.CreateNewTheme(newThemeName) - -    def CreateNewTheme(self, newThemeName): -        #creates new custom theme based on the previously active theme, -        #and makes the new theme active -        if self.themeIsBuiltin.get(): -            themeType = 'default' -            themeName = self.builtinTheme.get() -        else: -            themeType = 'user' -            themeName = self.customTheme.get() -        newTheme = idleConf.GetThemeDict(themeType, themeName) -        #apply any of the old theme's unsaved changes to the new theme -        if themeName in self.changedItems['highlight']: -            themeChanges = self.changedItems['highlight'][themeName] -            for element in themeChanges: -                newTheme[element] = themeChanges[element] -        #save the new theme -        self.SaveNewTheme(newThemeName, newTheme) -        #change gui over to the new theme -        customThemeList = idleConf.GetSectionList('user', 'highlight') -        customThemeList.sort() -        self.optMenuThemeCustom.SetMenu(customThemeList, newThemeName) -        self.themeIsBuiltin.set(0) -        self.SetThemeType() - -    def OnListFontButtonRelease(self, event): -        font = self.listFontName.get(ANCHOR) -        self.fontName.set(font.lower()) -        self.SetFontSample() - -    def SetFontSample(self, event=None): -        fontName = self.fontName.get() -        fontWeight = tkFont.BOLD if self.fontBold.get() else tkFont.NORMAL -        newFont = (fontName, self.fontSize.get(), fontWeight) -        self.labelFontSample.config(font=newFont) -        self.textHighlightSample.configure(font=newFont) - -    def SetHighlightTarget(self): -        if self.highlightTarget.get() == 'Cursor':  #bg not possible -            self.radioFg.config(state=DISABLED) -            self.radioBg.config(state=DISABLED) -            self.fgHilite.set(1) -        else:  #both fg and bg can be set -            self.radioFg.config(state=NORMAL) -            self.radioBg.config(state=NORMAL) -            self.fgHilite.set(1) -        self.SetColourSample() - -    def SetColourSampleBinding(self, *args): -        self.SetColourSample() - -    def SetColourSample(self): -        #set the colour smaple area -        tag = self.themeElements[self.highlightTarget.get()][0] -        plane = 'foreground' if self.fgHilite.get() else 'background' -        colour = self.textHighlightSample.tag_cget(tag, plane) -        self.frameColourSet.config(bg=colour) - -    def PaintThemeSample(self): -        if self.themeIsBuiltin.get():  #a default theme -            theme = self.builtinTheme.get() -        else:  #a user theme -            theme = self.customTheme.get() -        for elementTitle in self.themeElements: -            element = self.themeElements[elementTitle][0] -            colours = idleConf.GetHighlight(theme, element) -            if element == 'cursor': #cursor sample needs special painting -                colours['background'] = idleConf.GetHighlight( -                        theme, 'normal', fgBg='bg') -            #handle any unsaved changes to this theme -            if theme in self.changedItems['highlight']: -                themeDict = self.changedItems['highlight'][theme] -                if element + '-foreground' in themeDict: -                    colours['foreground'] = themeDict[element + '-foreground'] -                if element + '-background' in themeDict: -                    colours['background'] = themeDict[element + '-background'] -            self.textHighlightSample.tag_config(element, **colours) -        self.SetColourSample() - -    def HelpSourceSelected(self, event): -        self.SetHelpListButtonStates() - -    def SetHelpListButtonStates(self): -        if self.listHelp.size() < 1:  #no entries in list -            self.buttonHelpListEdit.config(state=DISABLED) -            self.buttonHelpListRemove.config(state=DISABLED) -        else: #there are some entries -            if self.listHelp.curselection():  #there currently is a selection -                self.buttonHelpListEdit.config(state=NORMAL) -                self.buttonHelpListRemove.config(state=NORMAL) -            else:  #there currently is not a selection -                self.buttonHelpListEdit.config(state=DISABLED) -                self.buttonHelpListRemove.config(state=DISABLED) - -    def HelpListItemAdd(self): -        helpSource = GetHelpSourceDialog(self, 'New Help Source').result -        if helpSource: -            self.userHelpList.append((helpSource[0], helpSource[1])) -            self.listHelp.insert(END, helpSource[0]) -            self.UpdateUserHelpChangedItems() -        self.SetHelpListButtonStates() - -    def HelpListItemEdit(self): -        itemIndex = self.listHelp.index(ANCHOR) -        helpSource = self.userHelpList[itemIndex] -        newHelpSource = GetHelpSourceDialog( -                self, 'Edit Help Source', menuItem=helpSource[0], -                filePath=helpSource[1]).result -        if (not newHelpSource) or (newHelpSource == helpSource): -            return #no changes -        self.userHelpList[itemIndex] = newHelpSource -        self.listHelp.delete(itemIndex) -        self.listHelp.insert(itemIndex, newHelpSource[0]) -        self.UpdateUserHelpChangedItems() -        self.SetHelpListButtonStates() - -    def HelpListItemRemove(self): -        itemIndex = self.listHelp.index(ANCHOR) -        del(self.userHelpList[itemIndex]) -        self.listHelp.delete(itemIndex) -        self.UpdateUserHelpChangedItems() -        self.SetHelpListButtonStates() - -    def UpdateUserHelpChangedItems(self): -        "Clear and rebuild the HelpFiles section in self.changedItems" -        self.changedItems['main']['HelpFiles'] = {} -        for num in range(1, len(self.userHelpList) + 1): -            self.AddChangedItem( -                    'main', 'HelpFiles', str(num), -                    ';'.join(self.userHelpList[num-1][:2])) - -    def LoadFontCfg(self): -        ##base editor font selection list -        fonts = list(tkFont.families(self)) -        fonts.sort() -        for font in fonts: -            self.listFontName.insert(END, font) -        configuredFont = idleConf.GetFont(self, 'main', 'EditorWindow') -        fontName = configuredFont[0].lower() -        fontSize = configuredFont[1] -        fontBold  = configuredFont[2]=='bold' -        self.fontName.set(fontName) -        lc_fonts = [s.lower() for s in fonts] -        try: -            currentFontIndex = lc_fonts.index(fontName) -            self.listFontName.see(currentFontIndex) -            self.listFontName.select_set(currentFontIndex) -            self.listFontName.select_anchor(currentFontIndex) -        except ValueError: -            pass -        ##font size dropdown -        self.optMenuFontSize.SetMenu(('7', '8', '9', '10', '11', '12', '13', -                                      '14', '16', '18', '20', '22'), fontSize ) -        ##fontWeight -        self.fontBold.set(fontBold) -        ##font sample -        self.SetFontSample() - -    def LoadTabCfg(self): -        ##indent sizes -        spaceNum = idleConf.GetOption( -            'main', 'Indent', 'num-spaces', default=4, type='int') -        self.spaceNum.set(spaceNum) - -    def LoadThemeCfg(self): -        ##current theme type radiobutton -        self.themeIsBuiltin.set(idleConf.GetOption( -                'main', 'Theme', 'default', type='bool', default=1)) -        ##currently set theme -        currentOption = idleConf.CurrentTheme() -        ##load available theme option menus -        if self.themeIsBuiltin.get(): #default theme selected -            itemList = idleConf.GetSectionList('default', 'highlight') -            itemList.sort() -            self.optMenuThemeBuiltin.SetMenu(itemList, currentOption) -            itemList = idleConf.GetSectionList('user', 'highlight') -            itemList.sort() -            if not itemList: -                self.radioThemeCustom.config(state=DISABLED) -                self.customTheme.set('- no custom themes -') -            else: -                self.optMenuThemeCustom.SetMenu(itemList, itemList[0]) -        else: #user theme selected -            itemList = idleConf.GetSectionList('user', 'highlight') -            itemList.sort() -            self.optMenuThemeCustom.SetMenu(itemList, currentOption) -            itemList = idleConf.GetSectionList('default', 'highlight') -            itemList.sort() -            self.optMenuThemeBuiltin.SetMenu(itemList, itemList[0]) -        self.SetThemeType() -        ##load theme element option menu -        themeNames = list(self.themeElements.keys()) -        themeNames.sort(key=lambda x: self.themeElements[x][1]) -        self.optMenuHighlightTarget.SetMenu(themeNames, themeNames[0]) -        self.PaintThemeSample() -        self.SetHighlightTarget() - -    def LoadKeyCfg(self): -        ##current keys type radiobutton -        self.keysAreBuiltin.set(idleConf.GetOption( -                'main', 'Keys', 'default', type='bool', default=1)) -        ##currently set keys -        currentOption = idleConf.CurrentKeys() -        ##load available keyset option menus -        if self.keysAreBuiltin.get(): #default theme selected -            itemList = idleConf.GetSectionList('default', 'keys') -            itemList.sort() -            self.optMenuKeysBuiltin.SetMenu(itemList, currentOption) -            itemList = idleConf.GetSectionList('user', 'keys') -            itemList.sort() -            if not itemList: -                self.radioKeysCustom.config(state=DISABLED) -                self.customKeys.set('- no custom keys -') -            else: -                self.optMenuKeysCustom.SetMenu(itemList, itemList[0]) -        else: #user key set selected -            itemList = idleConf.GetSectionList('user', 'keys') -            itemList.sort() -            self.optMenuKeysCustom.SetMenu(itemList, currentOption) -            itemList = idleConf.GetSectionList('default', 'keys') -            itemList.sort() -            self.optMenuKeysBuiltin.SetMenu(itemList, itemList[0]) -        self.SetKeysType() -        ##load keyset element list -        keySetName = idleConf.CurrentKeys() -        self.LoadKeysList(keySetName) - -    def LoadGeneralCfg(self): -        #startup state -        self.startupEdit.set(idleConf.GetOption( -                'main', 'General', 'editor-on-startup', default=1, type='bool')) -        #autosave state -        self.autoSave.set(idleConf.GetOption( -                'main', 'General', 'autosave', default=0, type='bool')) -        #initial window size -        self.winWidth.set(idleConf.GetOption( -                'main', 'EditorWindow', 'width', type='int')) -        self.winHeight.set(idleConf.GetOption( -                'main', 'EditorWindow', 'height', type='int')) -        # default source encoding -        self.encoding.set(idleConf.GetOption( -                'main', 'EditorWindow', 'encoding', default='none')) -        # additional help sources -        self.userHelpList = idleConf.GetAllExtraHelpSourcesList() -        for helpItem in self.userHelpList: -            self.listHelp.insert(END, helpItem[0]) -        self.SetHelpListButtonStates() - -    def LoadConfigs(self): -        """ -        load configuration from default and user config files and populate -        the widgets on the config dialog pages. -        """ -        ### fonts / tabs page -        self.LoadFontCfg() -        self.LoadTabCfg() -        ### highlighting page -        self.LoadThemeCfg() -        ### keys page -        self.LoadKeyCfg() -        ### general page -        self.LoadGeneralCfg() -        # note: extension page handled separately - -    def SaveNewKeySet(self, keySetName, keySet): -        """ -        save a newly created core key set. -        keySetName - string, the name of the new key set -        keySet - dictionary containing the new key set -        """ -        if not idleConf.userCfg['keys'].has_section(keySetName): -            idleConf.userCfg['keys'].add_section(keySetName) -        for event in keySet: -            value = keySet[event] -            idleConf.userCfg['keys'].SetOption(keySetName, event, value) - -    def SaveNewTheme(self, themeName, theme): -        """ -        save a newly created theme. -        themeName - string, the name of the new theme -        theme - dictionary containing the new theme -        """ -        if not idleConf.userCfg['highlight'].has_section(themeName): -            idleConf.userCfg['highlight'].add_section(themeName) -        for element in theme: -            value = theme[element] -            idleConf.userCfg['highlight'].SetOption(themeName, element, value) - -    def SetUserValue(self, configType, section, item, value): -        if idleConf.defaultCfg[configType].has_option(section, item): -            if idleConf.defaultCfg[configType].Get(section, item) == value: -                #the setting equals a default setting, remove it from user cfg -                return idleConf.userCfg[configType].RemoveOption(section, item) -        #if we got here set the option -        return idleConf.userCfg[configType].SetOption(section, item, value) - -    def SaveAllChangedConfigs(self): -        "Save configuration changes to the user config file." -        idleConf.userCfg['main'].Save() -        for configType in self.changedItems: -            cfgTypeHasChanges = False -            for section in self.changedItems[configType]: -                if section == 'HelpFiles': -                    #this section gets completely replaced -                    idleConf.userCfg['main'].remove_section('HelpFiles') -                    cfgTypeHasChanges = True -                for item in self.changedItems[configType][section]: -                    value = self.changedItems[configType][section][item] -                    if self.SetUserValue(configType, section, item, value): -                        cfgTypeHasChanges = True -            if cfgTypeHasChanges: -                idleConf.userCfg[configType].Save() -        for configType in ['keys', 'highlight']: -            # save these even if unchanged! -            idleConf.userCfg[configType].Save() -        self.ResetChangedItems() #clear the changed items dict -        self.save_all_changed_extensions()  # uses a different mechanism - -    def DeactivateCurrentConfig(self): -        #Before a config is saved, some cleanup of current -        #config must be done - remove the previous keybindings -        winInstances = self.parent.instance_dict.keys() -        for instance in winInstances: -            instance.RemoveKeybindings() - -    def ActivateConfigChanges(self): -        "Dynamically apply configuration changes" -        winInstances = self.parent.instance_dict.keys() -        for instance in winInstances: -            instance.ResetColorizer() -            instance.ResetFont() -            instance.set_notabs_indentwidth() -            instance.ApplyKeybindings() -            instance.reset_help_menu_entries() - -    def Cancel(self): -        self.destroy() - -    def Ok(self): -        self.Apply() -        self.destroy() - -    def Apply(self): -        self.DeactivateCurrentConfig() -        self.SaveAllChangedConfigs() -        self.ActivateConfigChanges() - -    def Help(self): -        page = self.tabPages._current_page -        view_text(self, title='Help for IDLE preferences', -                 text=help_common+help_pages.get(page, '')) - -    def CreatePageExtensions(self): -        """Part of the config dialog used for configuring IDLE extensions. - -        This code is generic - it works for any and all IDLE extensions. - -        IDLE extensions save their configuration options using idleConf. -        This code reads the current configuration using idleConf, supplies a -        GUI interface to change the configuration values, and saves the -        changes using idleConf. - -        Not all changes take effect immediately - some may require restarting IDLE. -        This depends on each extension's implementation. - -        All values are treated as text, and it is up to the user to supply -        reasonable values. The only exception to this are the 'enable*' options, -        which are boolean, and can be toggled with a True/False button. -        """ -        parent = self.parent -        frame = self.tabPages.pages['Extensions'].frame -        self.ext_defaultCfg = idleConf.defaultCfg['extensions'] -        self.ext_userCfg = idleConf.userCfg['extensions'] -        self.is_int = self.register(is_int) -        self.load_extensions() -        # create widgets - a listbox shows all available extensions, with the -        # controls for the extension selected in the listbox to the right -        self.extension_names = StringVar(self) -        frame.rowconfigure(0, weight=1) -        frame.columnconfigure(2, weight=1) -        self.extension_list = Listbox(frame, listvariable=self.extension_names, -                                      selectmode='browse') -        self.extension_list.bind('<<ListboxSelect>>', self.extension_selected) -        scroll = Scrollbar(frame, command=self.extension_list.yview) -        self.extension_list.yscrollcommand=scroll.set -        self.details_frame = LabelFrame(frame, width=250, height=250) -        self.extension_list.grid(column=0, row=0, sticky='nws') -        scroll.grid(column=1, row=0, sticky='ns') -        self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0]) -        frame.configure(padx=10, pady=10) -        self.config_frame = {} -        self.current_extension = None - -        self.outerframe = self                      # TEMPORARY -        self.tabbed_page_set = self.extension_list  # TEMPORARY - -        # create the frame holding controls for each extension -        ext_names = '' -        for ext_name in sorted(self.extensions): -            self.create_extension_frame(ext_name) -            ext_names = ext_names + '{' + ext_name + '} ' -        self.extension_names.set(ext_names) -        self.extension_list.selection_set(0) -        self.extension_selected(None) - -    def load_extensions(self): -        "Fill self.extensions with data from the default and user configs." -        self.extensions = {} -        for ext_name in idleConf.GetExtensions(active_only=False): -            self.extensions[ext_name] = [] - -        for ext_name in self.extensions: -            opt_list = sorted(self.ext_defaultCfg.GetOptionList(ext_name)) - -            # bring 'enable' options to the beginning of the list -            enables = [opt_name for opt_name in opt_list -                       if opt_name.startswith('enable')] -            for opt_name in enables: -                opt_list.remove(opt_name) -            opt_list = enables + opt_list - -            for opt_name in opt_list: -                def_str = self.ext_defaultCfg.Get( -                        ext_name, opt_name, raw=True) -                try: -                    def_obj = {'True':True, 'False':False}[def_str] -                    opt_type = 'bool' -                except KeyError: -                    try: -                        def_obj = int(def_str) -                        opt_type = 'int' -                    except ValueError: -                        def_obj = def_str -                        opt_type = None -                try: -                    value = self.ext_userCfg.Get( -                            ext_name, opt_name, type=opt_type, raw=True, -                            default=def_obj) -                except ValueError:  # Need this until .Get fixed -                    value = def_obj  # bad values overwritten by entry -                var = StringVar(self) -                var.set(str(value)) - -                self.extensions[ext_name].append({'name': opt_name, -                                                  'type': opt_type, -                                                  'default': def_str, -                                                  'value': value, -                                                  'var': var, -                                                 }) - -    def extension_selected(self, event): -        newsel = self.extension_list.curselection() -        if newsel: -            newsel = self.extension_list.get(newsel) -        if newsel is None or newsel != self.current_extension: -            if self.current_extension: -                self.details_frame.config(text='') -                self.config_frame[self.current_extension].grid_forget() -                self.current_extension = None -        if newsel: -            self.details_frame.config(text=newsel) -            self.config_frame[newsel].grid(column=0, row=0, sticky='nsew') -            self.current_extension = newsel - -    def create_extension_frame(self, ext_name): -        """Create a frame holding the widgets to configure one extension""" -        f = VerticalScrolledFrame(self.details_frame, height=250, width=250) -        self.config_frame[ext_name] = f -        entry_area = f.interior -        # create an entry for each configuration option -        for row, opt in enumerate(self.extensions[ext_name]): -            # create a row with a label and entry/checkbutton -            label = Label(entry_area, text=opt['name']) -            label.grid(row=row, column=0, sticky=NW) -            var = opt['var'] -            if opt['type'] == 'bool': -                Checkbutton(entry_area, textvariable=var, variable=var, -                            onvalue='True', offvalue='False', -                            indicatoron=FALSE, selectcolor='', width=8 -                            ).grid(row=row, column=1, sticky=W, padx=7) -            elif opt['type'] == 'int': -                Entry(entry_area, textvariable=var, validate='key', -                      validatecommand=(self.is_int, '%P') -                      ).grid(row=row, column=1, sticky=NSEW, padx=7) - -            else: -                Entry(entry_area, textvariable=var -                      ).grid(row=row, column=1, sticky=NSEW, padx=7) -        return - -    def set_extension_value(self, section, opt): -        name = opt['name'] -        default = opt['default'] -        value = opt['var'].get().strip() or default -        opt['var'].set(value) -        # if self.defaultCfg.has_section(section): -        # Currently, always true; if not, indent to return -        if (value == default): -            return self.ext_userCfg.RemoveOption(section, name) -        # set the option -        return self.ext_userCfg.SetOption(section, name, value) - -    def save_all_changed_extensions(self): -        """Save configuration changes to the user config file.""" -        has_changes = False -        for ext_name in self.extensions: -            options = self.extensions[ext_name] -            for opt in options: -                if self.set_extension_value(ext_name, opt): -                    has_changes = True -        if has_changes: -            self.ext_userCfg.Save() - - -help_common = '''\ -When you click either the Apply or Ok buttons, settings in this -dialog that are different from IDLE's default are saved in -a .idlerc directory in your home directory. Except as noted, -these changes apply to all versions of IDLE installed on this -machine. Some do not take affect until IDLE is restarted. -[Cancel] only cancels changes made since the last save. -''' -help_pages = { -    'Highlighting':''' -Highlighting: -The IDLE Dark color theme is new in October 2015.  It can only -be used with older IDLE releases if it is saved as a custom -theme, with a different name. -''' -} - - -def is_int(s): -    "Return 's is blank or represents an int'" -    if not s: -        return True -    try: -        int(s) -        return True -    except ValueError: -        return False - - -class VerticalScrolledFrame(Frame): -    """A pure Tkinter vertically scrollable frame. - -    * Use the 'interior' attribute to place widgets inside the scrollable frame -    * Construct and pack/place/grid normally -    * This frame only allows vertical scrolling -    """ -    def __init__(self, parent, *args, **kw): -        Frame.__init__(self, parent, *args, **kw) - -        # create a canvas object and a vertical scrollbar for scrolling it -        vscrollbar = Scrollbar(self, orient=VERTICAL) -        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE) -        canvas = Canvas(self, bd=0, highlightthickness=0, -                        yscrollcommand=vscrollbar.set, width=240) -        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE) -        vscrollbar.config(command=canvas.yview) - -        # reset the view -        canvas.xview_moveto(0) -        canvas.yview_moveto(0) - -        # create a frame inside the canvas which will be scrolled with it -        self.interior = interior = Frame(canvas) -        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW) - -        # track changes to the canvas and frame width and sync them, -        # also updating the scrollbar -        def _configure_interior(event): -            # update the scrollbars to match the size of the inner frame -            size = (interior.winfo_reqwidth(), interior.winfo_reqheight()) -            canvas.config(scrollregion="0 0 %s %s" % size) -        interior.bind('<Configure>', _configure_interior) - -        def _configure_canvas(event): -            if interior.winfo_reqwidth() != canvas.winfo_width(): -                # update the inner frame's width to fill the canvas -                canvas.itemconfigure(interior_id, width=canvas.winfo_width()) -        canvas.bind('<Configure>', _configure_canvas) - -        return - - -if __name__ == '__main__': -    import unittest -    unittest.main('idlelib.idle_test.test_configdialog', -                  verbosity=2, exit=False) -    from idlelib.idle_test.htest import run -    run(ConfigDialog) | 
