1 """IDLE Configuration Dialog: support user customization of IDLE by GUI
3 Customize font faces, sizes, and colorization attributes. Set indentation
4 defaults. Customize keybindings. Colorization and keybindings can be
5 saved as user defined sets. Select startup options including shell/editor
6 and default window size. Define additional help sources.
8 Note that tab width in IDLE is currently fixed at eight due to Tk issues.
9 Refer to comment in EditorWindow autoindent code for details.
13 import tkMessageBox
, tkColorChooser
, tkFont
16 from configHandler
import idleConf
17 from dynOptionMenuWidget
import DynOptionMenu
18 from tabpage
import TabPageSet
19 from keybindingDialog
import GetKeysDialog
20 from configSectionNameDialog
import GetCfgSectionNameDialog
21 from configHelpSourceEdit
import GetHelpSourceDialog
23 class ConfigDialog(Toplevel
):
25 configuration dialog for idle
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 it's 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 Comments':('comment','03'),
39 'Python Strings':('string','04'),
40 'Selected Text':('hilite','05'),
41 'Found Text':('hit','06'),
42 'Cursor':('cursor','07'),
43 'Error Text':('error','08'),
44 'Shell Normal Text':('console','09'),
45 'Shell Stdout Text':('stdout','10'),
46 'Shell Stderr Text':('stderr','11')}
47 self
.ResetChangedItems() #load initial values in changed items dict
49 self
.resizable(height
=FALSE
,width
=FALSE
)
50 self
.transient(parent
)
52 self
.protocol("WM_DELETE_WINDOW", self
.Cancel
)
54 self
.tabPages
.focus_set()
55 #key bindings for this dialog
56 #self.bind('<Escape>',self.Cancel) #dismiss dialog, no save
57 #self.bind('<Alt-a>',self.Apply) #apply changes, save
58 #self.bind('<F1>',self.Help) #context help
60 self
.AttachVarCallbacks() #avoid callbacks during LoadConfigs
63 def CreateWidgets(self
):
64 self
.tabPages
= TabPageSet(self
,
65 pageNames
=['Fonts/Tabs','Highlighting','Keys','General'])
66 self
.tabPages
.ChangePage()#activates default (first) page
67 frameActionButtons
= Frame(self
)
69 self
.buttonHelp
= Button(frameActionButtons
,text
='Help',
70 command
=self
.Help
,takefocus
=FALSE
)
71 self
.buttonOk
= Button(frameActionButtons
,text
='Ok',
72 command
=self
.Ok
,takefocus
=FALSE
)
73 self
.buttonApply
= Button(frameActionButtons
,text
='Apply',
74 command
=self
.Apply
,takefocus
=FALSE
)
75 self
.buttonCancel
= Button(frameActionButtons
,text
='Cancel',
76 command
=self
.Cancel
,takefocus
=FALSE
)
77 self
.CreatePageFontTab()
78 self
.CreatePageHighlight()
80 self
.CreatePageGeneral()
81 self
.buttonHelp
.pack(side
=RIGHT
,padx
=5,pady
=5)
82 self
.buttonOk
.pack(side
=LEFT
,padx
=5,pady
=5)
83 self
.buttonApply
.pack(side
=LEFT
,padx
=5,pady
=5)
84 self
.buttonCancel
.pack(side
=LEFT
,padx
=5,pady
=5)
85 frameActionButtons
.pack(side
=BOTTOM
)
86 self
.tabPages
.pack(side
=TOP
,expand
=TRUE
,fill
=BOTH
)
88 def CreatePageFontTab(self
):
90 self
.fontSize
=StringVar(self
)
91 self
.fontBold
=BooleanVar(self
)
92 self
.fontName
=StringVar(self
)
93 self
.spaceNum
=IntVar(self
)
94 #self.tabCols=IntVar(self)
95 self
.indentBySpaces
=BooleanVar(self
)
96 self
.editFont
=tkFont
.Font(self
,('courier',10,'normal'))
99 frame
=self
.tabPages
.pages
['Fonts/Tabs']['page']
101 frameFont
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
102 frameIndent
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
104 labelFontTitle
=Label(frameFont
,text
='Set Base Editor Font')
105 frameFontName
=Frame(frameFont
)
106 frameFontParam
=Frame(frameFont
)
107 labelFontNameTitle
=Label(frameFontName
,justify
=LEFT
,
109 self
.listFontName
=Listbox(frameFontName
,height
=5,takefocus
=FALSE
,
110 exportselection
=FALSE
)
111 self
.listFontName
.bind('<ButtonRelease-1>',self
.OnListFontButtonRelease
)
112 scrollFont
=Scrollbar(frameFontName
)
113 scrollFont
.config(command
=self
.listFontName
.yview
)
114 self
.listFontName
.config(yscrollcommand
=scrollFont
.set)
115 labelFontSizeTitle
=Label(frameFontParam
,text
='Size :')
116 self
.optMenuFontSize
=DynOptionMenu(frameFontParam
,self
.fontSize
,None,
117 command
=self
.SetFontSample
)
118 checkFontBold
=Checkbutton(frameFontParam
,variable
=self
.fontBold
,
119 onvalue
=1,offvalue
=0,text
='Bold',command
=self
.SetFontSample
)
120 frameFontSample
=Frame(frameFont
,relief
=SOLID
,borderwidth
=1)
121 self
.labelFontSample
=Label(frameFontSample
,
122 text
='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]',
123 justify
=LEFT
,font
=self
.editFont
)
125 labelIndentTitle
=Label(frameIndent
,text
='Set Indentation Defaults')
126 frameIndentType
=Frame(frameIndent
)
127 frameIndentSize
=Frame(frameIndent
)
128 labelIndentTypeTitle
=Label(frameIndentType
,
129 text
='Choose indentation type :')
130 radioUseSpaces
=Radiobutton(frameIndentType
,variable
=self
.indentBySpaces
,
131 value
=1,text
='Tab key inserts spaces')
132 radioUseTabs
=Radiobutton(frameIndentType
,variable
=self
.indentBySpaces
,
133 value
=0,text
='Tab key inserts tabs')
134 labelIndentSizeTitle
=Label(frameIndentSize
,
135 text
='Choose indentation size :')
136 labelSpaceNumTitle
=Label(frameIndentSize
,justify
=LEFT
,
138 self
.scaleSpaceNum
=Scale(frameIndentSize
,variable
=self
.spaceNum
,
139 orient
='horizontal',tickinterval
=2,from_
=2,to
=16)
140 #labeltabColsTitle=Label(frameIndentSize,justify=LEFT,
141 # text='when tab key inserts tabs,\ncolumns per tab')
142 #self.scaleTabCols=Scale(frameIndentSize,variable=self.tabCols,
143 # orient='horizontal',tickinterval=2,from_=2,to=8)
146 frameFont
.pack(side
=LEFT
,padx
=5,pady
=10,expand
=TRUE
,fill
=BOTH
)
147 frameIndent
.pack(side
=LEFT
,padx
=5,pady
=10,fill
=Y
)
149 labelFontTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
150 frameFontName
.pack(side
=TOP
,padx
=5,pady
=5,fill
=X
)
151 frameFontParam
.pack(side
=TOP
,padx
=5,pady
=5,fill
=X
)
152 labelFontNameTitle
.pack(side
=TOP
,anchor
=W
)
153 self
.listFontName
.pack(side
=LEFT
,expand
=TRUE
,fill
=X
)
154 scrollFont
.pack(side
=LEFT
,fill
=Y
)
155 labelFontSizeTitle
.pack(side
=LEFT
,anchor
=W
)
156 self
.optMenuFontSize
.pack(side
=LEFT
,anchor
=W
)
157 checkFontBold
.pack(side
=LEFT
,anchor
=W
,padx
=20)
158 frameFontSample
.pack(side
=TOP
,padx
=5,pady
=5,expand
=TRUE
,fill
=BOTH
)
159 self
.labelFontSample
.pack(expand
=TRUE
,fill
=BOTH
)
161 labelIndentTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
162 frameIndentType
.pack(side
=TOP
,padx
=5,fill
=X
)
163 frameIndentSize
.pack(side
=TOP
,padx
=5,pady
=5,fill
=BOTH
)
164 labelIndentTypeTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
165 radioUseSpaces
.pack(side
=TOP
,anchor
=W
,padx
=5)
166 radioUseTabs
.pack(side
=TOP
,anchor
=W
,padx
=5)
167 labelIndentSizeTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
168 labelSpaceNumTitle
.pack(side
=TOP
,anchor
=W
,padx
=5)
169 self
.scaleSpaceNum
.pack(side
=TOP
,padx
=5,fill
=X
)
170 #labeltabColsTitle.pack(side=TOP,anchor=W,padx=5)
171 #self.scaleTabCols.pack(side=TOP,padx=5,fill=X)
174 def CreatePageHighlight(self
):
175 self
.builtinTheme
=StringVar(self
)
176 self
.customTheme
=StringVar(self
)
177 self
.fgHilite
=BooleanVar(self
)
178 self
.colour
=StringVar(self
)
179 self
.fontName
=StringVar(self
)
180 self
.themeIsBuiltin
=BooleanVar(self
)
181 self
.highlightTarget
=StringVar(self
)
184 frame
=self
.tabPages
.pages
['Highlighting']['page']
186 frameCustom
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
187 frameTheme
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
189 self
.textHighlightSample
=Text(frameCustom
,relief
=SOLID
,borderwidth
=1,
190 font
=('courier',12,''),cursor
='hand2',width
=21,height
=10,
191 takefocus
=FALSE
,highlightthickness
=0,wrap
=NONE
)
192 text
=self
.textHighlightSample
193 text
.bind('<Double-Button-1>',lambda e
: 'break')
194 text
.bind('<B1-Motion>',lambda e
: 'break')
195 textAndTags
=(('#you can click here','comment'),('\n','normal'),
196 ('#to choose items','comment'),('\n','normal'),('def','keyword'),
197 (' ','normal'),('func','definition'),('(param):','normal'),
198 ('\n ','normal'),('"""string"""','string'),('\n var0 = ','normal'),
199 ("'string'",'string'),('\n var1 = ','normal'),("'selected'",'hilite'),
200 ('\n var2 = ','normal'),("'found'",'hit'),('\n\n','normal'),
201 (' error ','error'),(' ','normal'),('cursor |','cursor'),
202 ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'),
203 (' ','normal'),('stderr','stderr'),('\n','normal'))
204 for txTa
in textAndTags
:
205 text
.insert(END
,txTa
[0],txTa
[1])
206 for element
in self
.themeElements
.keys():
207 text
.tag_bind(self
.themeElements
[element
][0],'<ButtonPress-1>',
208 lambda event
,elem
=element
: event
.widget
.winfo_toplevel()
209 .highlightTarget
.set(elem
))
210 text
.config(state
=DISABLED
)
211 self
.frameColourSet
=Frame(frameCustom
,relief
=SOLID
,borderwidth
=1)
212 frameFgBg
=Frame(frameCustom
)
213 labelCustomTitle
=Label(frameCustom
,text
='Set Custom Highlighting')
214 buttonSetColour
=Button(self
.frameColourSet
,text
='Choose Colour for :',
215 command
=self
.GetColour
,highlightthickness
=0)
216 self
.optMenuHighlightTarget
=DynOptionMenu(self
.frameColourSet
,
217 self
.highlightTarget
,None,highlightthickness
=0)#,command=self.SetHighlightTargetBinding
218 self
.radioFg
=Radiobutton(frameFgBg
,variable
=self
.fgHilite
,
219 value
=1,text
='Foreground',command
=self
.SetColourSampleBinding
)
220 self
.radioBg
=Radiobutton(frameFgBg
,variable
=self
.fgHilite
,
221 value
=0,text
='Background',command
=self
.SetColourSampleBinding
)
223 buttonSaveCustomTheme
=Button(frameCustom
,
224 text
='Save as New Custom Theme',command
=self
.SaveAsNewTheme
)
226 labelThemeTitle
=Label(frameTheme
,text
='Select a Highlighting Theme')
227 labelTypeTitle
=Label(frameTheme
,text
='Select : ')
228 self
.radioThemeBuiltin
=Radiobutton(frameTheme
,variable
=self
.themeIsBuiltin
,
229 value
=1,command
=self
.SetThemeType
,text
='a Built-in Theme')
230 self
.radioThemeCustom
=Radiobutton(frameTheme
,variable
=self
.themeIsBuiltin
,
231 value
=0,command
=self
.SetThemeType
,text
='a Custom Theme')
232 self
.optMenuThemeBuiltin
=DynOptionMenu(frameTheme
,
233 self
.builtinTheme
,None,command
=None)
234 self
.optMenuThemeCustom
=DynOptionMenu(frameTheme
,
235 self
.customTheme
,None,command
=None)
236 self
.buttonDeleteCustomTheme
=Button(frameTheme
,text
='Delete Custom Theme',
237 command
=self
.DeleteCustomTheme
)
240 frameCustom
.pack(side
=LEFT
,padx
=5,pady
=10,expand
=TRUE
,fill
=BOTH
)
241 frameTheme
.pack(side
=LEFT
,padx
=5,pady
=10,fill
=Y
)
243 labelCustomTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
244 self
.frameColourSet
.pack(side
=TOP
,padx
=5,pady
=5,expand
=TRUE
,fill
=X
)
245 frameFgBg
.pack(side
=TOP
,padx
=5,pady
=0)
246 self
.textHighlightSample
.pack(side
=TOP
,padx
=5,pady
=5,expand
=TRUE
,
248 buttonSetColour
.pack(side
=TOP
,expand
=TRUE
,fill
=X
,padx
=8,pady
=4)
249 self
.optMenuHighlightTarget
.pack(side
=TOP
,expand
=TRUE
,fill
=X
,padx
=8,pady
=3)
250 self
.radioFg
.pack(side
=LEFT
,anchor
=E
)
251 self
.radioBg
.pack(side
=RIGHT
,anchor
=W
)
252 buttonSaveCustomTheme
.pack(side
=BOTTOM
,fill
=X
,padx
=5,pady
=5)
254 labelThemeTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
255 labelTypeTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
256 self
.radioThemeBuiltin
.pack(side
=TOP
,anchor
=W
,padx
=5)
257 self
.radioThemeCustom
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=2)
258 self
.optMenuThemeBuiltin
.pack(side
=TOP
,fill
=X
,padx
=5,pady
=5)
259 self
.optMenuThemeCustom
.pack(side
=TOP
,fill
=X
,anchor
=W
,padx
=5,pady
=5)
260 self
.buttonDeleteCustomTheme
.pack(side
=TOP
,fill
=X
,padx
=5,pady
=5)
263 def CreatePageKeys(self
):
265 self
.bindingTarget
=StringVar(self
)
266 self
.builtinKeys
=StringVar(self
)
267 self
.customKeys
=StringVar(self
)
268 self
.keysAreBuiltin
=BooleanVar(self
)
269 self
.keyBinding
=StringVar(self
)
272 frame
=self
.tabPages
.pages
['Keys']['page']
274 frameCustom
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
275 frameKeySets
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
277 frameTarget
=Frame(frameCustom
)
278 labelCustomTitle
=Label(frameCustom
,text
='Set Custom Key Bindings')
279 labelTargetTitle
=Label(frameTarget
,text
='Action - Key(s)')
280 scrollTargetY
=Scrollbar(frameTarget
)
281 scrollTargetX
=Scrollbar(frameTarget
,orient
=HORIZONTAL
)
282 self
.listBindings
=Listbox(frameTarget
,takefocus
=FALSE
,
283 exportselection
=FALSE
)
284 self
.listBindings
.bind('<ButtonRelease-1>',self
.KeyBindingSelected
)
285 scrollTargetY
.config(command
=self
.listBindings
.yview
)
286 scrollTargetX
.config(command
=self
.listBindings
.xview
)
287 self
.listBindings
.config(yscrollcommand
=scrollTargetY
.set)
288 self
.listBindings
.config(xscrollcommand
=scrollTargetX
.set)
289 self
.buttonNewKeys
=Button(frameCustom
,text
='Get New Keys for Selection',
290 command
=self
.GetNewKeys
,state
=DISABLED
)
291 buttonSaveCustomKeys
=Button(frameCustom
,
292 text
='Save as New Custom Key Set',command
=self
.SaveAsNewKeySet
)
294 labelKeysTitle
=Label(frameKeySets
,text
='Select a Key Set')
295 labelTypeTitle
=Label(frameKeySets
,text
='Select : ')
296 self
.radioKeysBuiltin
=Radiobutton(frameKeySets
,variable
=self
.keysAreBuiltin
,
297 value
=1,command
=self
.SetKeysType
,text
='a Built-in Key Set')
298 self
.radioKeysCustom
=Radiobutton(frameKeySets
,variable
=self
.keysAreBuiltin
,
299 value
=0,command
=self
.SetKeysType
,text
='a Custom Key Set')
300 self
.optMenuKeysBuiltin
=DynOptionMenu(frameKeySets
,
301 self
.builtinKeys
,None,command
=None)
302 self
.optMenuKeysCustom
=DynOptionMenu(frameKeySets
,
303 self
.customKeys
,None,command
=None)
304 self
.buttonDeleteCustomKeys
=Button(frameKeySets
,text
='Delete Custom Key Set',
305 command
=self
.DeleteCustomKeys
)
308 frameCustom
.pack(side
=LEFT
,padx
=5,pady
=5,expand
=TRUE
,fill
=BOTH
)
309 frameKeySets
.pack(side
=LEFT
,padx
=5,pady
=5,fill
=Y
)
311 labelCustomTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
312 buttonSaveCustomKeys
.pack(side
=BOTTOM
,fill
=X
,padx
=5,pady
=5)
313 self
.buttonNewKeys
.pack(side
=BOTTOM
,fill
=X
,padx
=5,pady
=5)
314 frameTarget
.pack(side
=LEFT
,padx
=5,pady
=5,expand
=TRUE
,fill
=BOTH
)
316 frameTarget
.columnconfigure(0,weight
=1)
317 frameTarget
.rowconfigure(1,weight
=1)
318 labelTargetTitle
.grid(row
=0,column
=0,columnspan
=2,sticky
=W
)
319 self
.listBindings
.grid(row
=1,column
=0,sticky
=NSEW
)
320 scrollTargetY
.grid(row
=1,column
=1,sticky
=NS
)
321 scrollTargetX
.grid(row
=2,column
=0,sticky
=EW
)
323 labelKeysTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
324 labelTypeTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
325 self
.radioKeysBuiltin
.pack(side
=TOP
,anchor
=W
,padx
=5)
326 self
.radioKeysCustom
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=2)
327 self
.optMenuKeysBuiltin
.pack(side
=TOP
,fill
=X
,padx
=5,pady
=5)
328 self
.optMenuKeysCustom
.pack(side
=TOP
,fill
=X
,anchor
=W
,padx
=5,pady
=5)
329 self
.buttonDeleteCustomKeys
.pack(side
=TOP
,fill
=X
,padx
=5,pady
=5)
332 def CreatePageGeneral(self
):
334 self
.winWidth
=StringVar(self
)
335 self
.winHeight
=StringVar(self
)
336 self
.startupEdit
=IntVar(self
)
337 self
.autoSave
=IntVar(self
)
338 self
.encoding
=StringVar(self
)
339 self
.userHelpBrowser
=BooleanVar(self
)
340 self
.helpBrowser
=StringVar(self
)
343 frame
=self
.tabPages
.pages
['General']['page']
345 frameRun
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
346 frameSave
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
347 frameWinSize
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
348 frameEncoding
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
349 frameHelp
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
351 labelRunTitle
=Label(frameRun
,text
='Startup Preferences')
352 labelRunChoiceTitle
=Label(frameRun
,text
='At Startup')
353 radioStartupEdit
=Radiobutton(frameRun
,variable
=self
.startupEdit
,
354 value
=1,command
=self
.SetKeysType
,text
="Open Edit Window")
355 radioStartupShell
=Radiobutton(frameRun
,variable
=self
.startupEdit
,
356 value
=0,command
=self
.SetKeysType
,text
='Open Shell Window')
358 labelSaveTitle
=Label(frameSave
,text
='Autosave Preference')
359 labelRunSaveTitle
=Label(frameSave
,text
='At Start of Run (F5) ')
360 radioSaveAsk
=Radiobutton(frameSave
,variable
=self
.autoSave
,
361 value
=0,command
=self
.SetKeysType
,text
="Prompt to Save")
362 radioSaveAuto
=Radiobutton(frameSave
,variable
=self
.autoSave
,
363 value
=1,command
=self
.SetKeysType
,text
='No Prompt')
365 labelWinSizeTitle
=Label(frameWinSize
,text
='Initial Window Size'+
367 labelWinWidthTitle
=Label(frameWinSize
,text
='Width')
368 entryWinWidth
=Entry(frameWinSize
,textvariable
=self
.winWidth
,
370 labelWinHeightTitle
=Label(frameWinSize
,text
='Height')
371 entryWinHeight
=Entry(frameWinSize
,textvariable
=self
.winHeight
,
374 labelEncodingTitle
=Label(frameEncoding
,text
="Default Source Encoding")
375 radioEncLocale
=Radiobutton(frameEncoding
,variable
=self
.encoding
,
376 value
="locale",text
="Locale-defined")
377 radioEncUTF8
=Radiobutton(frameEncoding
,variable
=self
.encoding
,
378 value
="utf-8",text
="UTF-8")
379 radioEncNone
=Radiobutton(frameEncoding
,variable
=self
.encoding
,
380 value
="none",text
="None")
382 ##labelHelpTitle=Label(frameHelp,text='Help Options')
383 frameHelpList
=Frame(frameHelp
)
384 frameHelpListButtons
=Frame(frameHelpList
)
385 labelHelpListTitle
=Label(frameHelpList
,text
='Additional Help Sources:')
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 # the following is better handled by the BROWSER environment
399 # variable under unix/linux
400 #checkHelpBrowser=Checkbutton(frameHelp,variable=self.userHelpBrowser,
401 # onvalue=1,offvalue=0,text='user specified (html) help browser:',
402 # command=self.OnCheckUserHelpBrowser)
403 #self.entryHelpBrowser=Entry(frameHelp,textvariable=self.helpBrowser,
407 frameRun
.pack(side
=TOP
,padx
=5,pady
=5,fill
=X
)
408 frameSave
.pack(side
=TOP
,padx
=5,pady
=5,fill
=X
)
409 frameWinSize
.pack(side
=TOP
,padx
=5,pady
=5,fill
=X
)
410 frameEncoding
.pack(side
=TOP
,padx
=5,pady
=5,fill
=X
)
411 frameHelp
.pack(side
=TOP
,padx
=5,pady
=5,expand
=TRUE
,fill
=BOTH
)
413 labelRunTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
414 labelRunChoiceTitle
.pack(side
=LEFT
,anchor
=W
,padx
=5,pady
=5)
415 radioStartupShell
.pack(side
=RIGHT
,anchor
=W
,padx
=5,pady
=5)
416 radioStartupEdit
.pack(side
=RIGHT
,anchor
=W
,padx
=5,pady
=5)
418 labelSaveTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
419 labelRunSaveTitle
.pack(side
=LEFT
,anchor
=W
,padx
=5,pady
=5)
420 radioSaveAuto
.pack(side
=RIGHT
,anchor
=W
,padx
=5,pady
=5)
421 radioSaveAsk
.pack(side
=RIGHT
,anchor
=W
,padx
=5,pady
=5)
423 labelWinSizeTitle
.pack(side
=LEFT
,anchor
=W
,padx
=5,pady
=5)
424 entryWinHeight
.pack(side
=RIGHT
,anchor
=E
,padx
=10,pady
=5)
425 labelWinHeightTitle
.pack(side
=RIGHT
,anchor
=E
,pady
=5)
426 entryWinWidth
.pack(side
=RIGHT
,anchor
=E
,padx
=10,pady
=5)
427 labelWinWidthTitle
.pack(side
=RIGHT
,anchor
=E
,pady
=5)
429 labelEncodingTitle
.pack(side
=LEFT
,anchor
=W
,padx
=5,pady
=5)
430 radioEncNone
.pack(side
=RIGHT
,anchor
=E
,pady
=5)
431 radioEncUTF8
.pack(side
=RIGHT
,anchor
=E
,pady
=5)
432 radioEncLocale
.pack(side
=RIGHT
,anchor
=E
,pady
=5)
434 ##labelHelpTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
435 frameHelpListButtons
.pack(side
=RIGHT
,padx
=5,pady
=5,fill
=Y
)
436 frameHelpList
.pack(side
=TOP
,padx
=5,pady
=5,expand
=TRUE
,fill
=BOTH
)
437 labelHelpListTitle
.pack(side
=TOP
,anchor
=W
)
438 scrollHelpList
.pack(side
=RIGHT
,anchor
=W
,fill
=Y
)
439 self
.listHelp
.pack(side
=LEFT
,anchor
=E
,expand
=TRUE
,fill
=BOTH
)
440 self
.buttonHelpListEdit
.pack(side
=TOP
,anchor
=W
,pady
=5)
441 self
.buttonHelpListAdd
.pack(side
=TOP
,anchor
=W
)
442 self
.buttonHelpListRemove
.pack(side
=TOP
,anchor
=W
,pady
=5)
443 #checkHelpBrowser.pack(side=TOP,anchor=W,padx=5)
444 #self.entryHelpBrowser.pack(side=TOP,anchor=W,padx=5,pady=5)
447 def AttachVarCallbacks(self
):
448 self
.fontSize
.trace_variable('w',self
.VarChanged_fontSize
)
449 self
.fontName
.trace_variable('w',self
.VarChanged_fontName
)
450 self
.fontBold
.trace_variable('w',self
.VarChanged_fontBold
)
451 self
.spaceNum
.trace_variable('w',self
.VarChanged_spaceNum
)
452 #self.tabCols.trace_variable('w',self.VarChanged_tabCols)
453 self
.indentBySpaces
.trace_variable('w',self
.VarChanged_indentBySpaces
)
454 self
.colour
.trace_variable('w',self
.VarChanged_colour
)
455 self
.builtinTheme
.trace_variable('w',self
.VarChanged_builtinTheme
)
456 self
.customTheme
.trace_variable('w',self
.VarChanged_customTheme
)
457 self
.themeIsBuiltin
.trace_variable('w',self
.VarChanged_themeIsBuiltin
)
458 self
.highlightTarget
.trace_variable('w',self
.VarChanged_highlightTarget
)
459 self
.keyBinding
.trace_variable('w',self
.VarChanged_keyBinding
)
460 self
.builtinKeys
.trace_variable('w',self
.VarChanged_builtinKeys
)
461 self
.customKeys
.trace_variable('w',self
.VarChanged_customKeys
)
462 self
.keysAreBuiltin
.trace_variable('w',self
.VarChanged_keysAreBuiltin
)
463 self
.winWidth
.trace_variable('w',self
.VarChanged_winWidth
)
464 self
.winHeight
.trace_variable('w',self
.VarChanged_winHeight
)
465 self
.startupEdit
.trace_variable('w',self
.VarChanged_startupEdit
)
466 self
.autoSave
.trace_variable('w',self
.VarChanged_autoSave
)
467 self
.encoding
.trace_variable('w',self
.VarChanged_encoding
)
469 def VarChanged_fontSize(self
,*params
):
470 value
=self
.fontSize
.get()
471 self
.AddChangedItem('main','EditorWindow','font-size',value
)
473 def VarChanged_fontName(self
,*params
):
474 value
=self
.fontName
.get()
475 self
.AddChangedItem('main','EditorWindow','font',value
)
477 def VarChanged_fontBold(self
,*params
):
478 value
=self
.fontBold
.get()
479 self
.AddChangedItem('main','EditorWindow','font-bold',value
)
481 def VarChanged_indentBySpaces(self
,*params
):
482 value
=self
.indentBySpaces
.get()
483 self
.AddChangedItem('main','Indent','use-spaces',value
)
485 def VarChanged_spaceNum(self
,*params
):
486 value
=self
.spaceNum
.get()
487 self
.AddChangedItem('main','Indent','num-spaces',value
)
489 #def VarChanged_tabCols(self,*params):
490 # value=self.tabCols.get()
491 # self.AddChangedItem('main','Indent','tab-cols',value)
493 def VarChanged_colour(self
,*params
):
494 self
.OnNewColourSet()
496 def VarChanged_builtinTheme(self
,*params
):
497 value
=self
.builtinTheme
.get()
498 self
.AddChangedItem('main','Theme','name',value
)
499 self
.PaintThemeSample()
501 def VarChanged_customTheme(self
,*params
):
502 value
=self
.customTheme
.get()
503 if value
!= '- no custom themes -':
504 self
.AddChangedItem('main','Theme','name',value
)
505 self
.PaintThemeSample()
507 def VarChanged_themeIsBuiltin(self
,*params
):
508 value
=self
.themeIsBuiltin
.get()
509 self
.AddChangedItem('main','Theme','default',value
)
511 self
.VarChanged_builtinTheme()
513 self
.VarChanged_customTheme()
515 def VarChanged_highlightTarget(self
,*params
):
516 self
.SetHighlightTarget()
518 def VarChanged_keyBinding(self
,*params
):
519 value
=self
.keyBinding
.get()
520 keySet
=self
.customKeys
.get()
521 event
=self
.listBindings
.get(ANCHOR
).split()[0]
522 if idleConf
.IsCoreBinding(event
):
523 #this is a core keybinding
524 self
.AddChangedItem('keys',keySet
,event
,value
)
525 else: #this is an extension key binding
526 extName
=idleConf
.GetExtnNameForEvent(event
)
527 extKeybindSection
=extName
+'_cfgBindings'
528 self
.AddChangedItem('extensions',extKeybindSection
,event
,value
)
530 def VarChanged_builtinKeys(self
,*params
):
531 value
=self
.builtinKeys
.get()
532 self
.AddChangedItem('main','Keys','name',value
)
533 self
.LoadKeysList(value
)
535 def VarChanged_customKeys(self
,*params
):
536 value
=self
.customKeys
.get()
537 if value
!= '- no custom keys -':
538 self
.AddChangedItem('main','Keys','name',value
)
539 self
.LoadKeysList(value
)
541 def VarChanged_keysAreBuiltin(self
,*params
):
542 value
=self
.keysAreBuiltin
.get()
543 self
.AddChangedItem('main','Keys','default',value
)
545 self
.VarChanged_builtinKeys()
547 self
.VarChanged_customKeys()
549 def VarChanged_winWidth(self
,*params
):
550 value
=self
.winWidth
.get()
551 self
.AddChangedItem('main','EditorWindow','width',value
)
553 def VarChanged_winHeight(self
,*params
):
554 value
=self
.winHeight
.get()
555 self
.AddChangedItem('main','EditorWindow','height',value
)
557 def VarChanged_startupEdit(self
,*params
):
558 value
=self
.startupEdit
.get()
559 self
.AddChangedItem('main','General','editor-on-startup',value
)
561 def VarChanged_autoSave(self
,*params
):
562 value
=self
.autoSave
.get()
563 self
.AddChangedItem('main','General','autosave',value
)
565 def VarChanged_encoding(self
,*params
):
566 value
=self
.encoding
.get()
567 self
.AddChangedItem('main','EditorWindow','encoding',value
)
569 def ResetChangedItems(self
):
570 #When any config item is changed in this dialog, an entry
571 #should be made in the relevant section (config type) of this
572 #dictionary. The key should be the config file section name and the
573 #value a dictionary, whose key:value pairs are item=value pairs for
574 #that config file section.
575 self
.changedItems
={'main':{},'highlight':{},'keys':{},'extensions':{}}
577 def AddChangedItem(self
,type,section
,item
,value
):
578 value
=str(value
) #make sure we use a string
579 if not self
.changedItems
[type].has_key(section
):
580 self
.changedItems
[type][section
]={}
581 self
.changedItems
[type][section
][item
]=value
583 def GetDefaultItems(self
):
584 dItems
={'main':{},'highlight':{},'keys':{},'extensions':{}}
585 for configType
in dItems
.keys():
586 sections
=idleConf
.GetSectionList('default',configType
)
587 for section
in sections
:
588 dItems
[configType
][section
]={}
589 options
=idleConf
.defaultCfg
[configType
].GetOptionList(section
)
590 for option
in options
:
591 dItems
[configType
][section
][option
]=(
592 idleConf
.defaultCfg
[configType
].Get(section
,option
))
595 def SetThemeType(self
):
596 if self
.themeIsBuiltin
.get():
597 self
.optMenuThemeBuiltin
.config(state
=NORMAL
)
598 self
.optMenuThemeCustom
.config(state
=DISABLED
)
599 self
.buttonDeleteCustomTheme
.config(state
=DISABLED
)
601 self
.optMenuThemeBuiltin
.config(state
=DISABLED
)
602 self
.radioThemeCustom
.config(state
=NORMAL
)
603 self
.optMenuThemeCustom
.config(state
=NORMAL
)
604 self
.buttonDeleteCustomTheme
.config(state
=NORMAL
)
606 def SetKeysType(self
):
607 if self
.keysAreBuiltin
.get():
608 self
.optMenuKeysBuiltin
.config(state
=NORMAL
)
609 self
.optMenuKeysCustom
.config(state
=DISABLED
)
610 self
.buttonDeleteCustomKeys
.config(state
=DISABLED
)
612 self
.optMenuKeysBuiltin
.config(state
=DISABLED
)
613 self
.radioKeysCustom
.config(state
=NORMAL
)
614 self
.optMenuKeysCustom
.config(state
=NORMAL
)
615 self
.buttonDeleteCustomKeys
.config(state
=NORMAL
)
617 def GetNewKeys(self
):
618 listIndex
=self
.listBindings
.index(ANCHOR
)
619 binding
=self
.listBindings
.get(listIndex
)
620 bindName
=binding
.split()[0] #first part, up to first space
621 if self
.keysAreBuiltin
.get():
622 currentKeySetName
=self
.builtinKeys
.get()
624 currentKeySetName
=self
.customKeys
.get()
625 currentBindings
=idleConf
.GetCurrentKeySet()
626 if currentKeySetName
in self
.changedItems
['keys'].keys(): #unsaved changes
627 keySetChanges
=self
.changedItems
['keys'][currentKeySetName
]
628 for event
in keySetChanges
.keys():
629 currentBindings
[event
]=keySetChanges
[event
].split()
630 currentKeySequences
=currentBindings
.values()
631 newKeys
=GetKeysDialog(self
,'Get New Keys',bindName
,
632 currentKeySequences
).result
633 if newKeys
: #new keys were specified
634 if self
.keysAreBuiltin
.get(): #current key set is a built-in
635 message
=('Your changes will be saved as a new Custom Key Set. '+
636 'Enter a name for your new Custom Key Set below.')
637 newKeySet
=self
.GetNewKeysName(message
)
638 if not newKeySet
: #user cancelled custom key set creation
639 self
.listBindings
.select_set(listIndex
)
640 self
.listBindings
.select_anchor(listIndex
)
642 else: #create new custom key set based on previously active key set
643 self
.CreateNewKeySet(newKeySet
)
644 self
.listBindings
.delete(listIndex
)
645 self
.listBindings
.insert(listIndex
,bindName
+' - '+newKeys
)
646 self
.listBindings
.select_set(listIndex
)
647 self
.listBindings
.select_anchor(listIndex
)
648 self
.keyBinding
.set(newKeys
)
650 self
.listBindings
.select_set(listIndex
)
651 self
.listBindings
.select_anchor(listIndex
)
653 def GetNewKeysName(self
,message
):
654 usedNames
=(idleConf
.GetSectionList('user','keys')+
655 idleConf
.GetSectionList('default','keys'))
656 newKeySet
=GetCfgSectionNameDialog(self
,'New Custom Key Set',
657 message
,usedNames
).result
660 def SaveAsNewKeySet(self
):
661 newKeysName
=self
.GetNewKeysName('New Key Set Name:')
663 self
.CreateNewKeySet(newKeysName
)
665 def KeyBindingSelected(self
,event
):
666 self
.buttonNewKeys
.config(state
=NORMAL
)
668 def CreateNewKeySet(self
,newKeySetName
):
669 #creates new custom key set based on the previously active key set,
670 #and makes the new key set active
671 if self
.keysAreBuiltin
.get():
672 prevKeySetName
=self
.builtinKeys
.get()
674 prevKeySetName
=self
.customKeys
.get()
675 prevKeys
=idleConf
.GetCoreKeys(prevKeySetName
)
677 for event
in prevKeys
.keys(): #add key set to changed items
678 eventName
=event
[2:-2] #trim off the angle brackets
679 binding
=string
.join(prevKeys
[event
])
680 newKeys
[eventName
]=binding
681 #handle any unsaved changes to prev key set
682 if prevKeySetName
in self
.changedItems
['keys'].keys():
683 keySetChanges
=self
.changedItems
['keys'][prevKeySetName
]
684 for event
in keySetChanges
.keys():
685 newKeys
[event
]=keySetChanges
[event
]
687 self
.SaveNewKeySet(newKeySetName
,newKeys
)
688 #change gui over to the new key set
689 customKeyList
=idleConf
.GetSectionList('user','keys')
691 self
.optMenuKeysCustom
.SetMenu(customKeyList
,newKeySetName
)
692 self
.keysAreBuiltin
.set(0)
695 def LoadKeysList(self
,keySetName
):
698 if self
.listBindings
.curselection():
700 listIndex
=self
.listBindings
.index(ANCHOR
)
701 keySet
=idleConf
.GetKeySet(keySetName
)
702 bindNames
=keySet
.keys()
704 self
.listBindings
.delete(0,END
)
705 for bindName
in bindNames
:
706 key
=string
.join(keySet
[bindName
]) #make key(s) into a string
707 bindName
=bindName
[2:-2] #trim off the angle brackets
708 if keySetName
in self
.changedItems
['keys'].keys():
709 #handle any unsaved changes to this key set
710 if bindName
in self
.changedItems
['keys'][keySetName
].keys():
711 key
=self
.changedItems
['keys'][keySetName
][bindName
]
712 self
.listBindings
.insert(END
, bindName
+' - '+key
)
714 self
.listBindings
.see(listIndex
)
715 self
.listBindings
.select_set(listIndex
)
716 self
.listBindings
.select_anchor(listIndex
)
718 def DeleteCustomKeys(self
):
719 keySetName
=self
.customKeys
.get()
720 if not tkMessageBox
.askyesno('Delete Key Set','Are you sure you wish '+
721 'to delete the key set '+`keySetName`
+' ?',
724 #remove key set from config
725 idleConf
.userCfg
['keys'].remove_section(keySetName
)
726 if self
.changedItems
['keys'].has_key(keySetName
):
727 del(self
.changedItems
['keys'][keySetName
])
729 idleConf
.userCfg
['keys'].Save()
730 #reload user key set list
731 itemList
=idleConf
.GetSectionList('user','keys')
734 self
.radioKeysCustom
.config(state
=DISABLED
)
735 self
.optMenuKeysCustom
.SetMenu(itemList
,'- no custom keys -')
737 self
.optMenuKeysCustom
.SetMenu(itemList
,itemList
[0])
738 #revert to default key set
739 self
.keysAreBuiltin
.set(idleConf
.defaultCfg
['main'].Get('Keys','default'))
740 self
.builtinKeys
.set(idleConf
.defaultCfg
['main'].Get('Keys','name'))
741 #user can't back out of these changes, they must be applied now
745 def DeleteCustomTheme(self
):
746 themeName
=self
.customTheme
.get()
747 if not tkMessageBox
.askyesno('Delete Theme','Are you sure you wish '+
748 'to delete the theme '+`themeName`
+' ?',
751 #remove theme from config
752 idleConf
.userCfg
['highlight'].remove_section(themeName
)
753 if self
.changedItems
['highlight'].has_key(themeName
):
754 del(self
.changedItems
['highlight'][themeName
])
756 idleConf
.userCfg
['highlight'].Save()
757 #reload user theme list
758 itemList
=idleConf
.GetSectionList('user','highlight')
761 self
.radioThemeCustom
.config(state
=DISABLED
)
762 self
.optMenuThemeCustom
.SetMenu(itemList
,'- no custom themes -')
764 self
.optMenuThemeCustom
.SetMenu(itemList
,itemList
[0])
765 #revert to default theme
766 self
.themeIsBuiltin
.set(idleConf
.defaultCfg
['main'].Get('Theme','default'))
767 self
.builtinTheme
.set(idleConf
.defaultCfg
['main'].Get('Theme','name'))
768 #user can't back out of these changes, they must be applied now
773 target
=self
.highlightTarget
.get()
774 prevColour
=self
.frameColourSet
.cget('bg')
775 rgbTuplet
, colourString
= tkColorChooser
.askcolor(parent
=self
,
776 title
='Pick new colour for : '+target
,initialcolor
=prevColour
)
777 if colourString
and (colourString
!=prevColour
):
778 #user didn't cancel, and they chose a new colour
779 if self
.themeIsBuiltin
.get(): #current theme is a built-in
780 message
=('Your changes will be saved as a new Custom Theme. '+
781 'Enter a name for your new Custom Theme below.')
782 newTheme
=self
.GetNewThemeName(message
)
783 if not newTheme
: #user cancelled custom theme creation
785 else: #create new custom theme based on previously active theme
786 self
.CreateNewTheme(newTheme
)
787 self
.colour
.set(colourString
)
788 else: #current theme is user defined
789 self
.colour
.set(colourString
)
791 def OnNewColourSet(self
):
792 newColour
=self
.colour
.get()
793 self
.frameColourSet
.config(bg
=newColour
)#set sample
794 if self
.fgHilite
.get(): plane
='foreground'
795 else: plane
='background'
796 sampleElement
=self
.themeElements
[self
.highlightTarget
.get()][0]
797 apply(self
.textHighlightSample
.tag_config
,
798 (sampleElement
,),{plane
:newColour
})
799 theme
=self
.customTheme
.get()
800 themeElement
=sampleElement
+'-'+plane
801 self
.AddChangedItem('highlight',theme
,themeElement
,newColour
)
803 def GetNewThemeName(self
,message
):
804 usedNames
=(idleConf
.GetSectionList('user','highlight')+
805 idleConf
.GetSectionList('default','highlight'))
806 newTheme
=GetCfgSectionNameDialog(self
,'New Custom Theme',
807 message
,usedNames
).result
810 def SaveAsNewTheme(self
):
811 newThemeName
=self
.GetNewThemeName('New Theme Name:')
813 self
.CreateNewTheme(newThemeName
)
815 def CreateNewTheme(self
,newThemeName
):
816 #creates new custom theme based on the previously active theme,
817 #and makes the new theme active
818 if self
.themeIsBuiltin
.get():
820 themeName
=self
.builtinTheme
.get()
823 themeName
=self
.customTheme
.get()
824 newTheme
=idleConf
.GetThemeDict(themeType
,themeName
)
825 #apply any of the old theme's unsaved changes to the new theme
826 if themeName
in self
.changedItems
['highlight'].keys():
827 themeChanges
=self
.changedItems
['highlight'][themeName
]
828 for element
in themeChanges
.keys():
829 newTheme
[element
]=themeChanges
[element
]
831 self
.SaveNewTheme(newThemeName
,newTheme
)
832 #change gui over to the new theme
833 customThemeList
=idleConf
.GetSectionList('user','highlight')
834 customThemeList
.sort()
835 self
.optMenuThemeCustom
.SetMenu(customThemeList
,newThemeName
)
836 self
.themeIsBuiltin
.set(0)
839 def OnListFontButtonRelease(self
,event
):
840 font
= self
.listFontName
.get(ANCHOR
)
841 self
.fontName
.set(font
.lower())
844 def SetFontSample(self
,event
=None):
845 fontName
=self
.fontName
.get()
846 if self
.fontBold
.get():
847 fontWeight
=tkFont
.BOLD
849 fontWeight
=tkFont
.NORMAL
850 self
.editFont
.config(size
=self
.fontSize
.get(),
851 weight
=fontWeight
,family
=fontName
)
853 def SetHighlightTarget(self
):
854 if self
.highlightTarget
.get()=='Cursor': #bg not possible
855 self
.radioFg
.config(state
=DISABLED
)
856 self
.radioBg
.config(state
=DISABLED
)
858 else: #both fg and bg can be set
859 self
.radioFg
.config(state
=NORMAL
)
860 self
.radioBg
.config(state
=NORMAL
)
862 self
.SetColourSample()
864 def SetColourSampleBinding(self
,*args
):
865 self
.SetColourSample()
867 def SetColourSample(self
):
868 #set the colour smaple area
869 tag
=self
.themeElements
[self
.highlightTarget
.get()][0]
870 if self
.fgHilite
.get(): plane
='foreground'
871 else: plane
='background'
872 colour
=self
.textHighlightSample
.tag_cget(tag
,plane
)
873 self
.frameColourSet
.config(bg
=colour
)
875 def PaintThemeSample(self
):
876 if self
.themeIsBuiltin
.get(): #a default theme
877 theme
=self
.builtinTheme
.get()
879 theme
=self
.customTheme
.get()
880 for elementTitle
in self
.themeElements
.keys():
881 element
=self
.themeElements
[elementTitle
][0]
882 colours
=idleConf
.GetHighlight(theme
,element
)
883 if element
=='cursor': #cursor sample needs special painting
884 colours
['background']=idleConf
.GetHighlight(theme
,
886 #handle any unsaved changes to this theme
887 if theme
in self
.changedItems
['highlight'].keys():
888 themeDict
=self
.changedItems
['highlight'][theme
]
889 if themeDict
.has_key(element
+'-foreground'):
890 colours
['foreground']=themeDict
[element
+'-foreground']
891 if themeDict
.has_key(element
+'-background'):
892 colours
['background']=themeDict
[element
+'-background']
893 apply(self
.textHighlightSample
.tag_config
,(element
,),colours
)
894 self
.SetColourSample()
896 ## def OnCheckUserHelpBrowser(self):
897 ## if self.userHelpBrowser.get():
898 ## self.entryHelpBrowser.config(state=NORMAL)
900 ## self.entryHelpBrowser.config(state=DISABLED)
902 def HelpSourceSelected(self
,event
):
903 self
.SetHelpListButtonStates()
905 def SetHelpListButtonStates(self
):
906 if self
.listHelp
.size()<1: #no entries in list
907 self
.buttonHelpListEdit
.config(state
=DISABLED
)
908 self
.buttonHelpListRemove
.config(state
=DISABLED
)
909 else: #there are some entries
910 if self
.listHelp
.curselection(): #there currently is a selection
911 self
.buttonHelpListEdit
.config(state
=NORMAL
)
912 self
.buttonHelpListRemove
.config(state
=NORMAL
)
913 else: #there currently is not a selection
914 self
.buttonHelpListEdit
.config(state
=DISABLED
)
915 self
.buttonHelpListRemove
.config(state
=DISABLED
)
917 def HelpListItemAdd(self
):
918 helpSource
=GetHelpSourceDialog(self
,'New Help Source').result
920 self
.userHelpList
.append( (helpSource
[0],helpSource
[1]) )
921 self
.listHelp
.insert(END
,helpSource
[0])
922 self
.UpdateUserHelpChangedItems()
923 self
.SetHelpListButtonStates()
925 def HelpListItemEdit(self
):
926 itemIndex
=self
.listHelp
.index(ANCHOR
)
927 helpSource
=self
.userHelpList
[itemIndex
]
928 newHelpSource
=GetHelpSourceDialog(self
,'Edit Help Source',
929 menuItem
=helpSource
[0],filePath
=helpSource
[1]).result
930 if (not newHelpSource
) or (newHelpSource
==helpSource
):
932 self
.userHelpList
[itemIndex
]=newHelpSource
933 self
.listHelp
.delete(itemIndex
)
934 self
.listHelp
.insert(itemIndex
,newHelpSource
[0])
935 self
.UpdateUserHelpChangedItems()
936 self
.SetHelpListButtonStates()
938 def HelpListItemRemove(self
):
939 itemIndex
=self
.listHelp
.index(ANCHOR
)
940 del(self
.userHelpList
[itemIndex
])
941 self
.listHelp
.delete(itemIndex
)
942 self
.UpdateUserHelpChangedItems()
943 self
.SetHelpListButtonStates()
945 def UpdateUserHelpChangedItems(self
):
946 "Clear and rebuild the HelpFiles section in self.changedItems"
947 self
.changedItems
['main']['HelpFiles'] = {}
948 for num
in range(1,len(self
.userHelpList
)+1):
949 self
.AddChangedItem('main','HelpFiles',str(num
),
950 string
.join(self
.userHelpList
[num
-1][:2],';'))
952 def LoadFontCfg(self
):
953 ##base editor font selection list
954 fonts
=list(tkFont
.families(self
))
957 self
.listFontName
.insert(END
,font
)
958 configuredFont
=idleConf
.GetOption('main','EditorWindow','font',
960 lc_configuredFont
= configuredFont
.lower()
961 self
.fontName
.set(lc_configuredFont
)
962 lc_fonts
= [s
.lower() for s
in fonts
]
963 if lc_configuredFont
in lc_fonts
:
964 currentFontIndex
= lc_fonts
.index(lc_configuredFont
)
965 self
.listFontName
.see(currentFontIndex
)
966 self
.listFontName
.select_set(currentFontIndex
)
967 self
.listFontName
.select_anchor(currentFontIndex
)
969 fontSize
=idleConf
.GetOption('main','EditorWindow','font-size',
971 self
.optMenuFontSize
.SetMenu(('7','8','9','10','11','12','13','14',
972 '16','18','20','22'),fontSize
)
974 self
.fontBold
.set(idleConf
.GetOption('main','EditorWindow',
975 'font-bold',default
=0,type='bool'))
979 def LoadTabCfg(self
):
980 ##indent type radiobuttons
981 spaceIndent
=idleConf
.GetOption('main','Indent','use-spaces',
982 default
=1,type='bool')
983 self
.indentBySpaces
.set(spaceIndent
)
985 spaceNum
=idleConf
.GetOption('main','Indent','num-spaces',
986 default
=4,type='int')
987 #tabCols=idleConf.GetOption('main','Indent','tab-cols',
988 # default=4,type='int')
989 self
.spaceNum
.set(spaceNum
)
990 #self.tabCols.set(tabCols)
992 def LoadThemeCfg(self
):
993 ##current theme type radiobutton
994 self
.themeIsBuiltin
.set(idleConf
.GetOption('main','Theme','default',
995 type='bool',default
=1))
996 ##currently set theme
997 currentOption
=idleConf
.CurrentTheme()
998 ##load available theme option menus
999 if self
.themeIsBuiltin
.get(): #default theme selected
1000 itemList
=idleConf
.GetSectionList('default','highlight')
1002 self
.optMenuThemeBuiltin
.SetMenu(itemList
,currentOption
)
1003 itemList
=idleConf
.GetSectionList('user','highlight')
1006 self
.radioThemeCustom
.config(state
=DISABLED
)
1007 self
.customTheme
.set('- no custom themes -')
1009 self
.optMenuThemeCustom
.SetMenu(itemList
,itemList
[0])
1010 else: #user theme selected
1011 itemList
=idleConf
.GetSectionList('user','highlight')
1013 self
.optMenuThemeCustom
.SetMenu(itemList
,currentOption
)
1014 itemList
=idleConf
.GetSectionList('default','highlight')
1016 self
.optMenuThemeBuiltin
.SetMenu(itemList
,itemList
[0])
1018 ##load theme element option menu
1019 themeNames
=self
.themeElements
.keys()
1020 themeNames
.sort(self
.__ThemeNameIndexCompare
)
1021 self
.optMenuHighlightTarget
.SetMenu(themeNames
,themeNames
[0])
1022 self
.PaintThemeSample()
1023 self
.SetHighlightTarget()
1025 def __ThemeNameIndexCompare(self
,a
,b
):
1026 if self
.themeElements
[a
][1]<self
.themeElements
[b
][1]: return -1
1027 elif self
.themeElements
[a
][1]==self
.themeElements
[b
][1]: return 0
1030 def LoadKeyCfg(self
):
1031 ##current keys type radiobutton
1032 self
.keysAreBuiltin
.set(idleConf
.GetOption('main','Keys','default',
1033 type='bool',default
=1))
1034 ##currently set keys
1035 currentOption
=idleConf
.CurrentKeys()
1036 ##load available keyset option menus
1037 if self
.keysAreBuiltin
.get(): #default theme selected
1038 itemList
=idleConf
.GetSectionList('default','keys')
1040 self
.optMenuKeysBuiltin
.SetMenu(itemList
,currentOption
)
1041 itemList
=idleConf
.GetSectionList('user','keys')
1044 self
.radioKeysCustom
.config(state
=DISABLED
)
1045 self
.customKeys
.set('- no custom keys -')
1047 self
.optMenuKeysCustom
.SetMenu(itemList
,itemList
[0])
1048 else: #user key set selected
1049 itemList
=idleConf
.GetSectionList('user','keys')
1051 self
.optMenuKeysCustom
.SetMenu(itemList
,currentOption
)
1052 itemList
=idleConf
.GetSectionList('default','keys')
1054 self
.optMenuKeysBuiltin
.SetMenu(itemList
,itemList
[0])
1056 ##load keyset element list
1057 keySetName
=idleConf
.CurrentKeys()
1058 self
.LoadKeysList(keySetName
)
1060 def LoadGeneralCfg(self
):
1062 self
.startupEdit
.set(idleConf
.GetOption('main','General',
1063 'editor-on-startup',default
=1,type='bool'))
1065 self
.autoSave
.set(idleConf
.GetOption('main', 'General', 'autosave',
1066 default
=0, type='bool'))
1067 #initial window size
1068 self
.winWidth
.set(idleConf
.GetOption('main','EditorWindow','width'))
1069 self
.winHeight
.set(idleConf
.GetOption('main','EditorWindow','height'))
1070 # default source encoding
1071 self
.encoding
.set(idleConf
.GetOption('main', 'EditorWindow',
1072 'encoding', default
='none'))
1073 # additional help sources
1074 self
.userHelpList
= idleConf
.GetAllExtraHelpSourcesList()
1075 for helpItem
in self
.userHelpList
:
1076 self
.listHelp
.insert(END
,helpItem
[0])
1077 self
.SetHelpListButtonStates()
1078 #self.userHelpBrowser.set(idleConf.GetOption('main','General',
1079 # 'user-help-browser',default=0,type='bool'))
1080 #self.helpBrowser.set(idleConf.GetOption('main','General',
1081 # 'user-help-browser-command',default=''))
1082 #self.OnCheckUserHelpBrowser()
1084 def LoadConfigs(self
):
1086 load configuration from default and user config files and populate
1087 the widgets on the config dialog pages.
1089 ### fonts / tabs page
1092 ### highlighting page
1097 self
.LoadGeneralCfg()
1099 def SaveNewKeySet(self
,keySetName
,keySet
):
1101 save a newly created core key set.
1102 keySetName - string, the name of the new key set
1103 keySet - dictionary containing the new key set
1105 if not idleConf
.userCfg
['keys'].has_section(keySetName
):
1106 idleConf
.userCfg
['keys'].add_section(keySetName
)
1107 for event
in keySet
.keys():
1109 idleConf
.userCfg
['keys'].SetOption(keySetName
,event
,value
)
1111 def SaveNewTheme(self
,themeName
,theme
):
1113 save a newly created theme.
1114 themeName - string, the name of the new theme
1115 theme - dictionary containing the new theme
1117 if not idleConf
.userCfg
['highlight'].has_section(themeName
):
1118 idleConf
.userCfg
['highlight'].add_section(themeName
)
1119 for element
in theme
.keys():
1120 value
=theme
[element
]
1121 idleConf
.userCfg
['highlight'].SetOption(themeName
,element
,value
)
1123 def SetUserValue(self
,configType
,section
,item
,value
):
1124 if idleConf
.defaultCfg
[configType
].has_option(section
,item
):
1125 if idleConf
.defaultCfg
[configType
].Get(section
,item
)==value
:
1126 #the setting equals a default setting, remove it from user cfg
1127 return idleConf
.userCfg
[configType
].RemoveOption(section
,item
)
1128 #if we got here set the option
1129 return idleConf
.userCfg
[configType
].SetOption(section
,item
,value
)
1131 def SaveAllChangedConfigs(self
):
1132 "Save configuration changes to the user config file."
1133 idleConf
.userCfg
['main'].Save()
1134 for configType
in self
.changedItems
.keys():
1135 cfgTypeHasChanges
= False
1136 for section
in self
.changedItems
[configType
].keys():
1137 if section
== 'HelpFiles':
1138 #this section gets completely replaced
1139 idleConf
.userCfg
['main'].remove_section('HelpFiles')
1140 cfgTypeHasChanges
= True
1141 for item
in self
.changedItems
[configType
][section
].keys():
1142 value
= self
.changedItems
[configType
][section
][item
]
1143 if self
.SetUserValue(configType
,section
,item
,value
):
1144 cfgTypeHasChanges
= True
1145 if cfgTypeHasChanges
:
1146 idleConf
.userCfg
[configType
].Save()
1147 self
.ResetChangedItems() #clear the changed items dict
1149 def ActivateConfigChanges(self
):
1150 #things that need to be done to make
1151 #applied config changes dynamic:
1152 #update editor/shell font and repaint
1153 #dynamically update indentation setttings
1154 #update theme and repaint
1155 #update keybindings and re-bind
1156 #update user help sources menu
1157 winInstances
=self
.parent
.instanceDict
.keys()
1158 for instance
in winInstances
:
1159 instance
.ResetColorizer()
1160 instance
.ResetFont()
1161 instance
.ResetKeybindings()
1162 instance
.reset_help_menu_entries()
1172 self
.SaveAllChangedConfigs()
1173 self
.ActivateConfigChanges()
1178 if __name__
== '__main__':
1181 Button(root
,text
='Dialog',
1182 command
=lambda:ConfigDialog(root
,'Settings')).pack()
1183 root
.instanceDict
={}