5 import tkMessageBox
, tkColorChooser
, tkFont
8 from configHandler
import idleConf
9 from dynOptionMenuWidget
import DynOptionMenu
10 from tabpage
import TabPageSet
11 from keybindingDialog
import GetKeysDialog
12 from configSectionNameDialog
import GetCfgSectionNameDialog
13 from configHelpSourceEdit
import GetHelpSourceDialog
14 class ConfigDialog(Toplevel
):
16 configuration dialog for idle
18 def __init__(self
,parent
,title
):
19 Toplevel
.__init
__(self
, parent
)
20 self
.configure(borderwidth
=5)
21 self
.geometry("+%d+%d" % (parent
.winfo_rootx()+20,
22 parent
.winfo_rooty()+30))
23 #Theme Elements. Each theme element key is it's display name.
24 #The first value of the tuple is the sample area tag name.
25 #The second value is the display name list sort index.
26 self
.themeElements
={'Normal Text':('normal','00'),
27 'Python Keywords':('keyword','01'),
28 'Python Definitions':('definition','02'),
29 'Python Comments':('comment','03'),
30 'Python Strings':('string','04'),
31 'Selected Text':('hilite','05'),
32 'Found Text':('hit','06'),
33 'Cursor':('cursor','07'),
34 'Error Text':('error','08'),
35 'Shell Normal Text':('console','09'),
36 'Shell Stdout Text':('stdout','10'),
37 'Shell Stderr Text':('stderr','11')}
38 self
.ResetChangedItems() #load initial values in changed items dict
40 self
.resizable(height
=FALSE
,width
=FALSE
)
41 self
.transient(parent
)
43 self
.protocol("WM_DELETE_WINDOW", self
.Cancel
)
45 self
.tabPages
.focus_set()
46 #key bindings for this dialog
47 #self.bind('<Escape>',self.Cancel) #dismiss dialog, no save
48 #self.bind('<Alt-a>',self.Apply) #apply changes, save
49 #self.bind('<F1>',self.Help) #context help
51 self
.AttachVarCallbacks() #avoid callbacks during LoadConfigs
54 def CreateWidgets(self
):
55 self
.tabPages
= TabPageSet(self
,
56 pageNames
=['Fonts/Tabs','Highlighting','Keys','General'])
57 self
.tabPages
.ChangePage()#activates default (first) page
58 frameActionButtons
= Frame(self
)
60 self
.buttonHelp
= Button(frameActionButtons
,text
='Help',
61 command
=self
.Help
,takefocus
=FALSE
)
62 self
.buttonOk
= Button(frameActionButtons
,text
='Ok',
63 command
=self
.Ok
,takefocus
=FALSE
)
64 self
.buttonApply
= Button(frameActionButtons
,text
='Apply',
65 command
=self
.Apply
,takefocus
=FALSE
)
66 self
.buttonCancel
= Button(frameActionButtons
,text
='Cancel',
67 command
=self
.Cancel
,takefocus
=FALSE
)
68 self
.CreatePageFontTab()
69 self
.CreatePageHighlight()
71 self
.CreatePageGeneral()
72 self
.buttonHelp
.pack(side
=RIGHT
,padx
=5,pady
=5)
73 self
.buttonOk
.pack(side
=LEFT
,padx
=5,pady
=5)
74 self
.buttonApply
.pack(side
=LEFT
,padx
=5,pady
=5)
75 self
.buttonCancel
.pack(side
=LEFT
,padx
=5,pady
=5)
76 frameActionButtons
.pack(side
=BOTTOM
)
77 self
.tabPages
.pack(side
=TOP
,expand
=TRUE
,fill
=BOTH
)
79 def CreatePageFontTab(self
):
81 self
.fontSize
=StringVar(self
)
82 self
.fontBold
=BooleanVar(self
)
83 self
.fontName
=StringVar(self
)
84 self
.spaceNum
=IntVar(self
)
85 #self.tabCols=IntVar(self)
86 self
.indentBySpaces
=BooleanVar(self
)
87 self
.editFont
=tkFont
.Font(self
,('courier',12,'normal'))
90 frame
=self
.tabPages
.pages
['Fonts/Tabs']['page']
92 frameFont
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
93 frameIndent
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
95 labelFontTitle
=Label(frameFont
,text
='Set Base Editor Font')
96 frameFontName
=Frame(frameFont
)
97 frameFontParam
=Frame(frameFont
)
98 labelFontNameTitle
=Label(frameFontName
,justify
=LEFT
,
100 self
.listFontName
=Listbox(frameFontName
,height
=5,takefocus
=FALSE
,
101 exportselection
=FALSE
)
102 self
.listFontName
.bind('<ButtonRelease-1>',self
.OnListFontButtonRelease
)
103 scrollFont
=Scrollbar(frameFontName
)
104 scrollFont
.config(command
=self
.listFontName
.yview
)
105 self
.listFontName
.config(yscrollcommand
=scrollFont
.set)
106 labelFontSizeTitle
=Label(frameFontParam
,text
='Size :')
107 self
.optMenuFontSize
=DynOptionMenu(frameFontParam
,self
.fontSize
,None,
108 command
=self
.SetFontSample
)
109 checkFontBold
=Checkbutton(frameFontParam
,variable
=self
.fontBold
,
110 onvalue
=1,offvalue
=0,text
='Bold',command
=self
.SetFontSample
)
111 frameFontSample
=Frame(frameFont
,relief
=SOLID
,borderwidth
=1)
112 self
.labelFontSample
=Label(frameFontSample
,
113 text
='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]',
114 justify
=LEFT
,font
=self
.editFont
)
116 labelIndentTitle
=Label(frameIndent
,text
='Set Indentation Defaults')
117 frameIndentType
=Frame(frameIndent
)
118 frameIndentSize
=Frame(frameIndent
)
119 labelIndentTypeTitle
=Label(frameIndentType
,
120 text
='Choose indentation type :')
121 radioUseSpaces
=Radiobutton(frameIndentType
,variable
=self
.indentBySpaces
,
122 value
=1,text
='Tab key inserts spaces')
123 radioUseTabs
=Radiobutton(frameIndentType
,variable
=self
.indentBySpaces
,
124 value
=0,text
='Tab key inserts tabs')
125 labelIndentSizeTitle
=Label(frameIndentSize
,
126 text
='Choose indentation size :')
127 labelSpaceNumTitle
=Label(frameIndentSize
,justify
=LEFT
,
128 text
='when tab key inserts spaces,\nspaces per indent')
129 self
.scaleSpaceNum
=Scale(frameIndentSize
,variable
=self
.spaceNum
,
130 orient
='horizontal',tickinterval
=2,from_
=2,to
=10)
131 #labeltabColsTitle=Label(frameIndentSize,justify=LEFT,
132 # text='when tab key inserts tabs,\ncolumns per tab')
133 #self.scaleTabCols=Scale(frameIndentSize,variable=self.tabCols,
134 # orient='horizontal',tickinterval=2,from_=2,to=8)
137 frameFont
.pack(side
=LEFT
,padx
=5,pady
=10,expand
=TRUE
,fill
=BOTH
)
138 frameIndent
.pack(side
=LEFT
,padx
=5,pady
=10,fill
=Y
)
140 labelFontTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
141 frameFontName
.pack(side
=TOP
,padx
=5,pady
=5,fill
=X
)
142 frameFontParam
.pack(side
=TOP
,padx
=5,pady
=5,fill
=X
)
143 labelFontNameTitle
.pack(side
=TOP
,anchor
=W
)
144 self
.listFontName
.pack(side
=LEFT
,expand
=TRUE
,fill
=X
)
145 scrollFont
.pack(side
=LEFT
,fill
=Y
)
146 labelFontSizeTitle
.pack(side
=LEFT
,anchor
=W
)
147 self
.optMenuFontSize
.pack(side
=LEFT
,anchor
=W
)
148 checkFontBold
.pack(side
=LEFT
,anchor
=W
,padx
=20)
149 frameFontSample
.pack(side
=TOP
,padx
=5,pady
=5,expand
=TRUE
,fill
=BOTH
)
150 self
.labelFontSample
.pack(expand
=TRUE
,fill
=BOTH
)
152 labelIndentTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
153 frameIndentType
.pack(side
=TOP
,padx
=5,fill
=X
)
154 frameIndentSize
.pack(side
=TOP
,padx
=5,pady
=5,fill
=BOTH
)
155 labelIndentTypeTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
156 radioUseSpaces
.pack(side
=TOP
,anchor
=W
,padx
=5)
157 radioUseTabs
.pack(side
=TOP
,anchor
=W
,padx
=5)
158 labelIndentSizeTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
159 labelSpaceNumTitle
.pack(side
=TOP
,anchor
=W
,padx
=5)
160 self
.scaleSpaceNum
.pack(side
=TOP
,padx
=5,fill
=X
)
161 #labeltabColsTitle.pack(side=TOP,anchor=W,padx=5)
162 #self.scaleTabCols.pack(side=TOP,padx=5,fill=X)
165 def CreatePageHighlight(self
):
166 self
.builtinTheme
=StringVar(self
)
167 self
.customTheme
=StringVar(self
)
168 self
.fgHilite
=BooleanVar(self
)
169 self
.colour
=StringVar(self
)
170 self
.fontName
=StringVar(self
)
171 self
.themeIsBuiltin
=BooleanVar(self
)
172 self
.highlightTarget
=StringVar(self
)
175 frame
=self
.tabPages
.pages
['Highlighting']['page']
177 frameCustom
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
178 frameTheme
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
180 self
.textHighlightSample
=Text(frameCustom
,relief
=SOLID
,borderwidth
=1,
181 font
=('courier',12,''),cursor
='hand2',width
=21,height
=10,
182 takefocus
=FALSE
,highlightthickness
=0,wrap
=NONE
)
183 text
=self
.textHighlightSample
184 text
.bind('<Double-Button-1>',lambda e
: 'break')
185 text
.bind('<B1-Motion>',lambda e
: 'break')
186 textAndTags
=(('#you can click here','comment'),('\n','normal'),
187 ('#to choose items','comment'),('\n','normal'),('def','keyword'),
188 (' ','normal'),('func','definition'),('(param):','normal'),
189 ('\n ','normal'),('"""string"""','string'),('\n var0 = ','normal'),
190 ("'string'",'string'),('\n var1 = ','normal'),("'selected'",'hilite'),
191 ('\n var2 = ','normal'),("'found'",'hit'),('\n\n','normal'),
192 (' error ','error'),(' ','normal'),('cursor |','cursor'),
193 ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'),
194 (' ','normal'),('stderr','stderr'),('\n','normal'))
195 for txTa
in textAndTags
:
196 text
.insert(END
,txTa
[0],txTa
[1])
197 for element
in self
.themeElements
.keys():
198 text
.tag_bind(self
.themeElements
[element
][0],'<ButtonPress-1>',
199 lambda event
,elem
=element
: event
.widget
.winfo_toplevel()
200 .highlightTarget
.set(elem
))
201 text
.config(state
=DISABLED
)
202 self
.frameColourSet
=Frame(frameCustom
,relief
=SOLID
,borderwidth
=1)
203 frameFgBg
=Frame(frameCustom
)
204 labelCustomTitle
=Label(frameCustom
,text
='Set Custom Highlighting')
205 buttonSetColour
=Button(self
.frameColourSet
,text
='Choose Colour for :',
206 command
=self
.GetColour
,highlightthickness
=0)
207 self
.optMenuHighlightTarget
=DynOptionMenu(self
.frameColourSet
,
208 self
.highlightTarget
,None,highlightthickness
=0)#,command=self.SetHighlightTargetBinding
209 self
.radioFg
=Radiobutton(frameFgBg
,variable
=self
.fgHilite
,
210 value
=1,text
='Foreground',command
=self
.SetColourSampleBinding
)
211 self
.radioBg
=Radiobutton(frameFgBg
,variable
=self
.fgHilite
,
212 value
=0,text
='Background',command
=self
.SetColourSampleBinding
)
214 buttonSaveCustomTheme
=Button(frameCustom
,
215 text
='Save as New Custom Theme',command
=self
.SaveAsNewTheme
)
217 labelThemeTitle
=Label(frameTheme
,text
='Select a Highlighting Theme')
218 labelTypeTitle
=Label(frameTheme
,text
='Select : ')
219 self
.radioThemeBuiltin
=Radiobutton(frameTheme
,variable
=self
.themeIsBuiltin
,
220 value
=1,command
=self
.SetThemeType
,text
='a Built-in Theme')
221 self
.radioThemeCustom
=Radiobutton(frameTheme
,variable
=self
.themeIsBuiltin
,
222 value
=0,command
=self
.SetThemeType
,text
='a Custom Theme')
223 self
.optMenuThemeBuiltin
=DynOptionMenu(frameTheme
,
224 self
.builtinTheme
,None,command
=None)
225 self
.optMenuThemeCustom
=DynOptionMenu(frameTheme
,
226 self
.customTheme
,None,command
=None)
227 self
.buttonDeleteCustomTheme
=Button(frameTheme
,text
='Delete Custom Theme',
228 command
=self
.DeleteCustomTheme
)
231 frameCustom
.pack(side
=LEFT
,padx
=5,pady
=10,expand
=TRUE
,fill
=BOTH
)
232 frameTheme
.pack(side
=LEFT
,padx
=5,pady
=10,fill
=Y
)
234 labelCustomTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
235 self
.frameColourSet
.pack(side
=TOP
,padx
=5,pady
=5,expand
=TRUE
,fill
=X
)
236 frameFgBg
.pack(side
=TOP
,padx
=5,pady
=0)
237 self
.textHighlightSample
.pack(side
=TOP
,padx
=5,pady
=5,expand
=TRUE
,
239 buttonSetColour
.pack(side
=TOP
,expand
=TRUE
,fill
=X
,padx
=8,pady
=4)
240 self
.optMenuHighlightTarget
.pack(side
=TOP
,expand
=TRUE
,fill
=X
,padx
=8,pady
=3)
241 self
.radioFg
.pack(side
=LEFT
,anchor
=E
)
242 self
.radioBg
.pack(side
=RIGHT
,anchor
=W
)
243 buttonSaveCustomTheme
.pack(side
=BOTTOM
,fill
=X
,padx
=5,pady
=5)
245 labelThemeTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
246 labelTypeTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
247 self
.radioThemeBuiltin
.pack(side
=TOP
,anchor
=W
,padx
=5)
248 self
.radioThemeCustom
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=2)
249 self
.optMenuThemeBuiltin
.pack(side
=TOP
,fill
=X
,padx
=5,pady
=5)
250 self
.optMenuThemeCustom
.pack(side
=TOP
,fill
=X
,anchor
=W
,padx
=5,pady
=5)
251 self
.buttonDeleteCustomTheme
.pack(side
=TOP
,fill
=X
,padx
=5,pady
=5)
254 def CreatePageKeys(self
):
256 self
.bindingTarget
=StringVar(self
)
257 self
.builtinKeys
=StringVar(self
)
258 self
.customKeys
=StringVar(self
)
259 self
.keysAreBuiltin
=BooleanVar(self
)
260 self
.keyBinding
=StringVar(self
)
263 frame
=self
.tabPages
.pages
['Keys']['page']
265 frameCustom
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
266 frameKeySets
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
268 frameTarget
=Frame(frameCustom
)
269 labelCustomTitle
=Label(frameCustom
,text
='Set Custom Key Bindings')
270 labelTargetTitle
=Label(frameTarget
,text
='Action - Key(s)')
271 scrollTargetY
=Scrollbar(frameTarget
)
272 scrollTargetX
=Scrollbar(frameTarget
,orient
=HORIZONTAL
)
273 self
.listBindings
=Listbox(frameTarget
,takefocus
=FALSE
,
274 exportselection
=FALSE
)
275 self
.listBindings
.bind('<ButtonRelease-1>',self
.KeyBindingSelected
)
276 scrollTargetY
.config(command
=self
.listBindings
.yview
)
277 scrollTargetX
.config(command
=self
.listBindings
.xview
)
278 self
.listBindings
.config(yscrollcommand
=scrollTargetY
.set)
279 self
.listBindings
.config(xscrollcommand
=scrollTargetX
.set)
280 self
.buttonNewKeys
=Button(frameCustom
,text
='Get New Keys for Selection',
281 command
=self
.GetNewKeys
,state
=DISABLED
)
282 buttonSaveCustomKeys
=Button(frameCustom
,
283 text
='Save as New Custom Key Set',command
=self
.SaveAsNewKeySet
)
285 labelKeysTitle
=Label(frameKeySets
,text
='Select a Key Set')
286 labelTypeTitle
=Label(frameKeySets
,text
='Select : ')
287 self
.radioKeysBuiltin
=Radiobutton(frameKeySets
,variable
=self
.keysAreBuiltin
,
288 value
=1,command
=self
.SetKeysType
,text
='a Built-in Key Set')
289 self
.radioKeysCustom
=Radiobutton(frameKeySets
,variable
=self
.keysAreBuiltin
,
290 value
=0,command
=self
.SetKeysType
,text
='a Custom Key Set')
291 self
.optMenuKeysBuiltin
=DynOptionMenu(frameKeySets
,
292 self
.builtinKeys
,None,command
=None)
293 self
.optMenuKeysCustom
=DynOptionMenu(frameKeySets
,
294 self
.customKeys
,None,command
=None)
295 self
.buttonDeleteCustomKeys
=Button(frameKeySets
,text
='Delete Custom Key Set',
296 command
=self
.DeleteCustomKeys
)
299 frameCustom
.pack(side
=LEFT
,padx
=5,pady
=5,expand
=TRUE
,fill
=BOTH
)
300 frameKeySets
.pack(side
=LEFT
,padx
=5,pady
=5,fill
=Y
)
302 labelCustomTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
303 buttonSaveCustomKeys
.pack(side
=BOTTOM
,fill
=X
,padx
=5,pady
=5)
304 self
.buttonNewKeys
.pack(side
=BOTTOM
,fill
=X
,padx
=5,pady
=5)
305 frameTarget
.pack(side
=LEFT
,padx
=5,pady
=5,expand
=TRUE
,fill
=BOTH
)
307 frameTarget
.columnconfigure(0,weight
=1)
308 frameTarget
.rowconfigure(1,weight
=1)
309 labelTargetTitle
.grid(row
=0,column
=0,columnspan
=2,sticky
=W
)
310 self
.listBindings
.grid(row
=1,column
=0,sticky
=NSEW
)
311 scrollTargetY
.grid(row
=1,column
=1,sticky
=NS
)
312 scrollTargetX
.grid(row
=2,column
=0,sticky
=EW
)
314 labelKeysTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
315 labelTypeTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
316 self
.radioKeysBuiltin
.pack(side
=TOP
,anchor
=W
,padx
=5)
317 self
.radioKeysCustom
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=2)
318 self
.optMenuKeysBuiltin
.pack(side
=TOP
,fill
=X
,padx
=5,pady
=5)
319 self
.optMenuKeysCustom
.pack(side
=TOP
,fill
=X
,anchor
=W
,padx
=5,pady
=5)
320 self
.buttonDeleteCustomKeys
.pack(side
=TOP
,fill
=X
,padx
=5,pady
=5)
323 def CreatePageGeneral(self
):
325 self
.winWidth
=StringVar(self
)
326 self
.winHeight
=StringVar(self
)
327 self
.startupEdit
=IntVar(self
)
328 self
.userHelpBrowser
=BooleanVar(self
)
329 self
.helpBrowser
=StringVar(self
)
332 frame
=self
.tabPages
.pages
['General']['page']
334 frameRun
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
335 frameWinSize
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
336 frameHelp
=Frame(frame
,borderwidth
=2,relief
=GROOVE
)
338 labelRunTitle
=Label(frameRun
,text
='Startup Preferences')
339 labelRunChoiceTitle
=Label(frameRun
,text
='On startup : ')
340 radioStartupEdit
=Radiobutton(frameRun
,variable
=self
.startupEdit
,
341 value
=1,command
=self
.SetKeysType
,text
="open Edit Window")
342 radioStartupShell
=Radiobutton(frameRun
,variable
=self
.startupEdit
,
343 value
=0,command
=self
.SetKeysType
,text
='open Shell Window')
345 labelWinSizeTitle
=Label(frameWinSize
,text
='Initial Window Size'+
347 labelWinWidthTitle
=Label(frameWinSize
,text
='Width')
348 entryWinWidth
=Entry(frameWinSize
,textvariable
=self
.winWidth
,
350 labelWinHeightTitle
=Label(frameWinSize
,text
='Height')
351 entryWinHeight
=Entry(frameWinSize
,textvariable
=self
.winHeight
,
354 labelHelpTitle
=Label(frameHelp
,text
='Help Options')
355 frameHelpList
=Frame(frameHelp
)
356 frameHelpListButtons
=Frame(frameHelpList
)
357 labelHelpListTitle
=Label(frameHelpList
,text
='Additional (html) Help Sources:')
358 scrollHelpList
=Scrollbar(frameHelpList
)
359 self
.listHelp
=Listbox(frameHelpList
,height
=5,takefocus
=FALSE
,
360 exportselection
=FALSE
)
361 scrollHelpList
.config(command
=self
.listHelp
.yview
)
362 self
.listHelp
.config(yscrollcommand
=scrollHelpList
.set)
363 self
.listHelp
.bind('<ButtonRelease-1>',self
.HelpSourceSelected
)
364 self
.buttonHelpListEdit
=Button(frameHelpListButtons
,text
='Edit',
365 state
=DISABLED
,width
=8,command
=self
.HelpListItemEdit
)
366 self
.buttonHelpListAdd
=Button(frameHelpListButtons
,text
='Add',
367 width
=8,command
=self
.HelpListItemAdd
)
368 self
.buttonHelpListRemove
=Button(frameHelpListButtons
,text
='Remove',
369 state
=DISABLED
,width
=8,command
=self
.HelpListItemRemove
)
370 # the following is better handled by the BROWSER environment
371 # variable under unix/linux
372 #checkHelpBrowser=Checkbutton(frameHelp,variable=self.userHelpBrowser,
373 # onvalue=1,offvalue=0,text='user specified (html) help browser:',
374 # command=self.OnCheckUserHelpBrowser)
375 #self.entryHelpBrowser=Entry(frameHelp,textvariable=self.helpBrowser,
379 frameRun
.pack(side
=TOP
,padx
=5,pady
=5,fill
=X
)
380 frameWinSize
.pack(side
=TOP
,padx
=5,pady
=5,fill
=X
)
381 frameHelp
.pack(side
=TOP
,padx
=5,pady
=5,expand
=TRUE
,fill
=BOTH
)
383 labelRunTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
384 labelRunChoiceTitle
.pack(side
=LEFT
,anchor
=W
,padx
=5,pady
=5)
385 radioStartupEdit
.pack(side
=LEFT
,anchor
=W
,padx
=5,pady
=5)
386 radioStartupShell
.pack(side
=LEFT
,anchor
=W
,padx
=5,pady
=5)
388 labelWinSizeTitle
.pack(side
=LEFT
,anchor
=W
,padx
=5,pady
=5)
389 entryWinHeight
.pack(side
=RIGHT
,anchor
=E
,padx
=10,pady
=5)
390 labelWinHeightTitle
.pack(side
=RIGHT
,anchor
=E
,pady
=5)
391 entryWinWidth
.pack(side
=RIGHT
,anchor
=E
,padx
=10,pady
=5)
392 labelWinWidthTitle
.pack(side
=RIGHT
,anchor
=E
,pady
=5)
394 labelHelpTitle
.pack(side
=TOP
,anchor
=W
,padx
=5,pady
=5)
395 frameHelpListButtons
.pack(side
=RIGHT
,padx
=5,pady
=5,fill
=Y
)
396 frameHelpList
.pack(side
=TOP
,padx
=5,pady
=5,expand
=TRUE
,fill
=BOTH
)
397 labelHelpListTitle
.pack(side
=TOP
,anchor
=W
)
398 scrollHelpList
.pack(side
=RIGHT
,anchor
=W
,fill
=Y
)
399 self
.listHelp
.pack(side
=LEFT
,anchor
=E
,expand
=TRUE
,fill
=BOTH
)
400 self
.buttonHelpListEdit
.pack(side
=TOP
,anchor
=W
,pady
=5)
401 self
.buttonHelpListAdd
.pack(side
=TOP
,anchor
=W
)
402 self
.buttonHelpListRemove
.pack(side
=TOP
,anchor
=W
,pady
=5)
403 #checkHelpBrowser.pack(side=TOP,anchor=W,padx=5)
404 #self.entryHelpBrowser.pack(side=TOP,anchor=W,padx=5,pady=5)
407 def AttachVarCallbacks(self
):
408 self
.fontSize
.trace_variable('w',self
.VarChanged_fontSize
)
409 self
.fontName
.trace_variable('w',self
.VarChanged_fontName
)
410 self
.fontBold
.trace_variable('w',self
.VarChanged_fontBold
)
411 self
.spaceNum
.trace_variable('w',self
.VarChanged_spaceNum
)
412 #self.tabCols.trace_variable('w',self.VarChanged_tabCols)
413 self
.indentBySpaces
.trace_variable('w',self
.VarChanged_indentBySpaces
)
414 self
.colour
.trace_variable('w',self
.VarChanged_colour
)
415 self
.builtinTheme
.trace_variable('w',self
.VarChanged_builtinTheme
)
416 self
.customTheme
.trace_variable('w',self
.VarChanged_customTheme
)
417 self
.themeIsBuiltin
.trace_variable('w',self
.VarChanged_themeIsBuiltin
)
418 self
.highlightTarget
.trace_variable('w',self
.VarChanged_highlightTarget
)
419 self
.keyBinding
.trace_variable('w',self
.VarChanged_keyBinding
)
420 self
.builtinKeys
.trace_variable('w',self
.VarChanged_builtinKeys
)
421 self
.customKeys
.trace_variable('w',self
.VarChanged_customKeys
)
422 self
.keysAreBuiltin
.trace_variable('w',self
.VarChanged_keysAreBuiltin
)
423 self
.winWidth
.trace_variable('w',self
.VarChanged_winWidth
)
424 self
.winHeight
.trace_variable('w',self
.VarChanged_winHeight
)
425 self
.startupEdit
.trace_variable('w',self
.VarChanged_startupEdit
)
427 def VarChanged_fontSize(self
,*params
):
428 value
=self
.fontSize
.get()
429 self
.AddChangedItem('main','EditorWindow','font-size',value
)
431 def VarChanged_fontName(self
,*params
):
432 value
=self
.fontName
.get()
433 self
.AddChangedItem('main','EditorWindow','font',value
)
435 def VarChanged_fontBold(self
,*params
):
436 value
=self
.fontBold
.get()
437 self
.AddChangedItem('main','EditorWindow','font-bold',value
)
439 def VarChanged_indentBySpaces(self
,*params
):
440 value
=self
.indentBySpaces
.get()
441 self
.AddChangedItem('main','Indent','use-spaces',value
)
443 def VarChanged_spaceNum(self
,*params
):
444 value
=self
.spaceNum
.get()
445 self
.AddChangedItem('main','Indent','num-spaces',value
)
447 #def VarChanged_tabCols(self,*params):
448 # value=self.tabCols.get()
449 # self.AddChangedItem('main','Indent','tab-cols',value)
451 def VarChanged_colour(self
,*params
):
452 self
.OnNewColourSet()
454 def VarChanged_builtinTheme(self
,*params
):
455 value
=self
.builtinTheme
.get()
456 self
.AddChangedItem('main','Theme','name',value
)
457 self
.PaintThemeSample()
459 def VarChanged_customTheme(self
,*params
):
460 value
=self
.customTheme
.get()
461 if value
!= '- no custom themes -':
462 self
.AddChangedItem('main','Theme','name',value
)
463 self
.PaintThemeSample()
465 def VarChanged_themeIsBuiltin(self
,*params
):
466 value
=self
.themeIsBuiltin
.get()
467 self
.AddChangedItem('main','Theme','default',value
)
469 self
.VarChanged_builtinTheme()
471 self
.VarChanged_customTheme()
473 def VarChanged_highlightTarget(self
,*params
):
474 self
.SetHighlightTarget()
476 def VarChanged_keyBinding(self
,*params
):
477 value
=self
.keyBinding
.get()
478 keySet
=self
.customKeys
.get()
479 event
=self
.listBindings
.get(ANCHOR
).split()[0]
480 if idleConf
.IsCoreBinding(event
):
481 #this is a core keybinding
482 self
.AddChangedItem('keys',keySet
,event
,value
)
483 else: #this is an extension key binding
484 extName
=idleConf
.GetExtnNameForEvent(event
)
485 extKeybindSection
=extName
+'_cfgBindings'
486 self
.AddChangedItem('extensions',extKeybindSection
,event
,value
)
488 def VarChanged_builtinKeys(self
,*params
):
489 value
=self
.builtinKeys
.get()
490 self
.AddChangedItem('main','Keys','name',value
)
491 self
.LoadKeysList(value
)
493 def VarChanged_customKeys(self
,*params
):
494 value
=self
.customKeys
.get()
495 if value
!= '- no custom keys -':
496 self
.AddChangedItem('main','Keys','name',value
)
497 self
.LoadKeysList(value
)
499 def VarChanged_keysAreBuiltin(self
,*params
):
500 value
=self
.keysAreBuiltin
.get()
501 self
.AddChangedItem('main','Keys','default',value
)
503 self
.VarChanged_builtinKeys()
505 self
.VarChanged_customKeys()
507 def VarChanged_winWidth(self
,*params
):
508 value
=self
.winWidth
.get()
509 self
.AddChangedItem('main','EditorWindow','width',value
)
511 def VarChanged_winHeight(self
,*params
):
512 value
=self
.winHeight
.get()
513 self
.AddChangedItem('main','EditorWindow','height',value
)
515 def VarChanged_startupEdit(self
,*params
):
516 value
=self
.startupEdit
.get()
517 self
.AddChangedItem('main','General','editor-on-startup',value
)
519 def ResetChangedItems(self
):
520 #When any config item is changed in this dialog, an entry
521 #should be made in the relevant section (config type) of this
522 #dictionary. The key should be the config file section name and the
523 #value a dictionary, whose key:value pairs are item=value pairs for
524 #that config file section.
525 self
.changedItems
={'main':{},'highlight':{},'keys':{},'extensions':{}}
527 def AddChangedItem(self
,type,section
,item
,value
):
528 value
=str(value
) #make sure we use a string
529 if not self
.changedItems
[type].has_key(section
):
530 self
.changedItems
[type][section
]={}
531 self
.changedItems
[type][section
][item
]=value
533 def GetDefaultItems(self
):
534 dItems
={'main':{},'highlight':{},'keys':{},'extensions':{}}
535 for configType
in dItems
.keys():
536 sections
=idleConf
.GetSectionList('default',configType
)
537 for section
in sections
:
538 dItems
[configType
][section
]={}
539 options
=idleConf
.defaultCfg
[configType
].GetOptionList(section
)
540 for option
in options
:
541 dItems
[configType
][section
][option
]=(
542 idleConf
.defaultCfg
[configType
].Get(section
,option
))
545 def SetThemeType(self
):
546 if self
.themeIsBuiltin
.get():
547 self
.optMenuThemeBuiltin
.config(state
=NORMAL
)
548 self
.optMenuThemeCustom
.config(state
=DISABLED
)
549 self
.buttonDeleteCustomTheme
.config(state
=DISABLED
)
551 self
.optMenuThemeBuiltin
.config(state
=DISABLED
)
552 self
.radioThemeCustom
.config(state
=NORMAL
)
553 self
.optMenuThemeCustom
.config(state
=NORMAL
)
554 self
.buttonDeleteCustomTheme
.config(state
=NORMAL
)
556 def SetKeysType(self
):
557 if self
.keysAreBuiltin
.get():
558 self
.optMenuKeysBuiltin
.config(state
=NORMAL
)
559 self
.optMenuKeysCustom
.config(state
=DISABLED
)
560 self
.buttonDeleteCustomKeys
.config(state
=DISABLED
)
562 self
.optMenuKeysBuiltin
.config(state
=DISABLED
)
563 self
.radioKeysCustom
.config(state
=NORMAL
)
564 self
.optMenuKeysCustom
.config(state
=NORMAL
)
565 self
.buttonDeleteCustomKeys
.config(state
=NORMAL
)
567 def GetNewKeys(self
):
568 listIndex
=self
.listBindings
.index(ANCHOR
)
569 binding
=self
.listBindings
.get(listIndex
)
570 bindName
=binding
.split()[0] #first part, up to first space
571 if self
.keysAreBuiltin
.get():
572 currentKeySetName
=self
.builtinKeys
.get()
574 currentKeySetName
=self
.customKeys
.get()
575 currentBindings
=idleConf
.GetCurrentKeySet()
576 if currentKeySetName
in self
.changedItems
['keys'].keys(): #unsaved changes
577 keySetChanges
=self
.changedItems
['keys'][currentKeySetName
]
578 for event
in keySetChanges
.keys():
579 currentBindings
[event
]=keySetChanges
[event
].split()
580 currentKeySequences
=currentBindings
.values()
581 newKeys
=GetKeysDialog(self
,'Get New Keys',bindName
,
582 currentKeySequences
).result
583 if newKeys
: #new keys were specified
584 if self
.keysAreBuiltin
.get(): #current key set is a built-in
585 message
=('Your changes will be saved as a new Custom Key Set. '+
586 'Enter a name for your new Custom Key Set below.')
587 newKeySet
=self
.GetNewKeysName(message
)
588 if not newKeySet
: #user cancelled custom key set creation
589 self
.listBindings
.select_set(listIndex
)
590 self
.listBindings
.select_anchor(listIndex
)
592 else: #create new custom key set based on previously active key set
593 self
.CreateNewKeySet(newKeySet
)
594 self
.listBindings
.delete(listIndex
)
595 self
.listBindings
.insert(listIndex
,bindName
+' - '+newKeys
)
596 self
.listBindings
.select_set(listIndex
)
597 self
.listBindings
.select_anchor(listIndex
)
598 self
.keyBinding
.set(newKeys
)
600 self
.listBindings
.select_set(listIndex
)
601 self
.listBindings
.select_anchor(listIndex
)
603 def GetNewKeysName(self
,message
):
604 usedNames
=(idleConf
.GetSectionList('user','keys')+
605 idleConf
.GetSectionList('default','keys'))
606 newKeySet
=GetCfgSectionNameDialog(self
,'New Custom Key Set',
607 message
,usedNames
).result
610 def SaveAsNewKeySet(self
):
611 newKeysName
=self
.GetNewKeysName('New Key Set Name:')
613 self
.CreateNewKeySet(newKeysName
)
615 def KeyBindingSelected(self
,event
):
616 self
.buttonNewKeys
.config(state
=NORMAL
)
618 def CreateNewKeySet(self
,newKeySetName
):
619 #creates new custom key set based on the previously active key set,
620 #and makes the new key set active
621 if self
.keysAreBuiltin
.get():
622 prevKeySetName
=self
.builtinKeys
.get()
624 prevKeySetName
=self
.customKeys
.get()
625 prevKeys
=idleConf
.GetCoreKeys(prevKeySetName
)
627 for event
in prevKeys
.keys(): #add key set to changed items
628 eventName
=event
[2:-2] #trim off the angle brackets
629 binding
=string
.join(prevKeys
[event
])
630 newKeys
[eventName
]=binding
631 #handle any unsaved changes to prev key set
632 if prevKeySetName
in self
.changedItems
['keys'].keys():
633 keySetChanges
=self
.changedItems
['keys'][prevKeySetName
]
634 for event
in keySetChanges
.keys():
635 newKeys
[event
]=keySetChanges
[event
]
637 self
.SaveNewKeySet(newKeySetName
,newKeys
)
638 #change gui over to the new key set
639 customKeyList
=idleConf
.GetSectionList('user','keys')
641 self
.optMenuKeysCustom
.SetMenu(customKeyList
,newKeySetName
)
642 self
.keysAreBuiltin
.set(0)
645 def LoadKeysList(self
,keySetName
):
648 if self
.listBindings
.curselection():
650 listIndex
=self
.listBindings
.index(ANCHOR
)
651 keySet
=idleConf
.GetKeySet(keySetName
)
652 bindNames
=keySet
.keys()
654 self
.listBindings
.delete(0,END
)
655 for bindName
in bindNames
:
656 key
=string
.join(keySet
[bindName
]) #make key(s) into a string
657 bindName
=bindName
[2:-2] #trim off the angle brackets
658 if keySetName
in self
.changedItems
['keys'].keys():
659 #handle any unsaved changes to this key set
660 if bindName
in self
.changedItems
['keys'][keySetName
].keys():
661 key
=self
.changedItems
['keys'][keySetName
][bindName
]
662 self
.listBindings
.insert(END
, bindName
+' - '+key
)
664 self
.listBindings
.see(listIndex
)
665 self
.listBindings
.select_set(listIndex
)
666 self
.listBindings
.select_anchor(listIndex
)
668 def DeleteCustomKeys(self
):
669 keySetName
=self
.customKeys
.get()
670 if not tkMessageBox
.askyesno('Delete Key Set','Are you sure you wish '+
671 'to delete the key set '+`keySetName`
+' ?'):
673 #remove key set from config
674 idleConf
.userCfg
['keys'].remove_section(keySetName
)
675 if self
.changedItems
['keys'].has_key(keySetName
):
676 del(self
.changedItems
['keys'][keySetName
])
678 idleConf
.userCfg
['keys'].Save()
679 #reload user key set list
680 itemList
=idleConf
.GetSectionList('user','keys')
683 self
.radioKeysCustom
.config(state
=DISABLED
)
684 self
.optMenuKeysCustom
.SetMenu(itemList
,'- no custom keys -')
686 self
.optMenuKeysCustom
.SetMenu(itemList
,itemList
[0])
687 #revert to default key set
688 self
.keysAreBuiltin
.set(idleConf
.defaultCfg
['main'].Get('Keys','default'))
689 self
.builtinKeys
.set(idleConf
.defaultCfg
['main'].Get('Keys','name'))
690 #user can't back out of these changes, they must be applied now
694 def DeleteCustomTheme(self
):
695 themeName
=self
.customTheme
.get()
696 if not tkMessageBox
.askyesno('Delete Theme','Are you sure you wish '+
697 'to delete the theme '+`themeName`
+' ?'):
699 #remove theme from config
700 idleConf
.userCfg
['highlight'].remove_section(themeName
)
701 if self
.changedItems
['highlight'].has_key(themeName
):
702 del(self
.changedItems
['highlight'][themeName
])
704 idleConf
.userCfg
['highlight'].Save()
705 #reload user theme list
706 itemList
=idleConf
.GetSectionList('user','highlight')
709 self
.radioThemeCustom
.config(state
=DISABLED
)
710 self
.optMenuThemeCustom
.SetMenu(itemList
,'- no custom themes -')
712 self
.optMenuThemeCustom
.SetMenu(itemList
,itemList
[0])
713 #revert to default theme
714 self
.themeIsBuiltin
.set(idleConf
.defaultCfg
['main'].Get('Theme','default'))
715 self
.builtinTheme
.set(idleConf
.defaultCfg
['main'].Get('Theme','name'))
716 #user can't back out of these changes, they must be applied now
721 target
=self
.highlightTarget
.get()
722 prevColour
=self
.frameColourSet
.cget('bg')
723 rgbTuplet
, colourString
= tkColorChooser
.askcolor(parent
=self
,
724 title
='Pick new colour for : '+target
,initialcolor
=prevColour
)
725 if colourString
and (colourString
!=prevColour
):
726 #user didn't cancel, and they chose a new colour
727 if self
.themeIsBuiltin
.get(): #current theme is a built-in
728 message
=('Your changes will be saved as a new Custom Theme. '+
729 'Enter a name for your new Custom Theme below.')
730 newTheme
=self
.GetNewThemeName(message
)
731 if not newTheme
: #user cancelled custom theme creation
733 else: #create new custom theme based on previously active theme
734 self
.CreateNewTheme(newTheme
)
735 self
.colour
.set(colourString
)
736 else: #current theme is user defined
737 self
.colour
.set(colourString
)
739 def OnNewColourSet(self
):
740 newColour
=self
.colour
.get()
741 self
.frameColourSet
.config(bg
=newColour
)#set sample
742 if self
.fgHilite
.get(): plane
='foreground'
743 else: plane
='background'
744 sampleElement
=self
.themeElements
[self
.highlightTarget
.get()][0]
745 apply(self
.textHighlightSample
.tag_config
,
746 (sampleElement
,),{plane
:newColour
})
747 theme
=self
.customTheme
.get()
748 themeElement
=sampleElement
+'-'+plane
749 self
.AddChangedItem('highlight',theme
,themeElement
,newColour
)
751 def GetNewThemeName(self
,message
):
752 usedNames
=(idleConf
.GetSectionList('user','highlight')+
753 idleConf
.GetSectionList('default','highlight'))
754 newTheme
=GetCfgSectionNameDialog(self
,'New Custom Theme',
755 message
,usedNames
).result
758 def SaveAsNewTheme(self
):
759 newThemeName
=self
.GetNewThemeName('New Theme Name:')
761 self
.CreateNewTheme(newThemeName
)
763 def CreateNewTheme(self
,newThemeName
):
764 #creates new custom theme based on the previously active theme,
765 #and makes the new theme active
766 if self
.themeIsBuiltin
.get():
768 themeName
=self
.builtinTheme
.get()
771 themeName
=self
.customTheme
.get()
772 newTheme
=idleConf
.GetThemeDict(themeType
,themeName
)
773 #apply any of the old theme's unsaved changes to the new theme
774 if themeName
in self
.changedItems
['highlight'].keys():
775 themeChanges
=self
.changedItems
['highlight'][themeName
]
776 for element
in themeChanges
.keys():
777 newTheme
[element
]=themeChanges
[element
]
779 self
.SaveNewTheme(newThemeName
,newTheme
)
780 #change gui over to the new theme
781 customThemeList
=idleConf
.GetSectionList('user','highlight')
782 customThemeList
.sort()
783 self
.optMenuThemeCustom
.SetMenu(customThemeList
,newThemeName
)
784 self
.themeIsBuiltin
.set(0)
787 def OnListFontButtonRelease(self
,event
):
788 self
.fontName
.set(self
.listFontName
.get(ANCHOR
))
791 def SetFontSample(self
,event
=None):
792 fontName
=self
.fontName
.get()
793 if self
.fontBold
.get():
794 fontWeight
=tkFont
.BOLD
796 fontWeight
=tkFont
.NORMAL
797 self
.editFont
.config(size
=self
.fontSize
.get(),
798 weight
=fontWeight
,family
=fontName
)
800 def SetHighlightTarget(self
):
801 if self
.highlightTarget
.get()=='Cursor': #bg not possible
802 self
.radioFg
.config(state
=DISABLED
)
803 self
.radioBg
.config(state
=DISABLED
)
805 else: #both fg and bg can be set
806 self
.radioFg
.config(state
=NORMAL
)
807 self
.radioBg
.config(state
=NORMAL
)
809 self
.SetColourSample()
811 def SetColourSampleBinding(self
,*args
):
812 self
.SetColourSample()
814 def SetColourSample(self
):
815 #set the colour smaple area
816 tag
=self
.themeElements
[self
.highlightTarget
.get()][0]
817 if self
.fgHilite
.get(): plane
='foreground'
818 else: plane
='background'
819 colour
=self
.textHighlightSample
.tag_cget(tag
,plane
)
820 self
.frameColourSet
.config(bg
=colour
)
822 def PaintThemeSample(self
):
823 if self
.themeIsBuiltin
.get(): #a default theme
824 theme
=self
.builtinTheme
.get()
826 theme
=self
.customTheme
.get()
827 for elementTitle
in self
.themeElements
.keys():
828 element
=self
.themeElements
[elementTitle
][0]
829 colours
=idleConf
.GetHighlight(theme
,element
)
830 if element
=='cursor': #cursor sample needs special painting
831 colours
['background']=idleConf
.GetHighlight(theme
,
833 #handle any unsaved changes to this theme
834 if theme
in self
.changedItems
['highlight'].keys():
835 themeDict
=self
.changedItems
['highlight'][theme
]
836 if themeDict
.has_key(element
+'-foreground'):
837 colours
['foreground']=themeDict
[element
+'-foreground']
838 if themeDict
.has_key(element
+'-background'):
839 colours
['background']=themeDict
[element
+'-background']
840 apply(self
.textHighlightSample
.tag_config
,(element
,),colours
)
841 self
.SetColourSample()
843 def OnCheckUserHelpBrowser(self
):
844 if self
.userHelpBrowser
.get():
845 self
.entryHelpBrowser
.config(state
=NORMAL
)
847 self
.entryHelpBrowser
.config(state
=DISABLED
)
849 def HelpSourceSelected(self
,event
):
850 self
.SetHelpListButtonStates()
852 def SetHelpListButtonStates(self
):
853 if self
.listHelp
.size()<1: #no entries in list
854 self
.buttonHelpListEdit
.config(state
=DISABLED
)
855 self
.buttonHelpListRemove
.config(state
=DISABLED
)
856 else: #there are some entries
857 if self
.listHelp
.curselection(): #there currently is a selection
858 self
.buttonHelpListEdit
.config(state
=NORMAL
)
859 self
.buttonHelpListRemove
.config(state
=NORMAL
)
860 else: #there currently is not a selection
861 self
.buttonHelpListEdit
.config(state
=DISABLED
)
862 self
.buttonHelpListRemove
.config(state
=DISABLED
)
864 def HelpListItemAdd(self
):
865 helpSource
=GetHelpSourceDialog(self
,'New Help Source').result
867 self
.userHelpList
.append( (helpSource
[0],helpSource
[1]) )
868 self
.listHelp
.insert(END
,helpSource
[0]+' '+helpSource
[1])
869 self
.UpdateUserHelpChangedItems()
870 self
.SetHelpListButtonStates()
872 def HelpListItemEdit(self
):
873 itemIndex
=self
.listHelp
.index(ANCHOR
)
874 helpSource
=self
.userHelpList
[itemIndex
]
875 newHelpSource
=GetHelpSourceDialog(self
,'Edit Help Source',
876 menuItem
=helpSource
[0],filePath
=helpSource
[1]).result
877 if (not newHelpSource
) or (newHelpSource
==helpSource
):
879 self
.userHelpList
[itemIndex
]=newHelpSource
880 self
.listHelp
.delete(itemIndex
)
881 self
.listHelp
.insert(itemIndex
,newHelpSource
[0]+' '+newHelpSource
[1])
882 self
.UpdateUserHelpChangedItems()
883 self
.SetHelpListButtonStates()
885 def HelpListItemRemove(self
):
886 itemIndex
=self
.listHelp
.index(ANCHOR
)
887 del(self
.userHelpList
[itemIndex
])
888 self
.listHelp
.delete(itemIndex
)
889 self
.UpdateUserHelpChangedItems()
890 self
.SetHelpListButtonStates()
892 def UpdateUserHelpChangedItems(self
):
893 #clear and rebuild the HelpFiles secion in self.changedItems
894 if self
.changedItems
['main'].has_key('HelpFiles'):
895 del(self
.changedItems
['main']['HelpFiles'])
896 for num
in range(1,len(self
.userHelpList
)+1):
897 self
.AddChangedItem('main','HelpFiles',str(num
),
898 string
.join(self
.userHelpList
[num
-1],';'))
900 def LoadFontCfg(self
):
901 ##base editor font selection list
902 fonts
=list(tkFont
.families(self
))
905 self
.listFontName
.insert(END
,font
)
906 configuredFont
=idleConf
.GetOption('main','EditorWindow','font',
908 self
.fontName
.set(configuredFont
)
909 if configuredFont
in fonts
:
910 currentFontIndex
=fonts
.index(configuredFont
)
911 self
.listFontName
.see(currentFontIndex
)
912 self
.listFontName
.select_set(currentFontIndex
)
913 self
.listFontName
.select_anchor(currentFontIndex
)
915 fontSize
=idleConf
.GetOption('main','EditorWindow','font-size',
917 self
.optMenuFontSize
.SetMenu(('10','11','12','13','14',
918 '16','18','20','22'),fontSize
)
920 self
.fontBold
.set(idleConf
.GetOption('main','EditorWindow',
921 'font-bold',default
=0,type='bool'))
925 def LoadTabCfg(self
):
926 ##indent type radiobuttons
927 spaceIndent
=idleConf
.GetOption('main','Indent','use-spaces',
928 default
=1,type='bool')
929 self
.indentBySpaces
.set(spaceIndent
)
931 spaceNum
=idleConf
.GetOption('main','Indent','num-spaces',
932 default
=4,type='int')
933 #tabCols=idleConf.GetOption('main','Indent','tab-cols',
934 # default=4,type='int')
935 self
.spaceNum
.set(spaceNum
)
936 #self.tabCols.set(tabCols)
938 def LoadThemeCfg(self
):
939 ##current theme type radiobutton
940 self
.themeIsBuiltin
.set(idleConf
.GetOption('main','Theme','default',
941 type='bool',default
=1))
942 ##currently set theme
943 currentOption
=idleConf
.CurrentTheme()
944 ##load available theme option menus
945 if self
.themeIsBuiltin
.get(): #default theme selected
946 itemList
=idleConf
.GetSectionList('default','highlight')
948 self
.optMenuThemeBuiltin
.SetMenu(itemList
,currentOption
)
949 itemList
=idleConf
.GetSectionList('user','highlight')
952 self
.radioThemeCustom
.config(state
=DISABLED
)
953 self
.customTheme
.set('- no custom themes -')
955 self
.optMenuThemeCustom
.SetMenu(itemList
,itemList
[0])
956 else: #user theme selected
957 itemList
=idleConf
.GetSectionList('user','highlight')
959 self
.optMenuThemeCustom
.SetMenu(itemList
,currentOption
)
960 itemList
=idleConf
.GetSectionList('default','highlight')
962 self
.optMenuThemeBuiltin
.SetMenu(itemList
,itemList
[0])
964 ##load theme element option menu
965 themeNames
=self
.themeElements
.keys()
966 themeNames
.sort(self
.__ThemeNameIndexCompare
)
967 self
.optMenuHighlightTarget
.SetMenu(themeNames
,themeNames
[0])
968 self
.PaintThemeSample()
969 self
.SetHighlightTarget()
971 def __ThemeNameIndexCompare(self
,a
,b
):
972 if self
.themeElements
[a
][1]<self
.themeElements
[b
][1]: return -1
973 elif self
.themeElements
[a
][1]==self
.themeElements
[b
][1]: return 0
976 def LoadKeyCfg(self
):
977 ##current keys type radiobutton
978 self
.keysAreBuiltin
.set(idleConf
.GetOption('main','Keys','default',
979 type='bool',default
=1))
981 currentOption
=idleConf
.CurrentKeys()
982 ##load available keyset option menus
983 if self
.keysAreBuiltin
.get(): #default theme selected
984 itemList
=idleConf
.GetSectionList('default','keys')
986 self
.optMenuKeysBuiltin
.SetMenu(itemList
,currentOption
)
987 itemList
=idleConf
.GetSectionList('user','keys')
990 self
.radioKeysCustom
.config(state
=DISABLED
)
991 self
.customKeys
.set('- no custom keys -')
993 self
.optMenuKeysCustom
.SetMenu(itemList
,itemList
[0])
994 else: #user key set selected
995 itemList
=idleConf
.GetSectionList('user','keys')
997 self
.optMenuKeysCustom
.SetMenu(itemList
,currentOption
)
998 itemList
=idleConf
.GetSectionList('default','keys')
1000 self
.optMenuKeysBuiltin
.SetMenu(itemList
,itemList
[0])
1002 ##load keyset element list
1003 keySetName
=idleConf
.CurrentKeys()
1004 self
.LoadKeysList(keySetName
)
1006 def LoadGeneralCfg(self
):
1008 self
.startupEdit
.set(idleConf
.GetOption('main','General',
1009 'editor-on-startup',default
=1,type='bool'))
1010 #initial window size
1011 self
.winWidth
.set(idleConf
.GetOption('main','EditorWindow','width'))
1012 self
.winHeight
.set(idleConf
.GetOption('main','EditorWindow','height'))
1014 self
.userHelpList
=idleConf
.GetExtraHelpSourceList('user')
1015 for helpItem
in self
.userHelpList
:
1016 self
.listHelp
.insert(END
,helpItem
[0]+' '+helpItem
[1])
1017 self
.SetHelpListButtonStates()
1018 #self.userHelpBrowser.set(idleConf.GetOption('main','General',
1019 # 'user-help-browser',default=0,type='bool'))
1020 #self.helpBrowser.set(idleConf.GetOption('main','General',
1021 # 'user-help-browser-command',default=''))
1022 #self.OnCheckUserHelpBrowser()
1024 def LoadConfigs(self
):
1026 load configuration from default and user config files and populate
1027 the widgets on the config dialog pages.
1029 ### fonts / tabs page
1032 ### highlighting page
1037 self
.LoadGeneralCfg()
1039 def SaveNewKeySet(self
,keySetName
,keySet
):
1041 save a newly created core key set.
1042 keySetName - string, the name of the new key set
1043 keySet - dictionary containing the new key set
1045 if not idleConf
.userCfg
['keys'].has_section(keySetName
):
1046 idleConf
.userCfg
['keys'].add_section(keySetName
)
1047 for event
in keySet
.keys():
1049 idleConf
.userCfg
['keys'].SetOption(keySetName
,event
,value
)
1051 def SaveNewTheme(self
,themeName
,theme
):
1053 save a newly created theme.
1054 themeName - string, the name of the new theme
1055 theme - dictionary containing the new theme
1057 if not idleConf
.userCfg
['highlight'].has_section(themeName
):
1058 idleConf
.userCfg
['highlight'].add_section(themeName
)
1059 for element
in theme
.keys():
1060 value
=theme
[element
]
1061 idleConf
.userCfg
['highlight'].SetOption(themeName
,element
,value
)
1063 def SetUserValue(self
,configType
,section
,item
,value
):
1064 if idleConf
.defaultCfg
[configType
].has_option(section
,item
):
1065 if idleConf
.defaultCfg
[configType
].Get(section
,item
)==value
:
1066 #the setting equals a default setting, remove it from user cfg
1067 return idleConf
.userCfg
[configType
].RemoveOption(section
,item
)
1068 #if we got here set the option
1069 return idleConf
.userCfg
[configType
].SetOption(section
,item
,value
)
1071 def SaveAllChangedConfigs(self
):
1073 save all configuration changes to user config files.
1075 #this section gets completely replaced
1076 idleConf
.userCfg
['main'].remove_section('HelpFiles')
1077 idleConf
.userCfg
['main'].Save()
1078 for configType
in self
.changedItems
.keys():
1080 for section
in self
.changedItems
[configType
].keys():
1081 for item
in self
.changedItems
[configType
][section
].keys():
1082 value
=self
.changedItems
[configType
][section
][item
]
1083 if self
.SetUserValue(configType
,section
,item
,value
):
1085 if cfgTypeHasChanges
:
1086 idleConf
.userCfg
[configType
].Save()
1087 self
.ResetChangedItems() #clear the changed items dict
1089 def ActivateConfigChanges(self
):
1090 #things that need to be done to make
1091 #applied config changes dynamic:
1092 #update editor/shell font and repaint
1093 #dynamically update indentation setttings
1094 #update theme and repaint
1095 #update keybindings and re-bind
1096 #update user help sources menu
1097 winInstances
=self
.parent
.instanceDict
.keys()
1098 for instance
in winInstances
:
1099 instance
.ResetColorizer()
1100 instance
.ResetFont()
1101 instance
.ResetKeybindings()
1102 instance
.ResetExtraHelpMenu()
1112 self
.SaveAllChangedConfigs()
1113 self
.ActivateConfigChanges()
1118 if __name__
== '__main__':
1121 Button(root
,text
='Dialog',
1122 command
=lambda:ConfigDialog(root
,'Settings')).pack()
1123 root
.instanceDict
={}