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