PyXR

c:\python24\lib \ idlelib \ configDialog.py



0001 """IDLE Configuration Dialog: support user customization of IDLE by GUI
0002 
0003 Customize font faces, sizes, and colorization attributes.  Set indentation
0004 defaults.  Customize keybindings.  Colorization and keybindings can be
0005 saved as user defined sets.  Select startup options including shell/editor
0006 and default window size.  Define additional help sources.
0007 
0008 Note that tab width in IDLE is currently fixed at eight due to Tk issues.
0009 Refer to comment in EditorWindow autoindent code for details.
0010 
0011 """
0012 from Tkinter import *
0013 import tkMessageBox, tkColorChooser, tkFont
0014 import string, copy
0015 
0016 from configHandler import idleConf
0017 from dynOptionMenuWidget import DynOptionMenu
0018 from tabpage import TabPageSet
0019 from keybindingDialog import GetKeysDialog
0020 from configSectionNameDialog import GetCfgSectionNameDialog
0021 from configHelpSourceEdit import GetHelpSourceDialog
0022 
0023 class ConfigDialog(Toplevel):
0024     """
0025     configuration dialog for idle
0026     """
0027     def __init__(self,parent,title):
0028         Toplevel.__init__(self, parent)
0029         self.configure(borderwidth=5)
0030         self.geometry("+%d+%d" % (parent.winfo_rootx()+20,
0031                 parent.winfo_rooty()+30))
0032         #Theme Elements. Each theme element key is it's display name.
0033         #The first value of the tuple is the sample area tag name.
0034         #The second value is the display name list sort index.
0035         self.themeElements={'Normal Text':('normal','00'),
0036             'Python Keywords':('keyword','01'),
0037             'Python Definitions':('definition','02'),
0038             'Python Builtins':('builtin', '03'),
0039             'Python Comments':('comment','04'),
0040             'Python Strings':('string','05'),
0041             'Selected Text':('hilite','06'),
0042             'Found Text':('hit','07'),
0043             'Cursor':('cursor','08'),
0044             'Error Text':('error','09'),
0045             'Shell Normal Text':('console','10'),
0046             'Shell Stdout Text':('stdout','11'),
0047             'Shell Stderr Text':('stderr','12'),
0048             }
0049         self.ResetChangedItems() #load initial values in changed items dict
0050         self.CreateWidgets()
0051         self.resizable(height=FALSE,width=FALSE)
0052         self.transient(parent)
0053         self.grab_set()
0054         self.protocol("WM_DELETE_WINDOW", self.Cancel)
0055         self.parent = parent
0056         self.tabPages.focus_set()
0057         #key bindings for this dialog
0058         #self.bind('<Escape>',self.Cancel) #dismiss dialog, no save
0059         #self.bind('<Alt-a>',self.Apply) #apply changes, save
0060         #self.bind('<F1>',self.Help) #context help
0061         self.LoadConfigs()
0062         self.AttachVarCallbacks() #avoid callbacks during LoadConfigs
0063         self.wait_window()
0064 
0065     def CreateWidgets(self):
0066         self.tabPages = TabPageSet(self,
0067                 pageNames=['Fonts/Tabs','Highlighting','Keys','General'])
0068         self.tabPages.ChangePage()#activates default (first) page
0069         frameActionButtons = Frame(self)
0070         #action buttons
0071         self.buttonHelp = Button(frameActionButtons,text='Help',
0072                 command=self.Help,takefocus=FALSE)
0073         self.buttonOk = Button(frameActionButtons,text='Ok',
0074                 command=self.Ok,takefocus=FALSE)
0075         self.buttonApply = Button(frameActionButtons,text='Apply',
0076                 command=self.Apply,takefocus=FALSE)
0077         self.buttonCancel = Button(frameActionButtons,text='Cancel',
0078                 command=self.Cancel,takefocus=FALSE)
0079         self.CreatePageFontTab()
0080         self.CreatePageHighlight()
0081         self.CreatePageKeys()
0082         self.CreatePageGeneral()
0083         self.buttonHelp.pack(side=RIGHT,padx=5,pady=5)
0084         self.buttonOk.pack(side=LEFT,padx=5,pady=5)
0085         self.buttonApply.pack(side=LEFT,padx=5,pady=5)
0086         self.buttonCancel.pack(side=LEFT,padx=5,pady=5)
0087         frameActionButtons.pack(side=BOTTOM)
0088         self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH)
0089 
0090     def CreatePageFontTab(self):
0091         #tkVars
0092         self.fontSize=StringVar(self)
0093         self.fontBold=BooleanVar(self)
0094         self.fontName=StringVar(self)
0095         self.spaceNum=IntVar(self)
0096         #self.tabCols=IntVar(self)
0097         self.indentBySpaces=BooleanVar(self)
0098         self.editFont=tkFont.Font(self,('courier',10,'normal'))
0099         ##widget creation
0100         #body frame
0101         frame=self.tabPages.pages['Fonts/Tabs']['page']
0102         #body section frames
0103         frameFont=Frame(frame,borderwidth=2,relief=GROOVE)
0104         frameIndent=Frame(frame,borderwidth=2,relief=GROOVE)
0105         #frameFont
0106         labelFontTitle=Label(frameFont,text='Set Base Editor Font')
0107         frameFontName=Frame(frameFont)
0108         frameFontParam=Frame(frameFont)
0109         labelFontNameTitle=Label(frameFontName,justify=LEFT,
0110                 text='Font :')
0111         self.listFontName=Listbox(frameFontName,height=5,takefocus=FALSE,
0112                 exportselection=FALSE)
0113         self.listFontName.bind('<ButtonRelease-1>',self.OnListFontButtonRelease)
0114         scrollFont=Scrollbar(frameFontName)
0115         scrollFont.config(command=self.listFontName.yview)
0116         self.listFontName.config(yscrollcommand=scrollFont.set)
0117         labelFontSizeTitle=Label(frameFontParam,text='Size :')
0118         self.optMenuFontSize=DynOptionMenu(frameFontParam,self.fontSize,None,
0119             command=self.SetFontSample)
0120         checkFontBold=Checkbutton(frameFontParam,variable=self.fontBold,
0121             onvalue=1,offvalue=0,text='Bold',command=self.SetFontSample)
0122         frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1)
0123         self.labelFontSample=Label(frameFontSample,
0124                 text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]',
0125                 justify=LEFT,font=self.editFont)
0126         #frameIndent
0127         labelIndentTitle=Label(frameIndent,text='Set Indentation Defaults')
0128         frameIndentType=Frame(frameIndent)
0129         frameIndentSize=Frame(frameIndent)
0130         labelIndentTypeTitle=Label(frameIndentType,
0131                 text='Choose indentation type :')
0132         radioUseSpaces=Radiobutton(frameIndentType,variable=self.indentBySpaces,
0133             value=1,text='Tab key inserts spaces')
0134         radioUseTabs=Radiobutton(frameIndentType,variable=self.indentBySpaces,
0135             value=0,text='Tab key inserts tabs')
0136         labelIndentSizeTitle=Label(frameIndentSize,
0137                 text='Choose indentation size :')
0138         labelSpaceNumTitle=Label(frameIndentSize,justify=LEFT,
0139                 text='indent width')
0140         self.scaleSpaceNum=Scale(frameIndentSize,variable=self.spaceNum,
0141                 orient='horizontal',tickinterval=2,from_=2,to=16)
0142         #labeltabColsTitle=Label(frameIndentSize,justify=LEFT,
0143         #        text='when tab key inserts tabs,\ncolumns per tab')
0144         #self.scaleTabCols=Scale(frameIndentSize,variable=self.tabCols,
0145         #        orient='horizontal',tickinterval=2,from_=2,to=8)
0146         #widget packing
0147         #body
0148         frameFont.pack(side=LEFT,padx=5,pady=10,expand=TRUE,fill=BOTH)
0149         frameIndent.pack(side=LEFT,padx=5,pady=10,fill=Y)
0150         #frameFont
0151         labelFontTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0152         frameFontName.pack(side=TOP,padx=5,pady=5,fill=X)
0153         frameFontParam.pack(side=TOP,padx=5,pady=5,fill=X)
0154         labelFontNameTitle.pack(side=TOP,anchor=W)
0155         self.listFontName.pack(side=LEFT,expand=TRUE,fill=X)
0156         scrollFont.pack(side=LEFT,fill=Y)
0157         labelFontSizeTitle.pack(side=LEFT,anchor=W)
0158         self.optMenuFontSize.pack(side=LEFT,anchor=W)
0159         checkFontBold.pack(side=LEFT,anchor=W,padx=20)
0160         frameFontSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
0161         self.labelFontSample.pack(expand=TRUE,fill=BOTH)
0162         #frameIndent
0163         labelIndentTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0164         frameIndentType.pack(side=TOP,padx=5,fill=X)
0165         frameIndentSize.pack(side=TOP,padx=5,pady=5,fill=BOTH)
0166         labelIndentTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0167         radioUseSpaces.pack(side=TOP,anchor=W,padx=5)
0168         radioUseTabs.pack(side=TOP,anchor=W,padx=5)
0169         labelIndentSizeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0170         labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5)
0171         self.scaleSpaceNum.pack(side=TOP,padx=5,fill=X)
0172         #labeltabColsTitle.pack(side=TOP,anchor=W,padx=5)
0173         #self.scaleTabCols.pack(side=TOP,padx=5,fill=X)
0174         return frame
0175 
0176     def CreatePageHighlight(self):
0177         self.builtinTheme=StringVar(self)
0178         self.customTheme=StringVar(self)
0179         self.fgHilite=BooleanVar(self)
0180         self.colour=StringVar(self)
0181         self.fontName=StringVar(self)
0182         self.themeIsBuiltin=BooleanVar(self)
0183         self.highlightTarget=StringVar(self)
0184         ##widget creation
0185         #body frame
0186         frame=self.tabPages.pages['Highlighting']['page']
0187         #body section frames
0188         frameCustom=Frame(frame,borderwidth=2,relief=GROOVE)
0189         frameTheme=Frame(frame,borderwidth=2,relief=GROOVE)
0190         #frameCustom
0191         self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1,
0192             font=('courier',12,''),cursor='hand2',width=21,height=10,
0193             takefocus=FALSE,highlightthickness=0,wrap=NONE)
0194         text=self.textHighlightSample
0195         text.bind('<Double-Button-1>',lambda e: 'break')
0196         text.bind('<B1-Motion>',lambda e: 'break')
0197         textAndTags=(('#you can click here','comment'),('\n','normal'),
0198             ('#to choose items','comment'),('\n','normal'),('def','keyword'),
0199             (' ','normal'),('func','definition'),('(param):','normal'),
0200             ('\n  ','normal'),('"""string"""','string'),('\n  var0 = ','normal'),
0201             ("'string'",'string'),('\n  var1 = ','normal'),("'selected'",'hilite'),
0202             ('\n  var2 = ','normal'),("'found'",'hit'),
0203             ('\n  var3 = ','normal'),('list', 'builtin'), ('(','normal'),
0204             ('None', 'builtin'),(')\n\n','normal'),
0205             (' error ','error'),(' ','normal'),('cursor |','cursor'),
0206             ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'),
0207             (' ','normal'),('stderr','stderr'),('\n','normal'))
0208         for txTa in textAndTags:
0209             text.insert(END,txTa[0],txTa[1])
0210         for element in self.themeElements.keys():
0211             text.tag_bind(self.themeElements[element][0],'<ButtonPress-1>',
0212                 lambda event,elem=element: event.widget.winfo_toplevel()
0213                 .highlightTarget.set(elem))
0214         text.config(state=DISABLED)
0215         self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1)
0216         frameFgBg=Frame(frameCustom)
0217         labelCustomTitle=Label(frameCustom,text='Set Custom Highlighting')
0218         buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :',
0219             command=self.GetColour,highlightthickness=0)
0220         self.optMenuHighlightTarget=DynOptionMenu(self.frameColourSet,
0221             self.highlightTarget,None,highlightthickness=0)#,command=self.SetHighlightTargetBinding
0222         self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite,
0223             value=1,text='Foreground',command=self.SetColourSampleBinding)
0224         self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite,
0225             value=0,text='Background',command=self.SetColourSampleBinding)
0226         self.fgHilite.set(1)
0227         buttonSaveCustomTheme=Button(frameCustom,
0228             text='Save as New Custom Theme',command=self.SaveAsNewTheme)
0229         #frameTheme
0230         labelThemeTitle=Label(frameTheme,text='Select a Highlighting Theme')
0231         labelTypeTitle=Label(frameTheme,text='Select : ')
0232         self.radioThemeBuiltin=Radiobutton(frameTheme,variable=self.themeIsBuiltin,
0233             value=1,command=self.SetThemeType,text='a Built-in Theme')
0234         self.radioThemeCustom=Radiobutton(frameTheme,variable=self.themeIsBuiltin,
0235             value=0,command=self.SetThemeType,text='a Custom Theme')
0236         self.optMenuThemeBuiltin=DynOptionMenu(frameTheme,
0237             self.builtinTheme,None,command=None)
0238         self.optMenuThemeCustom=DynOptionMenu(frameTheme,
0239             self.customTheme,None,command=None)
0240         self.buttonDeleteCustomTheme=Button(frameTheme,text='Delete Custom Theme',
0241                 command=self.DeleteCustomTheme)
0242         ##widget packing
0243         #body
0244         frameCustom.pack(side=LEFT,padx=5,pady=10,expand=TRUE,fill=BOTH)
0245         frameTheme.pack(side=LEFT,padx=5,pady=10,fill=Y)
0246         #frameCustom
0247         labelCustomTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0248         self.frameColourSet.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=X)
0249         frameFgBg.pack(side=TOP,padx=5,pady=0)
0250         self.textHighlightSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,
0251             fill=BOTH)
0252         buttonSetColour.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=4)
0253         self.optMenuHighlightTarget.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=3)
0254         self.radioFg.pack(side=LEFT,anchor=E)
0255         self.radioBg.pack(side=RIGHT,anchor=W)
0256         buttonSaveCustomTheme.pack(side=BOTTOM,fill=X,padx=5,pady=5)
0257         #frameTheme
0258         labelThemeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0259         labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0260         self.radioThemeBuiltin.pack(side=TOP,anchor=W,padx=5)
0261         self.radioThemeCustom.pack(side=TOP,anchor=W,padx=5,pady=2)
0262         self.optMenuThemeBuiltin.pack(side=TOP,fill=X,padx=5,pady=5)
0263         self.optMenuThemeCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5)
0264         self.buttonDeleteCustomTheme.pack(side=TOP,fill=X,padx=5,pady=5)
0265         return frame
0266 
0267     def CreatePageKeys(self):
0268         #tkVars
0269         self.bindingTarget=StringVar(self)
0270         self.builtinKeys=StringVar(self)
0271         self.customKeys=StringVar(self)
0272         self.keysAreBuiltin=BooleanVar(self)
0273         self.keyBinding=StringVar(self)
0274         ##widget creation
0275         #body frame
0276         frame=self.tabPages.pages['Keys']['page']
0277         #body section frames
0278         frameCustom=Frame(frame,borderwidth=2,relief=GROOVE)
0279         frameKeySets=Frame(frame,borderwidth=2,relief=GROOVE)
0280         #frameCustom
0281         frameTarget=Frame(frameCustom)
0282         labelCustomTitle=Label(frameCustom,text='Set Custom Key Bindings')
0283         labelTargetTitle=Label(frameTarget,text='Action - Key(s)')
0284         scrollTargetY=Scrollbar(frameTarget)
0285         scrollTargetX=Scrollbar(frameTarget,orient=HORIZONTAL)
0286         self.listBindings=Listbox(frameTarget,takefocus=FALSE,
0287                 exportselection=FALSE)
0288         self.listBindings.bind('<ButtonRelease-1>',self.KeyBindingSelected)
0289         scrollTargetY.config(command=self.listBindings.yview)
0290         scrollTargetX.config(command=self.listBindings.xview)
0291         self.listBindings.config(yscrollcommand=scrollTargetY.set)
0292         self.listBindings.config(xscrollcommand=scrollTargetX.set)
0293         self.buttonNewKeys=Button(frameCustom,text='Get New Keys for Selection',
0294             command=self.GetNewKeys,state=DISABLED)
0295         buttonSaveCustomKeys=Button(frameCustom,
0296                 text='Save as New Custom Key Set',command=self.SaveAsNewKeySet)
0297         #frameKeySets
0298         labelKeysTitle=Label(frameKeySets,text='Select a Key Set')
0299         labelTypeTitle=Label(frameKeySets,text='Select : ')
0300         self.radioKeysBuiltin=Radiobutton(frameKeySets,variable=self.keysAreBuiltin,
0301             value=1,command=self.SetKeysType,text='a Built-in Key Set')
0302         self.radioKeysCustom=Radiobutton(frameKeySets,variable=self.keysAreBuiltin,
0303             value=0,command=self.SetKeysType,text='a Custom Key Set')
0304         self.optMenuKeysBuiltin=DynOptionMenu(frameKeySets,
0305             self.builtinKeys,None,command=None)
0306         self.optMenuKeysCustom=DynOptionMenu(frameKeySets,
0307             self.customKeys,None,command=None)
0308         self.buttonDeleteCustomKeys=Button(frameKeySets,text='Delete Custom Key Set',
0309                 command=self.DeleteCustomKeys)
0310         ##widget packing
0311         #body
0312         frameCustom.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH)
0313         frameKeySets.pack(side=LEFT,padx=5,pady=5,fill=Y)
0314         #frameCustom
0315         labelCustomTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0316         buttonSaveCustomKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5)
0317         self.buttonNewKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5)
0318         frameTarget.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH)
0319         #frame target
0320         frameTarget.columnconfigure(0,weight=1)
0321         frameTarget.rowconfigure(1,weight=1)
0322         labelTargetTitle.grid(row=0,column=0,columnspan=2,sticky=W)
0323         self.listBindings.grid(row=1,column=0,sticky=NSEW)
0324         scrollTargetY.grid(row=1,column=1,sticky=NS)
0325         scrollTargetX.grid(row=2,column=0,sticky=EW)
0326         #frameKeySets
0327         labelKeysTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0328         labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0329         self.radioKeysBuiltin.pack(side=TOP,anchor=W,padx=5)
0330         self.radioKeysCustom.pack(side=TOP,anchor=W,padx=5,pady=2)
0331         self.optMenuKeysBuiltin.pack(side=TOP,fill=X,padx=5,pady=5)
0332         self.optMenuKeysCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5)
0333         self.buttonDeleteCustomKeys.pack(side=TOP,fill=X,padx=5,pady=5)
0334         return frame
0335 
0336     def CreatePageGeneral(self):
0337         #tkVars
0338         self.winWidth=StringVar(self)
0339         self.winHeight=StringVar(self)
0340         self.paraWidth=StringVar(self)
0341         self.startupEdit=IntVar(self)
0342         self.autoSave=IntVar(self)
0343         self.encoding=StringVar(self)
0344         self.userHelpBrowser=BooleanVar(self)
0345         self.helpBrowser=StringVar(self)
0346         #widget creation
0347         #body
0348         frame=self.tabPages.pages['General']['page']
0349         #body section frames
0350         frameRun=Frame(frame,borderwidth=2,relief=GROOVE)
0351         frameSave=Frame(frame,borderwidth=2,relief=GROOVE)
0352         frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE)
0353         frameParaSize=Frame(frame,borderwidth=2,relief=GROOVE)
0354         frameEncoding=Frame(frame,borderwidth=2,relief=GROOVE)
0355         frameHelp=Frame(frame,borderwidth=2,relief=GROOVE)
0356         #frameRun
0357         labelRunTitle=Label(frameRun,text='Startup Preferences')
0358         labelRunChoiceTitle=Label(frameRun,text='At Startup')
0359         radioStartupEdit=Radiobutton(frameRun,variable=self.startupEdit,
0360             value=1,command=self.SetKeysType,text="Open Edit Window")
0361         radioStartupShell=Radiobutton(frameRun,variable=self.startupEdit,
0362             value=0,command=self.SetKeysType,text='Open Shell Window')
0363         #frameSave
0364         labelSaveTitle=Label(frameSave,text='Autosave Preference')
0365         labelRunSaveTitle=Label(frameSave,text='At Start of Run (F5)  ')
0366         radioSaveAsk=Radiobutton(frameSave,variable=self.autoSave,
0367             value=0,command=self.SetKeysType,text="Prompt to Save")
0368         radioSaveAuto=Radiobutton(frameSave,variable=self.autoSave,
0369             value=1,command=self.SetKeysType,text='No Prompt')
0370         #frameWinSize
0371         labelWinSizeTitle=Label(frameWinSize,text='Initial Window Size'+
0372                 '  (in characters)')
0373         labelWinWidthTitle=Label(frameWinSize,text='Width')
0374         entryWinWidth=Entry(frameWinSize,textvariable=self.winWidth,
0375                 width=3)
0376         labelWinHeightTitle=Label(frameWinSize,text='Height')
0377         entryWinHeight=Entry(frameWinSize,textvariable=self.winHeight,
0378                 width=3)
0379         #paragraphFormatWidth
0380         labelParaWidthTitle=Label(frameParaSize,text='Paragraph reformat'+
0381                 ' width (in characters)')
0382         entryParaWidth=Entry(frameParaSize,textvariable=self.paraWidth,
0383                 width=3)
0384         #frameEncoding
0385         labelEncodingTitle=Label(frameEncoding,text="Default Source Encoding")
0386         radioEncLocale=Radiobutton(frameEncoding,variable=self.encoding,
0387             value="locale",text="Locale-defined")
0388         radioEncUTF8=Radiobutton(frameEncoding,variable=self.encoding,
0389             value="utf-8",text="UTF-8")
0390         radioEncNone=Radiobutton(frameEncoding,variable=self.encoding,
0391             value="none",text="None")
0392         #frameHelp
0393         ##labelHelpTitle=Label(frameHelp,text='Help Options')
0394         frameHelpList=Frame(frameHelp)
0395         frameHelpListButtons=Frame(frameHelpList)
0396         labelHelpListTitle=Label(frameHelpList,text='Additional Help Sources:')
0397         scrollHelpList=Scrollbar(frameHelpList)
0398         self.listHelp=Listbox(frameHelpList,height=5,takefocus=FALSE,
0399                 exportselection=FALSE)
0400         scrollHelpList.config(command=self.listHelp.yview)
0401         self.listHelp.config(yscrollcommand=scrollHelpList.set)
0402         self.listHelp.bind('<ButtonRelease-1>',self.HelpSourceSelected)
0403         self.buttonHelpListEdit=Button(frameHelpListButtons,text='Edit',
0404                 state=DISABLED,width=8,command=self.HelpListItemEdit)
0405         self.buttonHelpListAdd=Button(frameHelpListButtons,text='Add',
0406                 width=8,command=self.HelpListItemAdd)
0407         self.buttonHelpListRemove=Button(frameHelpListButtons,text='Remove',
0408                 state=DISABLED,width=8,command=self.HelpListItemRemove)
0409         # the following is better handled by the BROWSER environment
0410         # variable under unix/linux
0411         #checkHelpBrowser=Checkbutton(frameHelp,variable=self.userHelpBrowser,
0412         #    onvalue=1,offvalue=0,text='user specified (html) help browser:',
0413         #    command=self.OnCheckUserHelpBrowser)
0414         #self.entryHelpBrowser=Entry(frameHelp,textvariable=self.helpBrowser,
0415         #        width=40)
0416         #widget packing
0417         #body
0418         frameRun.pack(side=TOP,padx=5,pady=5,fill=X)
0419         frameSave.pack(side=TOP,padx=5,pady=5,fill=X)
0420         frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X)
0421         frameParaSize.pack(side=TOP,padx=5,pady=5,fill=X)
0422         frameEncoding.pack(side=TOP,padx=5,pady=5,fill=X)
0423         frameHelp.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
0424         #frameRun
0425         labelRunTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0426         labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
0427         radioStartupShell.pack(side=RIGHT,anchor=W,padx=5,pady=5)
0428         radioStartupEdit.pack(side=RIGHT,anchor=W,padx=5,pady=5)
0429         #frameSave
0430         labelSaveTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0431         labelRunSaveTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
0432         radioSaveAuto.pack(side=RIGHT,anchor=W,padx=5,pady=5)
0433         radioSaveAsk.pack(side=RIGHT,anchor=W,padx=5,pady=5)
0434         #frameWinSize
0435         labelWinSizeTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
0436         entryWinHeight.pack(side=RIGHT,anchor=E,padx=10,pady=5)
0437         labelWinHeightTitle.pack(side=RIGHT,anchor=E,pady=5)
0438         entryWinWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5)
0439         labelWinWidthTitle.pack(side=RIGHT,anchor=E,pady=5)
0440         #paragraphFormatWidth
0441         labelParaWidthTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
0442         entryParaWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5)
0443         #frameEncoding
0444         labelEncodingTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
0445         radioEncNone.pack(side=RIGHT,anchor=E,pady=5)
0446         radioEncUTF8.pack(side=RIGHT,anchor=E,pady=5)
0447         radioEncLocale.pack(side=RIGHT,anchor=E,pady=5)
0448         #frameHelp
0449         ##labelHelpTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
0450         frameHelpListButtons.pack(side=RIGHT,padx=5,pady=5,fill=Y)
0451         frameHelpList.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
0452         labelHelpListTitle.pack(side=TOP,anchor=W)
0453         scrollHelpList.pack(side=RIGHT,anchor=W,fill=Y)
0454         self.listHelp.pack(side=LEFT,anchor=E,expand=TRUE,fill=BOTH)
0455         self.buttonHelpListEdit.pack(side=TOP,anchor=W,pady=5)
0456         self.buttonHelpListAdd.pack(side=TOP,anchor=W)
0457         self.buttonHelpListRemove.pack(side=TOP,anchor=W,pady=5)
0458         #checkHelpBrowser.pack(side=TOP,anchor=W,padx=5)
0459         #self.entryHelpBrowser.pack(side=TOP,anchor=W,padx=5,pady=5)
0460         return frame
0461 
0462     def AttachVarCallbacks(self):
0463         self.fontSize.trace_variable('w',self.VarChanged_fontSize)
0464         self.fontName.trace_variable('w',self.VarChanged_fontName)
0465         self.fontBold.trace_variable('w',self.VarChanged_fontBold)
0466         self.spaceNum.trace_variable('w',self.VarChanged_spaceNum)
0467         #self.tabCols.trace_variable('w',self.VarChanged_tabCols)
0468         self.indentBySpaces.trace_variable('w',self.VarChanged_indentBySpaces)
0469         self.colour.trace_variable('w',self.VarChanged_colour)
0470         self.builtinTheme.trace_variable('w',self.VarChanged_builtinTheme)
0471         self.customTheme.trace_variable('w',self.VarChanged_customTheme)
0472         self.themeIsBuiltin.trace_variable('w',self.VarChanged_themeIsBuiltin)
0473         self.highlightTarget.trace_variable('w',self.VarChanged_highlightTarget)
0474         self.keyBinding.trace_variable('w',self.VarChanged_keyBinding)
0475         self.builtinKeys.trace_variable('w',self.VarChanged_builtinKeys)
0476         self.customKeys.trace_variable('w',self.VarChanged_customKeys)
0477         self.keysAreBuiltin.trace_variable('w',self.VarChanged_keysAreBuiltin)
0478         self.winWidth.trace_variable('w',self.VarChanged_winWidth)
0479         self.winHeight.trace_variable('w',self.VarChanged_winHeight)
0480         self.paraWidth.trace_variable('w',self.VarChanged_paraWidth)
0481         self.startupEdit.trace_variable('w',self.VarChanged_startupEdit)
0482         self.autoSave.trace_variable('w',self.VarChanged_autoSave)
0483         self.encoding.trace_variable('w',self.VarChanged_encoding)
0484 
0485     def VarChanged_fontSize(self,*params):
0486         value=self.fontSize.get()
0487         self.AddChangedItem('main','EditorWindow','font-size',value)
0488 
0489     def VarChanged_fontName(self,*params):
0490         value=self.fontName.get()
0491         self.AddChangedItem('main','EditorWindow','font',value)
0492 
0493     def VarChanged_fontBold(self,*params):
0494         value=self.fontBold.get()
0495         self.AddChangedItem('main','EditorWindow','font-bold',value)
0496 
0497     def VarChanged_indentBySpaces(self,*params):
0498         value=self.indentBySpaces.get()
0499         self.AddChangedItem('main','Indent','use-spaces',value)
0500 
0501     def VarChanged_spaceNum(self,*params):
0502         value=self.spaceNum.get()
0503         self.AddChangedItem('main','Indent','num-spaces',value)
0504 
0505     #def VarChanged_tabCols(self,*params):
0506     #    value=self.tabCols.get()
0507     #    self.AddChangedItem('main','Indent','tab-cols',value)
0508 
0509     def VarChanged_colour(self,*params):
0510         self.OnNewColourSet()
0511 
0512     def VarChanged_builtinTheme(self,*params):
0513         value=self.builtinTheme.get()
0514         self.AddChangedItem('main','Theme','name',value)
0515         self.PaintThemeSample()
0516 
0517     def VarChanged_customTheme(self,*params):
0518         value=self.customTheme.get()
0519         if value != '- no custom themes -':
0520             self.AddChangedItem('main','Theme','name',value)
0521             self.PaintThemeSample()
0522 
0523     def VarChanged_themeIsBuiltin(self,*params):
0524         value=self.themeIsBuiltin.get()
0525         self.AddChangedItem('main','Theme','default',value)
0526         if value:
0527             self.VarChanged_builtinTheme()
0528         else:
0529             self.VarChanged_customTheme()
0530 
0531     def VarChanged_highlightTarget(self,*params):
0532         self.SetHighlightTarget()
0533 
0534     def VarChanged_keyBinding(self,*params):
0535         value=self.keyBinding.get()
0536         keySet=self.customKeys.get()
0537         event=self.listBindings.get(ANCHOR).split()[0]
0538         if idleConf.IsCoreBinding(event):
0539             #this is a core keybinding
0540             self.AddChangedItem('keys',keySet,event,value)
0541         else: #this is an extension key binding
0542             extName=idleConf.GetExtnNameForEvent(event)
0543             extKeybindSection=extName+'_cfgBindings'
0544             self.AddChangedItem('extensions',extKeybindSection,event,value)
0545 
0546     def VarChanged_builtinKeys(self,*params):
0547         value=self.builtinKeys.get()
0548         self.AddChangedItem('main','Keys','name',value)
0549         self.LoadKeysList(value)
0550 
0551     def VarChanged_customKeys(self,*params):
0552         value=self.customKeys.get()
0553         if value != '- no custom keys -':
0554             self.AddChangedItem('main','Keys','name',value)
0555             self.LoadKeysList(value)
0556 
0557     def VarChanged_keysAreBuiltin(self,*params):
0558         value=self.keysAreBuiltin.get()
0559         self.AddChangedItem('main','Keys','default',value)
0560         if value:
0561             self.VarChanged_builtinKeys()
0562         else:
0563             self.VarChanged_customKeys()
0564 
0565     def VarChanged_winWidth(self,*params):
0566         value=self.winWidth.get()
0567         self.AddChangedItem('main','EditorWindow','width',value)
0568 
0569     def VarChanged_winHeight(self,*params):
0570         value=self.winHeight.get()
0571         self.AddChangedItem('main','EditorWindow','height',value)
0572 
0573     def VarChanged_paraWidth(self,*params):
0574         value=self.paraWidth.get()
0575         self.AddChangedItem('main','FormatParagraph','paragraph',value)
0576 
0577     def VarChanged_startupEdit(self,*params):
0578         value=self.startupEdit.get()
0579         self.AddChangedItem('main','General','editor-on-startup',value)
0580 
0581     def VarChanged_autoSave(self,*params):
0582         value=self.autoSave.get()
0583         self.AddChangedItem('main','General','autosave',value)
0584 
0585     def VarChanged_encoding(self,*params):
0586         value=self.encoding.get()
0587         self.AddChangedItem('main','EditorWindow','encoding',value)
0588 
0589     def ResetChangedItems(self):
0590         #When any config item is changed in this dialog, an entry
0591         #should be made in the relevant section (config type) of this
0592         #dictionary. The key should be the config file section name and the
0593         #value a dictionary, whose key:value pairs are item=value pairs for
0594         #that config file section.
0595         self.changedItems={'main':{},'highlight':{},'keys':{},'extensions':{}}
0596 
0597     def AddChangedItem(self,type,section,item,value):
0598         value=str(value) #make sure we use a string
0599         if not self.changedItems[type].has_key(section):
0600             self.changedItems[type][section]={}
0601         self.changedItems[type][section][item]=value
0602 
0603     def GetDefaultItems(self):
0604         dItems={'main':{},'highlight':{},'keys':{},'extensions':{}}
0605         for configType in dItems.keys():
0606             sections=idleConf.GetSectionList('default',configType)
0607             for section in sections:
0608                 dItems[configType][section]={}
0609                 options=idleConf.defaultCfg[configType].GetOptionList(section)
0610                 for option in options:
0611                     dItems[configType][section][option]=(
0612                             idleConf.defaultCfg[configType].Get(section,option))
0613         return dItems
0614 
0615     def SetThemeType(self):
0616         if self.themeIsBuiltin.get():
0617             self.optMenuThemeBuiltin.config(state=NORMAL)
0618             self.optMenuThemeCustom.config(state=DISABLED)
0619             self.buttonDeleteCustomTheme.config(state=DISABLED)
0620         else:
0621             self.optMenuThemeBuiltin.config(state=DISABLED)
0622             self.radioThemeCustom.config(state=NORMAL)
0623             self.optMenuThemeCustom.config(state=NORMAL)
0624             self.buttonDeleteCustomTheme.config(state=NORMAL)
0625 
0626     def SetKeysType(self):
0627         if self.keysAreBuiltin.get():
0628             self.optMenuKeysBuiltin.config(state=NORMAL)
0629             self.optMenuKeysCustom.config(state=DISABLED)
0630             self.buttonDeleteCustomKeys.config(state=DISABLED)
0631         else:
0632             self.optMenuKeysBuiltin.config(state=DISABLED)
0633             self.radioKeysCustom.config(state=NORMAL)
0634             self.optMenuKeysCustom.config(state=NORMAL)
0635             self.buttonDeleteCustomKeys.config(state=NORMAL)
0636 
0637     def GetNewKeys(self):
0638         listIndex=self.listBindings.index(ANCHOR)
0639         binding=self.listBindings.get(listIndex)
0640         bindName=binding.split()[0] #first part, up to first space
0641         if self.keysAreBuiltin.get():
0642             currentKeySetName=self.builtinKeys.get()
0643         else:
0644             currentKeySetName=self.customKeys.get()
0645         currentBindings=idleConf.GetCurrentKeySet()
0646         if currentKeySetName in self.changedItems['keys'].keys(): #unsaved changes
0647             keySetChanges=self.changedItems['keys'][currentKeySetName]
0648             for event in keySetChanges.keys():
0649                 currentBindings[event]=keySetChanges[event].split()
0650         currentKeySequences=currentBindings.values()
0651         newKeys=GetKeysDialog(self,'Get New Keys',bindName,
0652                 currentKeySequences).result
0653         if newKeys: #new keys were specified
0654             if self.keysAreBuiltin.get(): #current key set is a built-in
0655                 message=('Your changes will be saved as a new Custom Key Set. '+
0656                         'Enter a name for your new Custom Key Set below.')
0657                 newKeySet=self.GetNewKeysName(message)
0658                 if not newKeySet: #user cancelled custom key set creation
0659                     self.listBindings.select_set(listIndex)
0660                     self.listBindings.select_anchor(listIndex)
0661                     return
0662                 else: #create new custom key set based on previously active key set
0663                     self.CreateNewKeySet(newKeySet)
0664             self.listBindings.delete(listIndex)
0665             self.listBindings.insert(listIndex,bindName+' - '+newKeys)
0666             self.listBindings.select_set(listIndex)
0667             self.listBindings.select_anchor(listIndex)
0668             self.keyBinding.set(newKeys)
0669         else:
0670             self.listBindings.select_set(listIndex)
0671             self.listBindings.select_anchor(listIndex)
0672 
0673     def GetNewKeysName(self,message):
0674         usedNames=(idleConf.GetSectionList('user','keys')+
0675                 idleConf.GetSectionList('default','keys'))
0676         newKeySet=GetCfgSectionNameDialog(self,'New Custom Key Set',
0677                 message,usedNames).result
0678         return newKeySet
0679 
0680     def SaveAsNewKeySet(self):
0681         newKeysName=self.GetNewKeysName('New Key Set Name:')
0682         if newKeysName:
0683             self.CreateNewKeySet(newKeysName)
0684 
0685     def KeyBindingSelected(self,event):
0686         self.buttonNewKeys.config(state=NORMAL)
0687 
0688     def CreateNewKeySet(self,newKeySetName):
0689         #creates new custom key set based on the previously active key set,
0690         #and makes the new key set active
0691         if self.keysAreBuiltin.get():
0692             prevKeySetName=self.builtinKeys.get()
0693         else:
0694             prevKeySetName=self.customKeys.get()
0695         prevKeys=idleConf.GetCoreKeys(prevKeySetName)
0696         newKeys={}
0697         for event in prevKeys.keys(): #add key set to changed items
0698             eventName=event[2:-2] #trim off the angle brackets
0699             binding=string.join(prevKeys[event])
0700             newKeys[eventName]=binding
0701         #handle any unsaved changes to prev key set
0702         if prevKeySetName in self.changedItems['keys'].keys():
0703             keySetChanges=self.changedItems['keys'][prevKeySetName]
0704             for event in keySetChanges.keys():
0705                 newKeys[event]=keySetChanges[event]
0706         #save the new theme
0707         self.SaveNewKeySet(newKeySetName,newKeys)
0708         #change gui over to the new key set
0709         customKeyList=idleConf.GetSectionList('user','keys')
0710         customKeyList.sort()
0711         self.optMenuKeysCustom.SetMenu(customKeyList,newKeySetName)
0712         self.keysAreBuiltin.set(0)
0713         self.SetKeysType()
0714 
0715     def LoadKeysList(self,keySetName):
0716         reselect=0
0717         newKeySet=0
0718         if self.listBindings.curselection():
0719             reselect=1
0720             listIndex=self.listBindings.index(ANCHOR)
0721         keySet=idleConf.GetKeySet(keySetName)
0722         bindNames=keySet.keys()
0723         bindNames.sort()
0724         self.listBindings.delete(0,END)
0725         for bindName in bindNames:
0726             key=string.join(keySet[bindName]) #make key(s) into a string
0727             bindName=bindName[2:-2] #trim off the angle brackets
0728             if keySetName in self.changedItems['keys'].keys():
0729                 #handle any unsaved changes to this key set
0730                 if bindName in self.changedItems['keys'][keySetName].keys():
0731                     key=self.changedItems['keys'][keySetName][bindName]
0732             self.listBindings.insert(END, bindName+' - '+key)
0733         if reselect:
0734             self.listBindings.see(listIndex)
0735             self.listBindings.select_set(listIndex)
0736             self.listBindings.select_anchor(listIndex)
0737 
0738     def DeleteCustomKeys(self):
0739         keySetName=self.customKeys.get()
0740         if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+
0741                                      'to delete the key set %r ?' % (keySetName),
0742                                      parent=self):
0743             return
0744         #remove key set from config
0745         idleConf.userCfg['keys'].remove_section(keySetName)
0746         if self.changedItems['keys'].has_key(keySetName):
0747             del(self.changedItems['keys'][keySetName])
0748         #write changes
0749         idleConf.userCfg['keys'].Save()
0750         #reload user key set list
0751         itemList=idleConf.GetSectionList('user','keys')
0752         itemList.sort()
0753         if not itemList:
0754             self.radioKeysCustom.config(state=DISABLED)
0755             self.optMenuKeysCustom.SetMenu(itemList,'- no custom keys -')
0756         else:
0757             self.optMenuKeysCustom.SetMenu(itemList,itemList[0])
0758         #revert to default key set
0759         self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys','default'))
0760         self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys','name'))
0761         #user can't back out of these changes, they must be applied now
0762         self.Apply()
0763         self.SetKeysType()
0764 
0765     def DeleteCustomTheme(self):
0766         themeName=self.customTheme.get()
0767         if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+
0768                                      'to delete the theme %r ?' % (themeName,),
0769                                      parent=self):
0770             return
0771         #remove theme from config
0772         idleConf.userCfg['highlight'].remove_section(themeName)
0773         if self.changedItems['highlight'].has_key(themeName):
0774             del(self.changedItems['highlight'][themeName])
0775         #write changes
0776         idleConf.userCfg['highlight'].Save()
0777         #reload user theme list
0778         itemList=idleConf.GetSectionList('user','highlight')
0779         itemList.sort()
0780         if not itemList:
0781             self.radioThemeCustom.config(state=DISABLED)
0782             self.optMenuThemeCustom.SetMenu(itemList,'- no custom themes -')
0783         else:
0784             self.optMenuThemeCustom.SetMenu(itemList,itemList[0])
0785         #revert to default theme
0786         self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme','default'))
0787         self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme','name'))
0788         #user can't back out of these changes, they must be applied now
0789         self.Apply()
0790         self.SetThemeType()
0791 
0792     def GetColour(self):
0793         target=self.highlightTarget.get()
0794         prevColour=self.frameColourSet.cget('bg')
0795         rgbTuplet, colourString = tkColorChooser.askcolor(parent=self,
0796             title='Pick new colour for : '+target,initialcolor=prevColour)
0797         if colourString and (colourString!=prevColour):
0798             #user didn't cancel, and they chose a new colour
0799             if self.themeIsBuiltin.get(): #current theme is a built-in
0800                 message=('Your changes will be saved as a new Custom Theme. '+
0801                         'Enter a name for your new Custom Theme below.')
0802                 newTheme=self.GetNewThemeName(message)
0803                 if not newTheme: #user cancelled custom theme creation
0804                     return
0805                 else: #create new custom theme based on previously active theme
0806                     self.CreateNewTheme(newTheme)
0807                     self.colour.set(colourString)
0808             else: #current theme is user defined
0809                 self.colour.set(colourString)
0810 
0811     def OnNewColourSet(self):
0812         newColour=self.colour.get()
0813         self.frameColourSet.config(bg=newColour)#set sample
0814         if self.fgHilite.get(): plane='foreground'
0815         else: plane='background'
0816         sampleElement=self.themeElements[self.highlightTarget.get()][0]
0817         self.textHighlightSample.tag_config(sampleElement, **{plane:newColour})
0818         theme=self.customTheme.get()
0819         themeElement=sampleElement+'-'+plane
0820         self.AddChangedItem('highlight',theme,themeElement,newColour)
0821 
0822     def GetNewThemeName(self,message):
0823         usedNames=(idleConf.GetSectionList('user','highlight')+
0824                 idleConf.GetSectionList('default','highlight'))
0825         newTheme=GetCfgSectionNameDialog(self,'New Custom Theme',
0826                 message,usedNames).result
0827         return newTheme
0828 
0829     def SaveAsNewTheme(self):
0830         newThemeName=self.GetNewThemeName('New Theme Name:')
0831         if newThemeName:
0832             self.CreateNewTheme(newThemeName)
0833 
0834     def CreateNewTheme(self,newThemeName):
0835         #creates new custom theme based on the previously active theme,
0836         #and makes the new theme active
0837         if self.themeIsBuiltin.get():
0838             themeType='default'
0839             themeName=self.builtinTheme.get()
0840         else:
0841             themeType='user'
0842             themeName=self.customTheme.get()
0843         newTheme=idleConf.GetThemeDict(themeType,themeName)
0844         #apply any of the old theme's unsaved changes to the new theme
0845         if themeName in self.changedItems['highlight'].keys():
0846             themeChanges=self.changedItems['highlight'][themeName]
0847             for element in themeChanges.keys():
0848                 newTheme[element]=themeChanges[element]
0849         #save the new theme
0850         self.SaveNewTheme(newThemeName,newTheme)
0851         #change gui over to the new theme
0852         customThemeList=idleConf.GetSectionList('user','highlight')
0853         customThemeList.sort()
0854         self.optMenuThemeCustom.SetMenu(customThemeList,newThemeName)
0855         self.themeIsBuiltin.set(0)
0856         self.SetThemeType()
0857 
0858     def OnListFontButtonRelease(self,event):
0859         font = self.listFontName.get(ANCHOR)
0860         self.fontName.set(font.lower())
0861         self.SetFontSample()
0862 
0863     def SetFontSample(self,event=None):
0864         fontName=self.fontName.get()
0865         if self.fontBold.get():
0866             fontWeight=tkFont.BOLD
0867         else:
0868             fontWeight=tkFont.NORMAL
0869         self.editFont.config(size=self.fontSize.get(),
0870                 weight=fontWeight,family=fontName)
0871 
0872     def SetHighlightTarget(self):
0873         if self.highlightTarget.get()=='Cursor': #bg not possible
0874             self.radioFg.config(state=DISABLED)
0875             self.radioBg.config(state=DISABLED)
0876             self.fgHilite.set(1)
0877         else: #both fg and bg can be set
0878             self.radioFg.config(state=NORMAL)
0879             self.radioBg.config(state=NORMAL)
0880             self.fgHilite.set(1)
0881         self.SetColourSample()
0882 
0883     def SetColourSampleBinding(self,*args):
0884         self.SetColourSample()
0885 
0886     def SetColourSample(self):
0887         #set the colour smaple area
0888         tag=self.themeElements[self.highlightTarget.get()][0]
0889         if self.fgHilite.get(): plane='foreground'
0890         else: plane='background'
0891         colour=self.textHighlightSample.tag_cget(tag,plane)
0892         self.frameColourSet.config(bg=colour)
0893 
0894     def PaintThemeSample(self):
0895         if self.themeIsBuiltin.get(): #a default theme
0896             theme=self.builtinTheme.get()
0897         else: #a user theme
0898             theme=self.customTheme.get()
0899         for elementTitle in self.themeElements.keys():
0900             element=self.themeElements[elementTitle][0]
0901             colours=idleConf.GetHighlight(theme,element)
0902             if element=='cursor': #cursor sample needs special painting
0903                 colours['background']=idleConf.GetHighlight(theme,
0904                         'normal', fgBg='bg')
0905             #handle any unsaved changes to this theme
0906             if theme in self.changedItems['highlight'].keys():
0907                 themeDict=self.changedItems['highlight'][theme]
0908                 if themeDict.has_key(element+'-foreground'):
0909                     colours['foreground']=themeDict[element+'-foreground']
0910                 if themeDict.has_key(element+'-background'):
0911                     colours['background']=themeDict[element+'-background']
0912             self.textHighlightSample.tag_config(element, **colours)
0913         self.SetColourSample()
0914 
0915 ##     def OnCheckUserHelpBrowser(self):
0916 ##         if self.userHelpBrowser.get():
0917 ##             self.entryHelpBrowser.config(state=NORMAL)
0918 ##         else:
0919 ##             self.entryHelpBrowser.config(state=DISABLED)
0920 
0921     def HelpSourceSelected(self,event):
0922         self.SetHelpListButtonStates()
0923 
0924     def SetHelpListButtonStates(self):
0925         if self.listHelp.size()<1: #no entries in list
0926             self.buttonHelpListEdit.config(state=DISABLED)
0927             self.buttonHelpListRemove.config(state=DISABLED)
0928         else: #there are some entries
0929             if self.listHelp.curselection(): #there currently is a selection
0930                 self.buttonHelpListEdit.config(state=NORMAL)
0931                 self.buttonHelpListRemove.config(state=NORMAL)
0932             else:  #there currently is not a selection
0933                 self.buttonHelpListEdit.config(state=DISABLED)
0934                 self.buttonHelpListRemove.config(state=DISABLED)
0935 
0936     def HelpListItemAdd(self):
0937         helpSource=GetHelpSourceDialog(self,'New Help Source').result
0938         if helpSource:
0939             self.userHelpList.append( (helpSource[0],helpSource[1]) )
0940             self.listHelp.insert(END,helpSource[0])
0941             self.UpdateUserHelpChangedItems()
0942         self.SetHelpListButtonStates()
0943 
0944     def HelpListItemEdit(self):
0945         itemIndex=self.listHelp.index(ANCHOR)
0946         helpSource=self.userHelpList[itemIndex]
0947         newHelpSource=GetHelpSourceDialog(self,'Edit Help Source',
0948                 menuItem=helpSource[0],filePath=helpSource[1]).result
0949         if (not newHelpSource) or (newHelpSource==helpSource):
0950             return #no changes
0951         self.userHelpList[itemIndex]=newHelpSource
0952         self.listHelp.delete(itemIndex)
0953         self.listHelp.insert(itemIndex,newHelpSource[0])
0954         self.UpdateUserHelpChangedItems()
0955         self.SetHelpListButtonStates()
0956 
0957     def HelpListItemRemove(self):
0958         itemIndex=self.listHelp.index(ANCHOR)
0959         del(self.userHelpList[itemIndex])
0960         self.listHelp.delete(itemIndex)
0961         self.UpdateUserHelpChangedItems()
0962         self.SetHelpListButtonStates()
0963 
0964     def UpdateUserHelpChangedItems(self):
0965         "Clear and rebuild the HelpFiles section in self.changedItems"
0966         self.changedItems['main']['HelpFiles'] = {}
0967         for num in range(1,len(self.userHelpList)+1):
0968             self.AddChangedItem('main','HelpFiles',str(num),
0969                     string.join(self.userHelpList[num-1][:2],';'))
0970 
0971     def LoadFontCfg(self):
0972         ##base editor font selection list
0973         fonts=list(tkFont.families(self))
0974         fonts.sort()
0975         for font in fonts:
0976             self.listFontName.insert(END,font)
0977         configuredFont=idleConf.GetOption('main','EditorWindow','font',
0978                 default='courier')
0979         lc_configuredFont = configuredFont.lower()
0980         self.fontName.set(lc_configuredFont)
0981         lc_fonts = [s.lower() for s in fonts]
0982         if lc_configuredFont in lc_fonts:
0983             currentFontIndex = lc_fonts.index(lc_configuredFont)
0984             self.listFontName.see(currentFontIndex)
0985             self.listFontName.select_set(currentFontIndex)
0986             self.listFontName.select_anchor(currentFontIndex)
0987         ##font size dropdown
0988         fontSize=idleConf.GetOption('main','EditorWindow','font-size',
0989                 default='10')
0990         self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14',
0991                 '16','18','20','22'),fontSize )
0992         ##fontWeight
0993         self.fontBold.set(idleConf.GetOption('main','EditorWindow',
0994                 'font-bold',default=0,type='bool'))
0995         ##font sample
0996         self.SetFontSample()
0997 
0998     def LoadTabCfg(self):
0999         ##indent type radiobuttons
1000         spaceIndent=idleConf.GetOption('main','Indent','use-spaces',
1001                 default=1,type='bool')
1002         self.indentBySpaces.set(spaceIndent)
1003         ##indent sizes
1004         spaceNum=idleConf.GetOption('main','Indent','num-spaces',
1005                 default=4,type='int')
1006         #tabCols=idleConf.GetOption('main','Indent','tab-cols',
1007         #        default=4,type='int')
1008         self.spaceNum.set(spaceNum)
1009         #self.tabCols.set(tabCols)
1010 
1011     def LoadThemeCfg(self):
1012         ##current theme type radiobutton
1013         self.themeIsBuiltin.set(idleConf.GetOption('main','Theme','default',
1014             type='bool',default=1))
1015         ##currently set theme
1016         currentOption=idleConf.CurrentTheme()
1017         ##load available theme option menus
1018         if self.themeIsBuiltin.get(): #default theme selected
1019             itemList=idleConf.GetSectionList('default','highlight')
1020             itemList.sort()
1021             self.optMenuThemeBuiltin.SetMenu(itemList,currentOption)
1022             itemList=idleConf.GetSectionList('user','highlight')
1023             itemList.sort()
1024             if not itemList:
1025                 self.radioThemeCustom.config(state=DISABLED)
1026                 self.customTheme.set('- no custom themes -')
1027             else:
1028                 self.optMenuThemeCustom.SetMenu(itemList,itemList[0])
1029         else: #user theme selected
1030             itemList=idleConf.GetSectionList('user','highlight')
1031             itemList.sort()
1032             self.optMenuThemeCustom.SetMenu(itemList,currentOption)
1033             itemList=idleConf.GetSectionList('default','highlight')
1034             itemList.sort()
1035             self.optMenuThemeBuiltin.SetMenu(itemList,itemList[0])
1036         self.SetThemeType()
1037         ##load theme element option menu
1038         themeNames=self.themeElements.keys()
1039         themeNames.sort(self.__ThemeNameIndexCompare)
1040         self.optMenuHighlightTarget.SetMenu(themeNames,themeNames[0])
1041         self.PaintThemeSample()
1042         self.SetHighlightTarget()
1043 
1044     def __ThemeNameIndexCompare(self,a,b):
1045         if self.themeElements[a][1]<self.themeElements[b][1]: return -1
1046         elif self.themeElements[a][1]==self.themeElements[b][1]: return 0
1047         else: return 1
1048 
1049     def LoadKeyCfg(self):
1050         ##current keys type radiobutton
1051         self.keysAreBuiltin.set(idleConf.GetOption('main','Keys','default',
1052             type='bool',default=1))
1053         ##currently set keys
1054         currentOption=idleConf.CurrentKeys()
1055         ##load available keyset option menus
1056         if self.keysAreBuiltin.get(): #default theme selected
1057             itemList=idleConf.GetSectionList('default','keys')
1058             itemList.sort()
1059             self.optMenuKeysBuiltin.SetMenu(itemList,currentOption)
1060             itemList=idleConf.GetSectionList('user','keys')
1061             itemList.sort()
1062             if not itemList:
1063                 self.radioKeysCustom.config(state=DISABLED)
1064                 self.customKeys.set('- no custom keys -')
1065             else:
1066                 self.optMenuKeysCustom.SetMenu(itemList,itemList[0])
1067         else: #user key set selected
1068             itemList=idleConf.GetSectionList('user','keys')
1069             itemList.sort()
1070             self.optMenuKeysCustom.SetMenu(itemList,currentOption)
1071             itemList=idleConf.GetSectionList('default','keys')
1072             itemList.sort()
1073             self.optMenuKeysBuiltin.SetMenu(itemList,itemList[0])
1074         self.SetKeysType()
1075         ##load keyset element list
1076         keySetName=idleConf.CurrentKeys()
1077         self.LoadKeysList(keySetName)
1078 
1079     def LoadGeneralCfg(self):
1080         #startup state
1081         self.startupEdit.set(idleConf.GetOption('main','General',
1082                 'editor-on-startup',default=1,type='bool'))
1083         #autosave state
1084         self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave',
1085                                              default=0, type='bool'))
1086         #initial window size
1087         self.winWidth.set(idleConf.GetOption('main','EditorWindow','width'))
1088         self.winHeight.set(idleConf.GetOption('main','EditorWindow','height'))
1089         #initial paragraph reformat size
1090         self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph'))
1091         # default source encoding
1092         self.encoding.set(idleConf.GetOption('main', 'EditorWindow',
1093                                              'encoding', default='none'))
1094         # additional help sources
1095         self.userHelpList = idleConf.GetAllExtraHelpSourcesList()
1096         for helpItem in self.userHelpList:
1097             self.listHelp.insert(END,helpItem[0])
1098         self.SetHelpListButtonStates()
1099         #self.userHelpBrowser.set(idleConf.GetOption('main','General',
1100         #        'user-help-browser',default=0,type='bool'))
1101         #self.helpBrowser.set(idleConf.GetOption('main','General',
1102         #        'user-help-browser-command',default=''))
1103         #self.OnCheckUserHelpBrowser()
1104 
1105     def LoadConfigs(self):
1106         """
1107         load configuration from default and user config files and populate
1108         the widgets on the config dialog pages.
1109         """
1110         ### fonts / tabs page
1111         self.LoadFontCfg()
1112         self.LoadTabCfg()
1113         ### highlighting page
1114         self.LoadThemeCfg()
1115         ### keys page
1116         self.LoadKeyCfg()
1117         ### general page
1118         self.LoadGeneralCfg()
1119 
1120     def SaveNewKeySet(self,keySetName,keySet):
1121         """
1122         save a newly created core key set.
1123         keySetName - string, the name of the new key set
1124         keySet - dictionary containing the new key set
1125         """
1126         if not idleConf.userCfg['keys'].has_section(keySetName):
1127             idleConf.userCfg['keys'].add_section(keySetName)
1128         for event in keySet.keys():
1129             value=keySet[event]
1130             idleConf.userCfg['keys'].SetOption(keySetName,event,value)
1131 
1132     def SaveNewTheme(self,themeName,theme):
1133         """
1134         save a newly created theme.
1135         themeName - string, the name of the new theme
1136         theme - dictionary containing the new theme
1137         """
1138         if not idleConf.userCfg['highlight'].has_section(themeName):
1139             idleConf.userCfg['highlight'].add_section(themeName)
1140         for element in theme.keys():
1141             value=theme[element]
1142             idleConf.userCfg['highlight'].SetOption(themeName,element,value)
1143 
1144     def SetUserValue(self,configType,section,item,value):
1145         if idleConf.defaultCfg[configType].has_option(section,item):
1146             if idleConf.defaultCfg[configType].Get(section,item)==value:
1147                 #the setting equals a default setting, remove it from user cfg
1148                 return idleConf.userCfg[configType].RemoveOption(section,item)
1149         #if we got here set the option
1150         return idleConf.userCfg[configType].SetOption(section,item,value)
1151 
1152     def SaveAllChangedConfigs(self):
1153         "Save configuration changes to the user config file."
1154         idleConf.userCfg['main'].Save()
1155         for configType in self.changedItems.keys():
1156             cfgTypeHasChanges = False
1157             for section in self.changedItems[configType].keys():
1158                 if section == 'HelpFiles':
1159                     #this section gets completely replaced
1160                     idleConf.userCfg['main'].remove_section('HelpFiles')
1161                     cfgTypeHasChanges = True
1162                 for item in self.changedItems[configType][section].keys():
1163                     value = self.changedItems[configType][section][item]
1164                     if self.SetUserValue(configType,section,item,value):
1165                         cfgTypeHasChanges = True
1166             if cfgTypeHasChanges:
1167                 idleConf.userCfg[configType].Save()
1168         self.ResetChangedItems() #clear the changed items dict
1169 
1170     def ActivateConfigChanges(self):
1171         #things that need to be done to make
1172         #applied config changes dynamic:
1173         #update editor/shell font and repaint
1174         #dynamically update indentation setttings
1175         #update theme and repaint
1176         #update keybindings and re-bind
1177         #update user help sources menu
1178         winInstances=self.parent.instance_dict.keys()
1179         for instance in winInstances:
1180             instance.ResetColorizer()
1181             instance.ResetFont()
1182             instance.ResetKeybindings()
1183             instance.reset_help_menu_entries()
1184 
1185     def Cancel(self):
1186         self.destroy()
1187 
1188     def Ok(self):
1189         self.Apply()
1190         self.destroy()
1191 
1192     def Apply(self):
1193         self.SaveAllChangedConfigs()
1194         self.ActivateConfigChanges()
1195 
1196     def Help(self):
1197         pass
1198 
1199 if __name__ == '__main__':
1200     #test the dialog
1201     root=Tk()
1202     Button(root,text='Dialog',
1203             command=lambda:ConfigDialog(root,'Settings')).pack()
1204     root.instance_dict={}
1205     root.mainloop()
1206 

Generated by PyXR 0.9.4
SourceForge.net Logo