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