source: python/vendor/Python-2.7.6/Lib/idlelib/configDialog.py

Last change on this file was 388, checked in by dmik, 11 years ago

python: Update vendor to 2.7.6.

  • Property svn:eol-style set to native
File size: 52.2 KB
Line 
1"""IDLE Configuration Dialog: support user customization of IDLE by GUI
2
3Customize font faces, sizes, and colorization attributes. Set indentation
4defaults. Customize keybindings. Colorization and keybindings can be
5saved as user defined sets. Select startup options including shell/editor
6and default window size. Define additional help sources.
7
8Note that tab width in IDLE is currently fixed at eight due to Tk issues.
9Refer to comments in EditorWindow autoindent code for details.
10
11"""
12from Tkinter import *
13import tkMessageBox, tkColorChooser, tkFont
14import string
15
16from idlelib.configHandler import idleConf
17from idlelib.dynOptionMenuWidget import DynOptionMenu
18from idlelib.tabbedpages import TabbedPageSet
19from idlelib.keybindingDialog import GetKeysDialog
20from idlelib.configSectionNameDialog import GetCfgSectionNameDialog
21from idlelib.configHelpSourceEdit import GetHelpSourceDialog
22from idlelib import macosxSupport
23
24class ConfigDialog(Toplevel):
25
26 def __init__(self,parent,title):
27 Toplevel.__init__(self, parent)
28 self.wm_withdraw()
29
30 self.configure(borderwidth=5)
31 self.title('IDLE Preferences')
32 self.geometry("+%d+%d" % (parent.winfo_rootx()+20,
33 parent.winfo_rooty()+30))
34 #Theme Elements. Each theme element key is its display name.
35 #The first value of the tuple is the sample area tag name.
36 #The second value is the display name list sort index.
37 self.themeElements={'Normal Text':('normal','00'),
38 'Python Keywords':('keyword','01'),
39 'Python Definitions':('definition','02'),
40 'Python Builtins':('builtin', '03'),
41 'Python Comments':('comment','04'),
42 'Python Strings':('string','05'),
43 'Selected Text':('hilite','06'),
44 'Found Text':('hit','07'),
45 'Cursor':('cursor','08'),
46 'Error Text':('error','09'),
47 'Shell Normal Text':('console','10'),
48 'Shell Stdout Text':('stdout','11'),
49 'Shell Stderr Text':('stderr','12'),
50 }
51 self.ResetChangedItems() #load initial values in changed items dict
52 self.CreateWidgets()
53 self.resizable(height=FALSE,width=FALSE)
54 self.transient(parent)
55 self.grab_set()
56 self.protocol("WM_DELETE_WINDOW", self.Cancel)
57 self.parent = parent
58 self.tabPages.focus_set()
59 #key bindings for this dialog
60 #self.bind('<Escape>',self.Cancel) #dismiss dialog, no save
61 #self.bind('<Alt-a>',self.Apply) #apply changes, save
62 #self.bind('<F1>',self.Help) #context help
63 self.LoadConfigs()
64 self.AttachVarCallbacks() #avoid callbacks during LoadConfigs
65
66 self.wm_deiconify()
67 self.wait_window()
68
69 def CreateWidgets(self):
70 self.tabPages = TabbedPageSet(self,
71 page_names=['Fonts/Tabs','Highlighting','Keys','General'])
72 frameActionButtons = Frame(self,pady=2)
73 #action buttons
74 if macosxSupport.runningAsOSXApp():
75 # Changing the default padding on OSX results in unreadable
76 # text in the buttons
77 paddingArgs={}
78 else:
79 paddingArgs={'padx':6, 'pady':3}
80
81 self.buttonHelp = Button(frameActionButtons,text='Help',
82 command=self.Help,takefocus=FALSE,
83 **paddingArgs)
84 self.buttonOk = Button(frameActionButtons,text='Ok',
85 command=self.Ok,takefocus=FALSE,
86 **paddingArgs)
87 self.buttonApply = Button(frameActionButtons,text='Apply',
88 command=self.Apply,takefocus=FALSE,
89 **paddingArgs)
90 self.buttonCancel = Button(frameActionButtons,text='Cancel',
91 command=self.Cancel,takefocus=FALSE,
92 **paddingArgs)
93 self.CreatePageFontTab()
94 self.CreatePageHighlight()
95 self.CreatePageKeys()
96 self.CreatePageGeneral()
97 self.buttonHelp.pack(side=RIGHT,padx=5)
98 self.buttonOk.pack(side=LEFT,padx=5)
99 self.buttonApply.pack(side=LEFT,padx=5)
100 self.buttonCancel.pack(side=LEFT,padx=5)
101 frameActionButtons.pack(side=BOTTOM)
102 Frame(self, height=2, borderwidth=0).pack(side=BOTTOM)
103 self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH)
104
105 def CreatePageFontTab(self):
106 #tkVars
107 self.fontSize=StringVar(self)
108 self.fontBold=BooleanVar(self)
109 self.fontName=StringVar(self)
110 self.spaceNum=IntVar(self)
111 self.editFont=tkFont.Font(self,('courier',10,'normal'))
112 ##widget creation
113 #body frame
114 frame=self.tabPages.pages['Fonts/Tabs'].frame
115 #body section frames
116 frameFont=LabelFrame(frame,borderwidth=2,relief=GROOVE,
117 text=' Base Editor Font ')
118 frameIndent=LabelFrame(frame,borderwidth=2,relief=GROOVE,
119 text=' Indentation Width ')
120 #frameFont
121 frameFontName=Frame(frameFont)
122 frameFontParam=Frame(frameFont)
123 labelFontNameTitle=Label(frameFontName,justify=LEFT,
124 text='Font Face :')
125 self.listFontName=Listbox(frameFontName,height=5,takefocus=FALSE,
126 exportselection=FALSE)
127 self.listFontName.bind('<ButtonRelease-1>',self.OnListFontButtonRelease)
128 scrollFont=Scrollbar(frameFontName)
129 scrollFont.config(command=self.listFontName.yview)
130 self.listFontName.config(yscrollcommand=scrollFont.set)
131 labelFontSizeTitle=Label(frameFontParam,text='Size :')
132 self.optMenuFontSize=DynOptionMenu(frameFontParam,self.fontSize,None,
133 command=self.SetFontSample)
134 checkFontBold=Checkbutton(frameFontParam,variable=self.fontBold,
135 onvalue=1,offvalue=0,text='Bold',command=self.SetFontSample)
136 frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1)
137 self.labelFontSample=Label(frameFontSample,
138 text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]',
139 justify=LEFT,font=self.editFont)
140 #frameIndent
141 frameIndentSize=Frame(frameIndent)
142 labelSpaceNumTitle=Label(frameIndentSize, justify=LEFT,
143 text='Python Standard: 4 Spaces!')
144 self.scaleSpaceNum=Scale(frameIndentSize, variable=self.spaceNum,
145 orient='horizontal',
146 tickinterval=2, from_=2, to=16)
147 #widget packing
148 #body
149 frameFont.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH)
150 frameIndent.pack(side=LEFT,padx=5,pady=5,fill=Y)
151 #frameFont
152 frameFontName.pack(side=TOP,padx=5,pady=5,fill=X)
153 frameFontParam.pack(side=TOP,padx=5,pady=5,fill=X)
154 labelFontNameTitle.pack(side=TOP,anchor=W)
155 self.listFontName.pack(side=LEFT,expand=TRUE,fill=X)
156 scrollFont.pack(side=LEFT,fill=Y)
157 labelFontSizeTitle.pack(side=LEFT,anchor=W)
158 self.optMenuFontSize.pack(side=LEFT,anchor=W)
159 checkFontBold.pack(side=LEFT,anchor=W,padx=20)
160 frameFontSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
161 self.labelFontSample.pack(expand=TRUE,fill=BOTH)
162 #frameIndent
163 frameIndentSize.pack(side=TOP,fill=X)
164 labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5)
165 self.scaleSpaceNum.pack(side=TOP,padx=5,fill=X)
166 return frame
167
168 def CreatePageHighlight(self):
169 self.builtinTheme=StringVar(self)
170 self.customTheme=StringVar(self)
171 self.fgHilite=BooleanVar(self)
172 self.colour=StringVar(self)
173 self.fontName=StringVar(self)
174 self.themeIsBuiltin=BooleanVar(self)
175 self.highlightTarget=StringVar(self)
176 ##widget creation
177 #body frame
178 frame=self.tabPages.pages['Highlighting'].frame
179 #body section frames
180 frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE,
181 text=' Custom Highlighting ')
182 frameTheme=LabelFrame(frame,borderwidth=2,relief=GROOVE,
183 text=' Highlighting Theme ')
184 #frameCustom
185 self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1,
186 font=('courier',12,''),cursor='hand2',width=21,height=11,
187 takefocus=FALSE,highlightthickness=0,wrap=NONE)
188 text=self.textHighlightSample
189 text.bind('<Double-Button-1>',lambda e: 'break')
190 text.bind('<B1-Motion>',lambda e: 'break')
191 textAndTags=(('#you can click here','comment'),('\n','normal'),
192 ('#to choose items','comment'),('\n','normal'),('def','keyword'),
193 (' ','normal'),('func','definition'),('(param):','normal'),
194 ('\n ','normal'),('"""string"""','string'),('\n var0 = ','normal'),
195 ("'string'",'string'),('\n var1 = ','normal'),("'selected'",'hilite'),
196 ('\n var2 = ','normal'),("'found'",'hit'),
197 ('\n var3 = ','normal'),('list', 'builtin'), ('(','normal'),
198 ('None', 'builtin'),(')\n\n','normal'),
199 (' error ','error'),(' ','normal'),('cursor |','cursor'),
200 ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'),
201 (' ','normal'),('stderr','stderr'),('\n','normal'))
202 for txTa in textAndTags:
203 text.insert(END,txTa[0],txTa[1])
204 for element in self.themeElements.keys():
205 text.tag_bind(self.themeElements[element][0],'<ButtonPress-1>',
206 lambda event,elem=element: event.widget.winfo_toplevel()
207 .highlightTarget.set(elem))
208 text.config(state=DISABLED)
209 self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1)
210 frameFgBg=Frame(frameCustom)
211 buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :',
212 command=self.GetColour,highlightthickness=0)
213 self.optMenuHighlightTarget=DynOptionMenu(self.frameColourSet,
214 self.highlightTarget,None,highlightthickness=0)#,command=self.SetHighlightTargetBinding
215 self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite,
216 value=1,text='Foreground',command=self.SetColourSampleBinding)
217 self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite,
218 value=0,text='Background',command=self.SetColourSampleBinding)
219 self.fgHilite.set(1)
220 buttonSaveCustomTheme=Button(frameCustom,
221 text='Save as New Custom Theme',command=self.SaveAsNewTheme)
222 #frameTheme
223 labelTypeTitle=Label(frameTheme,text='Select : ')
224 self.radioThemeBuiltin=Radiobutton(frameTheme,variable=self.themeIsBuiltin,
225 value=1,command=self.SetThemeType,text='a Built-in Theme')
226 self.radioThemeCustom=Radiobutton(frameTheme,variable=self.themeIsBuiltin,
227 value=0,command=self.SetThemeType,text='a Custom Theme')
228 self.optMenuThemeBuiltin=DynOptionMenu(frameTheme,
229 self.builtinTheme,None,command=None)
230 self.optMenuThemeCustom=DynOptionMenu(frameTheme,
231 self.customTheme,None,command=None)
232 self.buttonDeleteCustomTheme=Button(frameTheme,text='Delete Custom Theme',
233 command=self.DeleteCustomTheme)
234 ##widget packing
235 #body
236 frameCustom.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH)
237 frameTheme.pack(side=LEFT,padx=5,pady=5,fill=Y)
238 #frameCustom
239 self.frameColourSet.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=X)
240 frameFgBg.pack(side=TOP,padx=5,pady=0)
241 self.textHighlightSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,
242 fill=BOTH)
243 buttonSetColour.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=4)
244 self.optMenuHighlightTarget.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=3)
245 self.radioFg.pack(side=LEFT,anchor=E)
246 self.radioBg.pack(side=RIGHT,anchor=W)
247 buttonSaveCustomTheme.pack(side=BOTTOM,fill=X,padx=5,pady=5)
248 #frameTheme
249 labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
250 self.radioThemeBuiltin.pack(side=TOP,anchor=W,padx=5)
251 self.radioThemeCustom.pack(side=TOP,anchor=W,padx=5,pady=2)
252 self.optMenuThemeBuiltin.pack(side=TOP,fill=X,padx=5,pady=5)
253 self.optMenuThemeCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5)
254 self.buttonDeleteCustomTheme.pack(side=TOP,fill=X,padx=5,pady=5)
255 return frame
256
257 def CreatePageKeys(self):
258 #tkVars
259 self.bindingTarget=StringVar(self)
260 self.builtinKeys=StringVar(self)
261 self.customKeys=StringVar(self)
262 self.keysAreBuiltin=BooleanVar(self)
263 self.keyBinding=StringVar(self)
264 ##widget creation
265 #body frame
266 frame=self.tabPages.pages['Keys'].frame
267 #body section frames
268 frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE,
269 text=' Custom Key Bindings ')
270 frameKeySets=LabelFrame(frame,borderwidth=2,relief=GROOVE,
271 text=' Key Set ')
272 #frameCustom
273 frameTarget=Frame(frameCustom)
274 labelTargetTitle=Label(frameTarget,text='Action - Key(s)')
275 scrollTargetY=Scrollbar(frameTarget)
276 scrollTargetX=Scrollbar(frameTarget,orient=HORIZONTAL)
277 self.listBindings=Listbox(frameTarget,takefocus=FALSE,
278 exportselection=FALSE)
279 self.listBindings.bind('<ButtonRelease-1>',self.KeyBindingSelected)
280 scrollTargetY.config(command=self.listBindings.yview)
281 scrollTargetX.config(command=self.listBindings.xview)
282 self.listBindings.config(yscrollcommand=scrollTargetY.set)
283 self.listBindings.config(xscrollcommand=scrollTargetX.set)
284 self.buttonNewKeys=Button(frameCustom,text='Get New Keys for Selection',
285 command=self.GetNewKeys,state=DISABLED)
286 #frameKeySets
287 frames = [Frame(frameKeySets, padx=2, pady=2, borderwidth=0)
288 for i in range(2)]
289 self.radioKeysBuiltin=Radiobutton(frames[0],variable=self.keysAreBuiltin,
290 value=1,command=self.SetKeysType,text='Use a Built-in Key Set')
291 self.radioKeysCustom=Radiobutton(frames[0],variable=self.keysAreBuiltin,
292 value=0,command=self.SetKeysType,text='Use a Custom Key Set')
293 self.optMenuKeysBuiltin=DynOptionMenu(frames[0],
294 self.builtinKeys,None,command=None)
295 self.optMenuKeysCustom=DynOptionMenu(frames[0],
296 self.customKeys,None,command=None)
297 self.buttonDeleteCustomKeys=Button(frames[1],text='Delete Custom Key Set',
298 command=self.DeleteCustomKeys)
299 buttonSaveCustomKeys=Button(frames[1],
300 text='Save as New Custom Key Set',command=self.SaveAsNewKeySet)
301 ##widget packing
302 #body
303 frameCustom.pack(side=BOTTOM,padx=5,pady=5,expand=TRUE,fill=BOTH)
304 frameKeySets.pack(side=BOTTOM,padx=5,pady=5,fill=BOTH)
305 #frameCustom
306 self.buttonNewKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5)
307 frameTarget.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH)
308 #frame target
309 frameTarget.columnconfigure(0,weight=1)
310 frameTarget.rowconfigure(1,weight=1)
311 labelTargetTitle.grid(row=0,column=0,columnspan=2,sticky=W)
312 self.listBindings.grid(row=1,column=0,sticky=NSEW)
313 scrollTargetY.grid(row=1,column=1,sticky=NS)
314 scrollTargetX.grid(row=2,column=0,sticky=EW)
315 #frameKeySets
316 self.radioKeysBuiltin.grid(row=0, column=0, sticky=W+NS)
317 self.radioKeysCustom.grid(row=1, column=0, sticky=W+NS)
318 self.optMenuKeysBuiltin.grid(row=0, column=1, sticky=NSEW)
319 self.optMenuKeysCustom.grid(row=1, column=1, sticky=NSEW)
320 self.buttonDeleteCustomKeys.pack(side=LEFT,fill=X,expand=True,padx=2)
321 buttonSaveCustomKeys.pack(side=LEFT,fill=X,expand=True,padx=2)
322 frames[0].pack(side=TOP, fill=BOTH, expand=True)
323 frames[1].pack(side=TOP, fill=X, expand=True, pady=2)
324 return frame
325
326 def CreatePageGeneral(self):
327 #tkVars
328 self.winWidth=StringVar(self)
329 self.winHeight=StringVar(self)
330 self.paraWidth=StringVar(self)
331 self.startupEdit=IntVar(self)
332 self.autoSave=IntVar(self)
333 self.encoding=StringVar(self)
334 self.userHelpBrowser=BooleanVar(self)
335 self.helpBrowser=StringVar(self)
336 #widget creation
337 #body
338 frame=self.tabPages.pages['General'].frame
339 #body section frames
340 frameRun=LabelFrame(frame,borderwidth=2,relief=GROOVE,
341 text=' Startup Preferences ')
342 frameSave=LabelFrame(frame,borderwidth=2,relief=GROOVE,
343 text=' Autosave Preferences ')
344 frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE)
345 frameParaSize=Frame(frame,borderwidth=2,relief=GROOVE)
346 frameEncoding=Frame(frame,borderwidth=2,relief=GROOVE)
347 frameHelp=LabelFrame(frame,borderwidth=2,relief=GROOVE,
348 text=' Additional Help Sources ')
349 #frameRun
350 labelRunChoiceTitle=Label(frameRun,text='At Startup')
351 radioStartupEdit=Radiobutton(frameRun,variable=self.startupEdit,
352 value=1,command=self.SetKeysType,text="Open Edit Window")
353 radioStartupShell=Radiobutton(frameRun,variable=self.startupEdit,
354 value=0,command=self.SetKeysType,text='Open Shell Window')
355 #frameSave
356 labelRunSaveTitle=Label(frameSave,text='At Start of Run (F5) ')
357 radioSaveAsk=Radiobutton(frameSave,variable=self.autoSave,
358 value=0,command=self.SetKeysType,text="Prompt to Save")
359 radioSaveAuto=Radiobutton(frameSave,variable=self.autoSave,
360 value=1,command=self.SetKeysType,text='No Prompt')
361 #frameWinSize
362 labelWinSizeTitle=Label(frameWinSize,text='Initial Window Size'+
363 ' (in characters)')
364 labelWinWidthTitle=Label(frameWinSize,text='Width')
365 entryWinWidth=Entry(frameWinSize,textvariable=self.winWidth,
366 width=3)
367 labelWinHeightTitle=Label(frameWinSize,text='Height')
368 entryWinHeight=Entry(frameWinSize,textvariable=self.winHeight,
369 width=3)
370 #paragraphFormatWidth
371 labelParaWidthTitle=Label(frameParaSize,text='Paragraph reformat'+
372 ' width (in characters)')
373 entryParaWidth=Entry(frameParaSize,textvariable=self.paraWidth,
374 width=3)
375 #frameEncoding
376 labelEncodingTitle=Label(frameEncoding,text="Default Source Encoding")
377 radioEncLocale=Radiobutton(frameEncoding,variable=self.encoding,
378 value="locale",text="Locale-defined")
379 radioEncUTF8=Radiobutton(frameEncoding,variable=self.encoding,
380 value="utf-8",text="UTF-8")
381 radioEncNone=Radiobutton(frameEncoding,variable=self.encoding,
382 value="none",text="None")
383 #frameHelp
384 frameHelpList=Frame(frameHelp)
385 frameHelpListButtons=Frame(frameHelpList)
386 scrollHelpList=Scrollbar(frameHelpList)
387 self.listHelp=Listbox(frameHelpList,height=5,takefocus=FALSE,
388 exportselection=FALSE)
389 scrollHelpList.config(command=self.listHelp.yview)
390 self.listHelp.config(yscrollcommand=scrollHelpList.set)
391 self.listHelp.bind('<ButtonRelease-1>',self.HelpSourceSelected)
392 self.buttonHelpListEdit=Button(frameHelpListButtons,text='Edit',
393 state=DISABLED,width=8,command=self.HelpListItemEdit)
394 self.buttonHelpListAdd=Button(frameHelpListButtons,text='Add',
395 width=8,command=self.HelpListItemAdd)
396 self.buttonHelpListRemove=Button(frameHelpListButtons,text='Remove',
397 state=DISABLED,width=8,command=self.HelpListItemRemove)
398 #widget packing
399 #body
400 frameRun.pack(side=TOP,padx=5,pady=5,fill=X)
401 frameSave.pack(side=TOP,padx=5,pady=5,fill=X)
402 frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X)
403 frameParaSize.pack(side=TOP,padx=5,pady=5,fill=X)
404 frameEncoding.pack(side=TOP,padx=5,pady=5,fill=X)
405 frameHelp.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
406 #frameRun
407 labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
408 radioStartupShell.pack(side=RIGHT,anchor=W,padx=5,pady=5)
409 radioStartupEdit.pack(side=RIGHT,anchor=W,padx=5,pady=5)
410 #frameSave
411 labelRunSaveTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
412 radioSaveAuto.pack(side=RIGHT,anchor=W,padx=5,pady=5)
413 radioSaveAsk.pack(side=RIGHT,anchor=W,padx=5,pady=5)
414 #frameWinSize
415 labelWinSizeTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
416 entryWinHeight.pack(side=RIGHT,anchor=E,padx=10,pady=5)
417 labelWinHeightTitle.pack(side=RIGHT,anchor=E,pady=5)
418 entryWinWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5)
419 labelWinWidthTitle.pack(side=RIGHT,anchor=E,pady=5)
420 #paragraphFormatWidth
421 labelParaWidthTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
422 entryParaWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5)
423 #frameEncoding
424 labelEncodingTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
425 radioEncNone.pack(side=RIGHT,anchor=E,pady=5)
426 radioEncUTF8.pack(side=RIGHT,anchor=E,pady=5)
427 radioEncLocale.pack(side=RIGHT,anchor=E,pady=5)
428 #frameHelp
429 frameHelpListButtons.pack(side=RIGHT,padx=5,pady=5,fill=Y)
430 frameHelpList.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
431 scrollHelpList.pack(side=RIGHT,anchor=W,fill=Y)
432 self.listHelp.pack(side=LEFT,anchor=E,expand=TRUE,fill=BOTH)
433 self.buttonHelpListEdit.pack(side=TOP,anchor=W,pady=5)
434 self.buttonHelpListAdd.pack(side=TOP,anchor=W)
435 self.buttonHelpListRemove.pack(side=TOP,anchor=W,pady=5)
436 return frame
437
438 def AttachVarCallbacks(self):
439 self.fontSize.trace_variable('w',self.VarChanged_fontSize)
440 self.fontName.trace_variable('w',self.VarChanged_fontName)
441 self.fontBold.trace_variable('w',self.VarChanged_fontBold)
442 self.spaceNum.trace_variable('w',self.VarChanged_spaceNum)
443 self.colour.trace_variable('w',self.VarChanged_colour)
444 self.builtinTheme.trace_variable('w',self.VarChanged_builtinTheme)
445 self.customTheme.trace_variable('w',self.VarChanged_customTheme)
446 self.themeIsBuiltin.trace_variable('w',self.VarChanged_themeIsBuiltin)
447 self.highlightTarget.trace_variable('w',self.VarChanged_highlightTarget)
448 self.keyBinding.trace_variable('w',self.VarChanged_keyBinding)
449 self.builtinKeys.trace_variable('w',self.VarChanged_builtinKeys)
450 self.customKeys.trace_variable('w',self.VarChanged_customKeys)
451 self.keysAreBuiltin.trace_variable('w',self.VarChanged_keysAreBuiltin)
452 self.winWidth.trace_variable('w',self.VarChanged_winWidth)
453 self.winHeight.trace_variable('w',self.VarChanged_winHeight)
454 self.paraWidth.trace_variable('w',self.VarChanged_paraWidth)
455 self.startupEdit.trace_variable('w',self.VarChanged_startupEdit)
456 self.autoSave.trace_variable('w',self.VarChanged_autoSave)
457 self.encoding.trace_variable('w',self.VarChanged_encoding)
458
459 def VarChanged_fontSize(self,*params):
460 value=self.fontSize.get()
461 self.AddChangedItem('main','EditorWindow','font-size',value)
462
463 def VarChanged_fontName(self,*params):
464 value=self.fontName.get()
465 self.AddChangedItem('main','EditorWindow','font',value)
466
467 def VarChanged_fontBold(self,*params):
468 value=self.fontBold.get()
469 self.AddChangedItem('main','EditorWindow','font-bold',value)
470
471 def VarChanged_spaceNum(self,*params):
472 value=self.spaceNum.get()
473 self.AddChangedItem('main','Indent','num-spaces',value)
474
475 def VarChanged_colour(self,*params):
476 self.OnNewColourSet()
477
478 def VarChanged_builtinTheme(self,*params):
479 value=self.builtinTheme.get()
480 self.AddChangedItem('main','Theme','name',value)
481 self.PaintThemeSample()
482
483 def VarChanged_customTheme(self,*params):
484 value=self.customTheme.get()
485 if value != '- no custom themes -':
486 self.AddChangedItem('main','Theme','name',value)
487 self.PaintThemeSample()
488
489 def VarChanged_themeIsBuiltin(self,*params):
490 value=self.themeIsBuiltin.get()
491 self.AddChangedItem('main','Theme','default',value)
492 if value:
493 self.VarChanged_builtinTheme()
494 else:
495 self.VarChanged_customTheme()
496
497 def VarChanged_highlightTarget(self,*params):
498 self.SetHighlightTarget()
499
500 def VarChanged_keyBinding(self,*params):
501 value=self.keyBinding.get()
502 keySet=self.customKeys.get()
503 event=self.listBindings.get(ANCHOR).split()[0]
504 if idleConf.IsCoreBinding(event):
505 #this is a core keybinding
506 self.AddChangedItem('keys',keySet,event,value)
507 else: #this is an extension key binding
508 extName=idleConf.GetExtnNameForEvent(event)
509 extKeybindSection=extName+'_cfgBindings'
510 self.AddChangedItem('extensions',extKeybindSection,event,value)
511
512 def VarChanged_builtinKeys(self,*params):
513 value=self.builtinKeys.get()
514 self.AddChangedItem('main','Keys','name',value)
515 self.LoadKeysList(value)
516
517 def VarChanged_customKeys(self,*params):
518 value=self.customKeys.get()
519 if value != '- no custom keys -':
520 self.AddChangedItem('main','Keys','name',value)
521 self.LoadKeysList(value)
522
523 def VarChanged_keysAreBuiltin(self,*params):
524 value=self.keysAreBuiltin.get()
525 self.AddChangedItem('main','Keys','default',value)
526 if value:
527 self.VarChanged_builtinKeys()
528 else:
529 self.VarChanged_customKeys()
530
531 def VarChanged_winWidth(self,*params):
532 value=self.winWidth.get()
533 self.AddChangedItem('main','EditorWindow','width',value)
534
535 def VarChanged_winHeight(self,*params):
536 value=self.winHeight.get()
537 self.AddChangedItem('main','EditorWindow','height',value)
538
539 def VarChanged_paraWidth(self,*params):
540 value=self.paraWidth.get()
541 self.AddChangedItem('main','FormatParagraph','paragraph',value)
542
543 def VarChanged_startupEdit(self,*params):
544 value=self.startupEdit.get()
545 self.AddChangedItem('main','General','editor-on-startup',value)
546
547 def VarChanged_autoSave(self,*params):
548 value=self.autoSave.get()
549 self.AddChangedItem('main','General','autosave',value)
550
551 def VarChanged_encoding(self,*params):
552 value=self.encoding.get()
553 self.AddChangedItem('main','EditorWindow','encoding',value)
554
555 def ResetChangedItems(self):
556 #When any config item is changed in this dialog, an entry
557 #should be made in the relevant section (config type) of this
558 #dictionary. The key should be the config file section name and the
559 #value a dictionary, whose key:value pairs are item=value pairs for
560 #that config file section.
561 self.changedItems={'main':{},'highlight':{},'keys':{},'extensions':{}}
562
563 def AddChangedItem(self,type,section,item,value):
564 value=str(value) #make sure we use a string
565 if section not in self.changedItems[type]:
566 self.changedItems[type][section]={}
567 self.changedItems[type][section][item]=value
568
569 def GetDefaultItems(self):
570 dItems={'main':{},'highlight':{},'keys':{},'extensions':{}}
571 for configType in dItems.keys():
572 sections=idleConf.GetSectionList('default',configType)
573 for section in sections:
574 dItems[configType][section]={}
575 options=idleConf.defaultCfg[configType].GetOptionList(section)
576 for option in options:
577 dItems[configType][section][option]=(
578 idleConf.defaultCfg[configType].Get(section,option))
579 return dItems
580
581 def SetThemeType(self):
582 if self.themeIsBuiltin.get():
583 self.optMenuThemeBuiltin.config(state=NORMAL)
584 self.optMenuThemeCustom.config(state=DISABLED)
585 self.buttonDeleteCustomTheme.config(state=DISABLED)
586 else:
587 self.optMenuThemeBuiltin.config(state=DISABLED)
588 self.radioThemeCustom.config(state=NORMAL)
589 self.optMenuThemeCustom.config(state=NORMAL)
590 self.buttonDeleteCustomTheme.config(state=NORMAL)
591
592 def SetKeysType(self):
593 if self.keysAreBuiltin.get():
594 self.optMenuKeysBuiltin.config(state=NORMAL)
595 self.optMenuKeysCustom.config(state=DISABLED)
596 self.buttonDeleteCustomKeys.config(state=DISABLED)
597 else:
598 self.optMenuKeysBuiltin.config(state=DISABLED)
599 self.radioKeysCustom.config(state=NORMAL)
600 self.optMenuKeysCustom.config(state=NORMAL)
601 self.buttonDeleteCustomKeys.config(state=NORMAL)
602
603 def GetNewKeys(self):
604 listIndex=self.listBindings.index(ANCHOR)
605 binding=self.listBindings.get(listIndex)
606 bindName=binding.split()[0] #first part, up to first space
607 if self.keysAreBuiltin.get():
608 currentKeySetName=self.builtinKeys.get()
609 else:
610 currentKeySetName=self.customKeys.get()
611 currentBindings=idleConf.GetCurrentKeySet()
612 if currentKeySetName in self.changedItems['keys'].keys(): #unsaved changes
613 keySetChanges=self.changedItems['keys'][currentKeySetName]
614 for event in keySetChanges.keys():
615 currentBindings[event]=keySetChanges[event].split()
616 currentKeySequences=currentBindings.values()
617 newKeys=GetKeysDialog(self,'Get New Keys',bindName,
618 currentKeySequences).result
619 if newKeys: #new keys were specified
620 if self.keysAreBuiltin.get(): #current key set is a built-in
621 message=('Your changes will be saved as a new Custom Key Set. '+
622 'Enter a name for your new Custom Key Set below.')
623 newKeySet=self.GetNewKeysName(message)
624 if not newKeySet: #user cancelled custom key set creation
625 self.listBindings.select_set(listIndex)
626 self.listBindings.select_anchor(listIndex)
627 return
628 else: #create new custom key set based on previously active key set
629 self.CreateNewKeySet(newKeySet)
630 self.listBindings.delete(listIndex)
631 self.listBindings.insert(listIndex,bindName+' - '+newKeys)
632 self.listBindings.select_set(listIndex)
633 self.listBindings.select_anchor(listIndex)
634 self.keyBinding.set(newKeys)
635 else:
636 self.listBindings.select_set(listIndex)
637 self.listBindings.select_anchor(listIndex)
638
639 def GetNewKeysName(self,message):
640 usedNames=(idleConf.GetSectionList('user','keys')+
641 idleConf.GetSectionList('default','keys'))
642 newKeySet=GetCfgSectionNameDialog(self,'New Custom Key Set',
643 message,usedNames).result
644 return newKeySet
645
646 def SaveAsNewKeySet(self):
647 newKeysName=self.GetNewKeysName('New Key Set Name:')
648 if newKeysName:
649 self.CreateNewKeySet(newKeysName)
650
651 def KeyBindingSelected(self,event):
652 self.buttonNewKeys.config(state=NORMAL)
653
654 def CreateNewKeySet(self,newKeySetName):
655 #creates new custom key set based on the previously active key set,
656 #and makes the new key set active
657 if self.keysAreBuiltin.get():
658 prevKeySetName=self.builtinKeys.get()
659 else:
660 prevKeySetName=self.customKeys.get()
661 prevKeys=idleConf.GetCoreKeys(prevKeySetName)
662 newKeys={}
663 for event in prevKeys.keys(): #add key set to changed items
664 eventName=event[2:-2] #trim off the angle brackets
665 binding=string.join(prevKeys[event])
666 newKeys[eventName]=binding
667 #handle any unsaved changes to prev key set
668 if prevKeySetName in self.changedItems['keys'].keys():
669 keySetChanges=self.changedItems['keys'][prevKeySetName]
670 for event in keySetChanges.keys():
671 newKeys[event]=keySetChanges[event]
672 #save the new theme
673 self.SaveNewKeySet(newKeySetName,newKeys)
674 #change gui over to the new key set
675 customKeyList=idleConf.GetSectionList('user','keys')
676 customKeyList.sort()
677 self.optMenuKeysCustom.SetMenu(customKeyList,newKeySetName)
678 self.keysAreBuiltin.set(0)
679 self.SetKeysType()
680
681 def LoadKeysList(self,keySetName):
682 reselect=0
683 newKeySet=0
684 if self.listBindings.curselection():
685 reselect=1
686 listIndex=self.listBindings.index(ANCHOR)
687 keySet=idleConf.GetKeySet(keySetName)
688 bindNames=keySet.keys()
689 bindNames.sort()
690 self.listBindings.delete(0,END)
691 for bindName in bindNames:
692 key=string.join(keySet[bindName]) #make key(s) into a string
693 bindName=bindName[2:-2] #trim off the angle brackets
694 if keySetName in self.changedItems['keys'].keys():
695 #handle any unsaved changes to this key set
696 if bindName in self.changedItems['keys'][keySetName].keys():
697 key=self.changedItems['keys'][keySetName][bindName]
698 self.listBindings.insert(END, bindName+' - '+key)
699 if reselect:
700 self.listBindings.see(listIndex)
701 self.listBindings.select_set(listIndex)
702 self.listBindings.select_anchor(listIndex)
703
704 def DeleteCustomKeys(self):
705 keySetName=self.customKeys.get()
706 if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+
707 'to delete the key set %r ?' % (keySetName),
708 parent=self):
709 return
710 #remove key set from config
711 idleConf.userCfg['keys'].remove_section(keySetName)
712 if keySetName in self.changedItems['keys']:
713 del(self.changedItems['keys'][keySetName])
714 #write changes
715 idleConf.userCfg['keys'].Save()
716 #reload user key set list
717 itemList=idleConf.GetSectionList('user','keys')
718 itemList.sort()
719 if not itemList:
720 self.radioKeysCustom.config(state=DISABLED)
721 self.optMenuKeysCustom.SetMenu(itemList,'- no custom keys -')
722 else:
723 self.optMenuKeysCustom.SetMenu(itemList,itemList[0])
724 #revert to default key set
725 self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys','default'))
726 self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys','name'))
727 #user can't back out of these changes, they must be applied now
728 self.Apply()
729 self.SetKeysType()
730
731 def DeleteCustomTheme(self):
732 themeName=self.customTheme.get()
733 if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+
734 'to delete the theme %r ?' % (themeName,),
735 parent=self):
736 return
737 #remove theme from config
738 idleConf.userCfg['highlight'].remove_section(themeName)
739 if themeName in self.changedItems['highlight']:
740 del(self.changedItems['highlight'][themeName])
741 #write changes
742 idleConf.userCfg['highlight'].Save()
743 #reload user theme list
744 itemList=idleConf.GetSectionList('user','highlight')
745 itemList.sort()
746 if not itemList:
747 self.radioThemeCustom.config(state=DISABLED)
748 self.optMenuThemeCustom.SetMenu(itemList,'- no custom themes -')
749 else:
750 self.optMenuThemeCustom.SetMenu(itemList,itemList[0])
751 #revert to default theme
752 self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme','default'))
753 self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme','name'))
754 #user can't back out of these changes, they must be applied now
755 self.Apply()
756 self.SetThemeType()
757
758 def GetColour(self):
759 target=self.highlightTarget.get()
760 prevColour=self.frameColourSet.cget('bg')
761 rgbTuplet, colourString = tkColorChooser.askcolor(parent=self,
762 title='Pick new colour for : '+target,initialcolor=prevColour)
763 if colourString and (colourString!=prevColour):
764 #user didn't cancel, and they chose a new colour
765 if self.themeIsBuiltin.get(): #current theme is a built-in
766 message=('Your changes will be saved as a new Custom Theme. '+
767 'Enter a name for your new Custom Theme below.')
768 newTheme=self.GetNewThemeName(message)
769 if not newTheme: #user cancelled custom theme creation
770 return
771 else: #create new custom theme based on previously active theme
772 self.CreateNewTheme(newTheme)
773 self.colour.set(colourString)
774 else: #current theme is user defined
775 self.colour.set(colourString)
776
777 def OnNewColourSet(self):
778 newColour=self.colour.get()
779 self.frameColourSet.config(bg=newColour)#set sample
780 if self.fgHilite.get(): plane='foreground'
781 else: plane='background'
782 sampleElement=self.themeElements[self.highlightTarget.get()][0]
783 self.textHighlightSample.tag_config(sampleElement, **{plane:newColour})
784 theme=self.customTheme.get()
785 themeElement=sampleElement+'-'+plane
786 self.AddChangedItem('highlight',theme,themeElement,newColour)
787
788 def GetNewThemeName(self,message):
789 usedNames=(idleConf.GetSectionList('user','highlight')+
790 idleConf.GetSectionList('default','highlight'))
791 newTheme=GetCfgSectionNameDialog(self,'New Custom Theme',
792 message,usedNames).result
793 return newTheme
794
795 def SaveAsNewTheme(self):
796 newThemeName=self.GetNewThemeName('New Theme Name:')
797 if newThemeName:
798 self.CreateNewTheme(newThemeName)
799
800 def CreateNewTheme(self,newThemeName):
801 #creates new custom theme based on the previously active theme,
802 #and makes the new theme active
803 if self.themeIsBuiltin.get():
804 themeType='default'
805 themeName=self.builtinTheme.get()
806 else:
807 themeType='user'
808 themeName=self.customTheme.get()
809 newTheme=idleConf.GetThemeDict(themeType,themeName)
810 #apply any of the old theme's unsaved changes to the new theme
811 if themeName in self.changedItems['highlight'].keys():
812 themeChanges=self.changedItems['highlight'][themeName]
813 for element in themeChanges.keys():
814 newTheme[element]=themeChanges[element]
815 #save the new theme
816 self.SaveNewTheme(newThemeName,newTheme)
817 #change gui over to the new theme
818 customThemeList=idleConf.GetSectionList('user','highlight')
819 customThemeList.sort()
820 self.optMenuThemeCustom.SetMenu(customThemeList,newThemeName)
821 self.themeIsBuiltin.set(0)
822 self.SetThemeType()
823
824 def OnListFontButtonRelease(self,event):
825 font = self.listFontName.get(ANCHOR)
826 self.fontName.set(font.lower())
827 self.SetFontSample()
828
829 def SetFontSample(self,event=None):
830 fontName=self.fontName.get()
831 if self.fontBold.get():
832 fontWeight=tkFont.BOLD
833 else:
834 fontWeight=tkFont.NORMAL
835 newFont = (fontName, self.fontSize.get(), fontWeight)
836 self.labelFontSample.config(font=newFont)
837 self.textHighlightSample.configure(font=newFont)
838
839 def SetHighlightTarget(self):
840 if self.highlightTarget.get()=='Cursor': #bg not possible
841 self.radioFg.config(state=DISABLED)
842 self.radioBg.config(state=DISABLED)
843 self.fgHilite.set(1)
844 else: #both fg and bg can be set
845 self.radioFg.config(state=NORMAL)
846 self.radioBg.config(state=NORMAL)
847 self.fgHilite.set(1)
848 self.SetColourSample()
849
850 def SetColourSampleBinding(self,*args):
851 self.SetColourSample()
852
853 def SetColourSample(self):
854 #set the colour smaple area
855 tag=self.themeElements[self.highlightTarget.get()][0]
856 if self.fgHilite.get(): plane='foreground'
857 else: plane='background'
858 colour=self.textHighlightSample.tag_cget(tag,plane)
859 self.frameColourSet.config(bg=colour)
860
861 def PaintThemeSample(self):
862 if self.themeIsBuiltin.get(): #a default theme
863 theme=self.builtinTheme.get()
864 else: #a user theme
865 theme=self.customTheme.get()
866 for elementTitle in self.themeElements.keys():
867 element=self.themeElements[elementTitle][0]
868 colours=idleConf.GetHighlight(theme,element)
869 if element=='cursor': #cursor sample needs special painting
870 colours['background']=idleConf.GetHighlight(theme,
871 'normal', fgBg='bg')
872 #handle any unsaved changes to this theme
873 if theme in self.changedItems['highlight'].keys():
874 themeDict=self.changedItems['highlight'][theme]
875 if element+'-foreground' in themeDict:
876 colours['foreground']=themeDict[element+'-foreground']
877 if element+'-background' in themeDict:
878 colours['background']=themeDict[element+'-background']
879 self.textHighlightSample.tag_config(element, **colours)
880 self.SetColourSample()
881
882 def HelpSourceSelected(self,event):
883 self.SetHelpListButtonStates()
884
885 def SetHelpListButtonStates(self):
886 if self.listHelp.size()<1: #no entries in list
887 self.buttonHelpListEdit.config(state=DISABLED)
888 self.buttonHelpListRemove.config(state=DISABLED)
889 else: #there are some entries
890 if self.listHelp.curselection(): #there currently is a selection
891 self.buttonHelpListEdit.config(state=NORMAL)
892 self.buttonHelpListRemove.config(state=NORMAL)
893 else: #there currently is not a selection
894 self.buttonHelpListEdit.config(state=DISABLED)
895 self.buttonHelpListRemove.config(state=DISABLED)
896
897 def HelpListItemAdd(self):
898 helpSource=GetHelpSourceDialog(self,'New Help Source').result
899 if helpSource:
900 self.userHelpList.append( (helpSource[0],helpSource[1]) )
901 self.listHelp.insert(END,helpSource[0])
902 self.UpdateUserHelpChangedItems()
903 self.SetHelpListButtonStates()
904
905 def HelpListItemEdit(self):
906 itemIndex=self.listHelp.index(ANCHOR)
907 helpSource=self.userHelpList[itemIndex]
908 newHelpSource=GetHelpSourceDialog(self,'Edit Help Source',
909 menuItem=helpSource[0],filePath=helpSource[1]).result
910 if (not newHelpSource) or (newHelpSource==helpSource):
911 return #no changes
912 self.userHelpList[itemIndex]=newHelpSource
913 self.listHelp.delete(itemIndex)
914 self.listHelp.insert(itemIndex,newHelpSource[0])
915 self.UpdateUserHelpChangedItems()
916 self.SetHelpListButtonStates()
917
918 def HelpListItemRemove(self):
919 itemIndex=self.listHelp.index(ANCHOR)
920 del(self.userHelpList[itemIndex])
921 self.listHelp.delete(itemIndex)
922 self.UpdateUserHelpChangedItems()
923 self.SetHelpListButtonStates()
924
925 def UpdateUserHelpChangedItems(self):
926 "Clear and rebuild the HelpFiles section in self.changedItems"
927 self.changedItems['main']['HelpFiles'] = {}
928 for num in range(1,len(self.userHelpList)+1):
929 self.AddChangedItem('main','HelpFiles',str(num),
930 string.join(self.userHelpList[num-1][:2],';'))
931
932 def LoadFontCfg(self):
933 ##base editor font selection list
934 fonts=list(tkFont.families(self))
935 fonts.sort()
936 for font in fonts:
937 self.listFontName.insert(END,font)
938 configuredFont=idleConf.GetOption('main','EditorWindow','font',
939 default='courier')
940 lc_configuredFont = configuredFont.lower()
941 self.fontName.set(lc_configuredFont)
942 lc_fonts = [s.lower() for s in fonts]
943 if lc_configuredFont in lc_fonts:
944 currentFontIndex = lc_fonts.index(lc_configuredFont)
945 self.listFontName.see(currentFontIndex)
946 self.listFontName.select_set(currentFontIndex)
947 self.listFontName.select_anchor(currentFontIndex)
948 ##font size dropdown
949 fontSize=idleConf.GetOption('main','EditorWindow','font-size',
950 type='int', default='10')
951 self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14',
952 '16','18','20','22'),fontSize )
953 ##fontWeight
954 self.fontBold.set(idleConf.GetOption('main','EditorWindow',
955 'font-bold',default=0,type='bool'))
956 ##font sample
957 self.SetFontSample()
958
959 def LoadTabCfg(self):
960 ##indent sizes
961 spaceNum=idleConf.GetOption('main','Indent','num-spaces',
962 default=4,type='int')
963 self.spaceNum.set(spaceNum)
964
965 def LoadThemeCfg(self):
966 ##current theme type radiobutton
967 self.themeIsBuiltin.set(idleConf.GetOption('main','Theme','default',
968 type='bool',default=1))
969 ##currently set theme
970 currentOption=idleConf.CurrentTheme()
971 ##load available theme option menus
972 if self.themeIsBuiltin.get(): #default theme selected
973 itemList=idleConf.GetSectionList('default','highlight')
974 itemList.sort()
975 self.optMenuThemeBuiltin.SetMenu(itemList,currentOption)
976 itemList=idleConf.GetSectionList('user','highlight')
977 itemList.sort()
978 if not itemList:
979 self.radioThemeCustom.config(state=DISABLED)
980 self.customTheme.set('- no custom themes -')
981 else:
982 self.optMenuThemeCustom.SetMenu(itemList,itemList[0])
983 else: #user theme selected
984 itemList=idleConf.GetSectionList('user','highlight')
985 itemList.sort()
986 self.optMenuThemeCustom.SetMenu(itemList,currentOption)
987 itemList=idleConf.GetSectionList('default','highlight')
988 itemList.sort()
989 self.optMenuThemeBuiltin.SetMenu(itemList,itemList[0])
990 self.SetThemeType()
991 ##load theme element option menu
992 themeNames=self.themeElements.keys()
993 themeNames.sort(key=lambda x: self.themeElements[x][1])
994 self.optMenuHighlightTarget.SetMenu(themeNames,themeNames[0])
995 self.PaintThemeSample()
996 self.SetHighlightTarget()
997
998 def LoadKeyCfg(self):
999 ##current keys type radiobutton
1000 self.keysAreBuiltin.set(idleConf.GetOption('main','Keys','default',
1001 type='bool',default=1))
1002 ##currently set keys
1003 currentOption=idleConf.CurrentKeys()
1004 ##load available keyset option menus
1005 if self.keysAreBuiltin.get(): #default theme selected
1006 itemList=idleConf.GetSectionList('default','keys')
1007 itemList.sort()
1008 self.optMenuKeysBuiltin.SetMenu(itemList,currentOption)
1009 itemList=idleConf.GetSectionList('user','keys')
1010 itemList.sort()
1011 if not itemList:
1012 self.radioKeysCustom.config(state=DISABLED)
1013 self.customKeys.set('- no custom keys -')
1014 else:
1015 self.optMenuKeysCustom.SetMenu(itemList,itemList[0])
1016 else: #user key set selected
1017 itemList=idleConf.GetSectionList('user','keys')
1018 itemList.sort()
1019 self.optMenuKeysCustom.SetMenu(itemList,currentOption)
1020 itemList=idleConf.GetSectionList('default','keys')
1021 itemList.sort()
1022 self.optMenuKeysBuiltin.SetMenu(itemList,itemList[0])
1023 self.SetKeysType()
1024 ##load keyset element list
1025 keySetName=idleConf.CurrentKeys()
1026 self.LoadKeysList(keySetName)
1027
1028 def LoadGeneralCfg(self):
1029 #startup state
1030 self.startupEdit.set(idleConf.GetOption('main','General',
1031 'editor-on-startup',default=1,type='bool'))
1032 #autosave state
1033 self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave',
1034 default=0, type='bool'))
1035 #initial window size
1036 self.winWidth.set(idleConf.GetOption('main','EditorWindow','width',
1037 type='int'))
1038 self.winHeight.set(idleConf.GetOption('main','EditorWindow','height',
1039 type='int'))
1040 #initial paragraph reformat size
1041 self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph',
1042 type='int'))
1043 # default source encoding
1044 self.encoding.set(idleConf.GetOption('main', 'EditorWindow',
1045 'encoding', default='none'))
1046 # additional help sources
1047 self.userHelpList = idleConf.GetAllExtraHelpSourcesList()
1048 for helpItem in self.userHelpList:
1049 self.listHelp.insert(END,helpItem[0])
1050 self.SetHelpListButtonStates()
1051
1052 def LoadConfigs(self):
1053 """
1054 load configuration from default and user config files and populate
1055 the widgets on the config dialog pages.
1056 """
1057 ### fonts / tabs page
1058 self.LoadFontCfg()
1059 self.LoadTabCfg()
1060 ### highlighting page
1061 self.LoadThemeCfg()
1062 ### keys page
1063 self.LoadKeyCfg()
1064 ### general page
1065 self.LoadGeneralCfg()
1066
1067 def SaveNewKeySet(self,keySetName,keySet):
1068 """
1069 save a newly created core key set.
1070 keySetName - string, the name of the new key set
1071 keySet - dictionary containing the new key set
1072 """
1073 if not idleConf.userCfg['keys'].has_section(keySetName):
1074 idleConf.userCfg['keys'].add_section(keySetName)
1075 for event in keySet.keys():
1076 value=keySet[event]
1077 idleConf.userCfg['keys'].SetOption(keySetName,event,value)
1078
1079 def SaveNewTheme(self,themeName,theme):
1080 """
1081 save a newly created theme.
1082 themeName - string, the name of the new theme
1083 theme - dictionary containing the new theme
1084 """
1085 if not idleConf.userCfg['highlight'].has_section(themeName):
1086 idleConf.userCfg['highlight'].add_section(themeName)
1087 for element in theme.keys():
1088 value=theme[element]
1089 idleConf.userCfg['highlight'].SetOption(themeName,element,value)
1090
1091 def SetUserValue(self,configType,section,item,value):
1092 if idleConf.defaultCfg[configType].has_option(section,item):
1093 if idleConf.defaultCfg[configType].Get(section,item)==value:
1094 #the setting equals a default setting, remove it from user cfg
1095 return idleConf.userCfg[configType].RemoveOption(section,item)
1096 #if we got here set the option
1097 return idleConf.userCfg[configType].SetOption(section,item,value)
1098
1099 def SaveAllChangedConfigs(self):
1100 "Save configuration changes to the user config file."
1101 idleConf.userCfg['main'].Save()
1102 for configType in self.changedItems.keys():
1103 cfgTypeHasChanges = False
1104 for section in self.changedItems[configType].keys():
1105 if section == 'HelpFiles':
1106 #this section gets completely replaced
1107 idleConf.userCfg['main'].remove_section('HelpFiles')
1108 cfgTypeHasChanges = True
1109 for item in self.changedItems[configType][section].keys():
1110 value = self.changedItems[configType][section][item]
1111 if self.SetUserValue(configType,section,item,value):
1112 cfgTypeHasChanges = True
1113 if cfgTypeHasChanges:
1114 idleConf.userCfg[configType].Save()
1115 for configType in ['keys', 'highlight']:
1116 # save these even if unchanged!
1117 idleConf.userCfg[configType].Save()
1118 self.ResetChangedItems() #clear the changed items dict
1119
1120 def DeactivateCurrentConfig(self):
1121 #Before a config is saved, some cleanup of current
1122 #config must be done - remove the previous keybindings
1123 winInstances=self.parent.instance_dict.keys()
1124 for instance in winInstances:
1125 instance.RemoveKeybindings()
1126
1127 def ActivateConfigChanges(self):
1128 "Dynamically apply configuration changes"
1129 winInstances=self.parent.instance_dict.keys()
1130 for instance in winInstances:
1131 instance.ResetColorizer()
1132 instance.ResetFont()
1133 instance.set_notabs_indentwidth()
1134 instance.ApplyKeybindings()
1135 instance.reset_help_menu_entries()
1136
1137 def Cancel(self):
1138 self.destroy()
1139
1140 def Ok(self):
1141 self.Apply()
1142 self.destroy()
1143
1144 def Apply(self):
1145 self.DeactivateCurrentConfig()
1146 self.SaveAllChangedConfigs()
1147 self.ActivateConfigChanges()
1148
1149 def Help(self):
1150 pass
1151
1152if __name__ == '__main__':
1153 #test the dialog
1154 root=Tk()
1155 Button(root,text='Dialog',
1156 command=lambda:ConfigDialog(root,'Settings')).pack()
1157 root.instance_dict={}
1158 root.mainloop()
Note: See TracBrowser for help on using the repository browser.