configDialog.py 27.9 KB
Newer Older
1 2 3 4
"""
configuration dialog
"""
from Tkinter import *
Steven M. Gava's avatar
Steven M. Gava committed
5
import tkMessageBox, tkColorChooser, tkFont
6

7
from configHandler import idleConf
8
from dynOptionMenuWidget import DynOptionMenu
9
from tabpage import TabPageSet
10

11 12
class ConfigDialog(Toplevel):
    """
13 14
    configuration dialog for idle
    """ 
15
    def __init__(self,parent,title):
16 17 18 19
        Toplevel.__init__(self, parent)
        self.configure(borderwidth=5)
        self.geometry("+%d+%d" % (parent.winfo_rootx()+20,
                parent.winfo_rooty()+30))
Steven M. Gava's avatar
Steven M. Gava committed
20 21 22 23 24
        #Theme Elements. Each theme element key is it's display name.
        #The first value of the tuple is the sample area tag name.
        #The second value is the display name list sort index. 
        #The third value indicates whether the element can have a foreground 
        #or background colour or both. 
25 26 27 28 29 30 31 32 33 34 35 36
        self.themeElements={'Normal Text':('normal','00'),
            'Python Keywords':('keyword','01'),
            'Python Definitions':('definition','02'),
            'Python Comments':('comment','03'),
            'Python Strings':('string','04'),
            'Selected Text':('hilite','05'),
            'Found Text':('hit','06'),
            'Cursor':('cursor','07'),
            'Error Text':('error','08'),
            'Shell Normal Text':('console','09'),
            'Shell Stdout Text':('stdout','10'),
            'Shell Stderr Text':('stderr','11')}
37 38 39 40 41 42
        self.CreateWidgets()
        self.resizable(height=FALSE,width=FALSE)
        self.transient(parent)
        self.grab_set()
        self.protocol("WM_DELETE_WINDOW", self.Cancel)
        self.parent = parent
43
        self.tabPages.focus_set()
44 45
        #key bindings for this dialog
        self.bind('<Escape>',self.CancelBinding) #dismiss dialog, no save
Steven M. Gava's avatar
Steven M. Gava committed
46
        self.bind('<Alt-a>',self.ApplyBinding) #apply changes, save
47
        self.bind('<F1>',self.HelpBinding) #context help
48
        self.LoadConfigs()
49 50 51 52
        self.wait_window()
        
    def Cancel(self):
        self.destroy()
53

Steven M. Gava's avatar
Steven M. Gava committed
54 55 56 57
    def Ok(self):
        pass

    def Apply(self):
58
        pass
59

60
    def Help(self):
61
        pass
62

63 64 65
    def CancelBinding(self,event):
        self.Cancel()
    
Steven M. Gava's avatar
Steven M. Gava committed
66 67 68 69 70
    def OkBinding(self,event):
        self.Ok()
    
    def ApplyBinding(self,event):
        self.Apply()
71
    
72 73
    def HelpBinding(self,event):
        self.Help()
74
    
75
    def SetThemeType(self):
Steven M. Gava's avatar
Steven M. Gava committed
76
        if self.themeIsBuiltin.get():
77 78
            self.optMenuThemeBuiltin.config(state=NORMAL)
            self.optMenuThemeCustom.config(state=DISABLED)
79
            self.buttonDeleteCustomTheme.config(state=DISABLED)
Steven M. Gava's avatar
Steven M. Gava committed
80
        else:
81 82
            self.optMenuThemeBuiltin.config(state=DISABLED)
            self.optMenuThemeCustom.config(state=NORMAL)
83 84 85
            self.buttonDeleteCustomTheme.config(state=NORMAL)

    def SetKeysType(self):
Steven M. Gava's avatar
Steven M. Gava committed
86
        if self.keysAreDefault.get():
87 88 89
            self.optMenuKeysBuiltin.config(state=NORMAL)
            self.optMenuKeysCustom.config(state=DISABLED)
            self.buttonDeleteCustomKeys.config(state=DISABLED)
Steven M. Gava's avatar
Steven M. Gava committed
90
        else:
91 92 93
            self.optMenuKeysBuiltin.config(state=DISABLED)
            self.optMenuKeysCustom.config(state=NORMAL)
            self.buttonDeleteCustomKeys.config(state=NORMAL)
94
    
95
    def GetColour(self):
Steven M. Gava's avatar
Steven M. Gava committed
96
        target=self.highlightTarget.get()
97
        rgbTuplet, colourString = tkColorChooser.askcolor(parent=self,
Steven M. Gava's avatar
Steven M. Gava committed
98 99
            title='Pick new colour for : '+target,
            initialcolor=self.frameColourSet.cget('bg'))
100
        if colourString: #user didn't cancel
Steven M. Gava's avatar
Steven M. Gava committed
101 102 103 104 105 106
            self.frameColourSet.config(bg=colourString)#set sample
            if self.fgHilite.get(): plane='foreground'
            else: plane='background'
            apply(self.textHighlightSample.tag_config,
                (self.themeElements[target][0],),{plane:colourString})
    
107 108 109 110 111
    def SetFontSampleBinding(self,event):
        self.SetFontSample()
        
    def SetFontSample(self):
        self.editFont.config(size=self.fontSize.get(),weight=NORMAL,
Steven M. Gava's avatar
Steven M. Gava committed
112
            family=self.listFontName.get(self.listFontName.curselection()[0]))
113

114
    def SetHighlightTargetBinding(self,*args):
Steven M. Gava's avatar
Steven M. Gava committed
115
        self.SetHighlightTarget()
116
        
Steven M. Gava's avatar
Steven M. Gava committed
117
    def SetHighlightTarget(self):
118
        if self.highlightTarget.get()=='Cursor': #bg not possible
Steven M. Gava's avatar
Steven M. Gava committed
119 120
            self.radioFg.config(state=DISABLED)
            self.radioBg.config(state=DISABLED)
121 122
            self.fgHilite.set(1)
        else: #both fg and bg can be set
123 124
            self.radioFg.config(state=NORMAL)
            self.radioBg.config(state=NORMAL)
Steven M. Gava's avatar
Steven M. Gava committed
125
            self.fgHilite.set(1)
126 127 128 129 130 131 132 133 134 135 136 137
        self.SetColourSample()
    
    def SetColourSampleBinding(self,*args):
        self.SetColourSample()
        
    def SetColourSample(self):
        #set the colour smaple area
        tag=self.themeElements[self.highlightTarget.get()][0]
        if self.fgHilite.get(): plane='foreground'
        else: plane='background'
        colour=self.textHighlightSample.tag_cget(tag,plane)
        self.frameColourSet.config(bg=colour)
Steven M. Gava's avatar
Steven M. Gava committed
138
    
139
    def CreateWidgets(self):
140 141
        self.tabPages = TabPageSet(self,
                pageNames=['Fonts/Tabs','Highlighting','Keys','General'])
142
        self.tabPages.ChangePage()#activates default (first) page
143 144
        frameActionButtons = Frame(self)
        #action buttons
145 146
        self.buttonHelp = Button(frameActionButtons,text='Help',
                command=self.Help,takefocus=FALSE)
Steven M. Gava's avatar
Steven M. Gava committed
147 148 149 150
        self.buttonOk = Button(frameActionButtons,text='Ok',
                command=self.Ok,takefocus=FALSE)
        self.buttonApply = Button(frameActionButtons,text='Apply',
                command=self.Apply,underline=0,takefocus=FALSE)
151 152
        self.buttonCancel = Button(frameActionButtons,text='Cancel',
                command=self.Cancel,takefocus=FALSE)
153 154 155 156
        self.CreatePageFontTab()
        self.CreatePageHighlight()
        self.CreatePageKeys()
        self.CreatePageGeneral()
Steven M. Gava's avatar
Steven M. Gava committed
157 158 159
        self.buttonHelp.pack(side=RIGHT,padx=5,pady=5)
        self.buttonOk.pack(side=LEFT,padx=5,pady=5)
        self.buttonApply.pack(side=LEFT,padx=5,pady=5)
160 161
        self.buttonCancel.pack(side=LEFT,padx=5,pady=5)
        frameActionButtons.pack(side=BOTTOM)
162 163
        self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH)

164
        
165
    def CreatePageFontTab(self):
166
        #tkVars
167 168 169 170 171
        self.fontSize=StringVar(self)
        self.fontBold=StringVar(self)
        self.spaceNum=IntVar(self)
        self.tabCols=IntVar(self)
        self.indentType=IntVar(self) 
172
        self.editFont=tkFont.Font(self,('courier',12,'normal'))
173 174
        ##widget creation
        #body frame
175
        frame=self.tabPages.pages['Fonts/Tabs']['page']
176 177 178 179 180 181
        #body section frames
        frameFont=Frame(frame,borderwidth=2,relief=GROOVE)
        frameIndent=Frame(frame,borderwidth=2,relief=GROOVE)
        #frameFont
        labelFontTitle=Label(frameFont,text='Set Base Editor Font')
        frameFontName=Frame(frameFont)
182
        frameFontParam=Frame(frameFont)
183
        labelFontNameTitle=Label(frameFontName,justify=LEFT,
Steven M. Gava's avatar
Steven M. Gava committed
184 185 186
                text='Font :')
        self.listFontName=Listbox(frameFontName,height=5,takefocus=FALSE,
                exportselection=FALSE)
187
        self.listFontName.bind('<<ListboxSelect>>',self.SetFontSampleBinding)
Steven M. Gava's avatar
Steven M. Gava committed
188 189 190
        scrollFont=Scrollbar(frameFontName)
        scrollFont.config(command=self.listFontName.yview)
        self.listFontName.config(yscrollcommand=scrollFont.set)
191 192
        labelFontSizeTitle=Label(frameFontParam,text='Size :')
        self.optMenuFontSize=DynOptionMenu(frameFontParam,self.fontSize,None,
193
            command=self.SetFontSampleBinding)
194 195
        checkFontBold=Checkbutton(frameFontParam,variable=self.fontBold,
            onvalue='Bold',offvalue='',text='Bold')
196 197 198
        frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1)
        self.labelFontSample=Label(frameFontSample,
                text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]',
199
                justify=LEFT,font=self.editFont)
200 201 202 203 204 205 206
        #frameIndent
        labelIndentTitle=Label(frameIndent,text='Set Indentation Defaults')
        frameIndentType=Frame(frameIndent)
        frameIndentSize=Frame(frameIndent)
        labelIndentTypeTitle=Label(frameIndentType,
                text='Choose indentation type :')
        radioUseSpaces=Radiobutton(frameIndentType,variable=self.indentType,
207
            value=1,text='Tab key inserts spaces')
208
        radioUseTabs=Radiobutton(frameIndentType,variable=self.indentType,
209
            value=0,text='Tab key inserts tabs')
210 211 212 213 214 215 216 217 218 219 220 221
        labelIndentSizeTitle=Label(frameIndentSize,
                text='Choose indentation size :')
        labelSpaceNumTitle=Label(frameIndentSize,justify=LEFT,
                text='when tab key inserts spaces,\nspaces per tab')
        self.scaleSpaceNum=Scale(frameIndentSize,variable=self.spaceNum,
                orient='horizontal',tickinterval=2,from_=2,to=8)
        labeltabColsTitle=Label(frameIndentSize,justify=LEFT,
                text='when tab key inserts tabs,\ncolumns per tab')
        self.scaleTabCols=Scale(frameIndentSize,variable=self.tabCols,
                orient='horizontal',tickinterval=2,from_=2,to=8)
        #widget packing
        #body
Steven M. Gava's avatar
Steven M. Gava committed
222 223
        frameFont.pack(side=LEFT,padx=5,pady=10,expand=TRUE,fill=BOTH)
        frameIndent.pack(side=LEFT,padx=5,pady=10,fill=Y)
224 225
        #frameFont
        labelFontTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
226 227
        frameFontName.pack(side=TOP,padx=5,pady=5,fill=X)
        frameFontParam.pack(side=TOP,padx=5,pady=5,fill=X)
228
        labelFontNameTitle.pack(side=TOP,anchor=W)
229
        self.listFontName.pack(side=LEFT,expand=TRUE,fill=X)
Steven M. Gava's avatar
Steven M. Gava committed
230
        scrollFont.pack(side=LEFT,fill=Y)
231 232 233
        labelFontSizeTitle.pack(side=LEFT,anchor=W)
        self.optMenuFontSize.pack(side=LEFT,anchor=W)
        checkFontBold.pack(side=LEFT,anchor=W,padx=20)
234
        frameFontSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
Steven M. Gava's avatar
Steven M. Gava committed
235
        self.labelFontSample.pack(expand=TRUE,fill=BOTH)
236 237 238 239 240 241 242 243 244 245 246 247
        #frameIndent
        labelIndentTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
        frameIndentType.pack(side=TOP,padx=5,fill=X)
        frameIndentSize.pack(side=TOP,padx=5,pady=5,fill=BOTH)
        labelIndentTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
        radioUseSpaces.pack(side=TOP,anchor=W,padx=5)
        radioUseTabs.pack(side=TOP,anchor=W,padx=5)
        labelIndentSizeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
        labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5)
        self.scaleSpaceNum.pack(side=TOP,padx=5,fill=X)
        labeltabColsTitle.pack(side=TOP,anchor=W,padx=5)
        self.scaleTabCols.pack(side=TOP,padx=5,fill=X)
248 249 250
        return frame

    def CreatePageHighlight(self):
251 252 253 254 255 256 257
        self.builtinTheme=StringVar(self)
        self.customTheme=StringVar(self)
        self.fgHilite=IntVar(self)
        self.colour=StringVar(self)
        self.fontName=StringVar(self)
        self.themeIsBuiltin=IntVar(self) 
        self.highlightTarget=StringVar(self)
258
        self.highlightTarget.trace_variable('w',self.SetHighlightTargetBinding)
259 260
        ##widget creation
        #body frame
261
        frame=self.tabPages.pages['Highlighting']['page']
262 263 264 265
        #body section frames
        frameCustom=Frame(frame,borderwidth=2,relief=GROOVE)
        frameTheme=Frame(frame,borderwidth=2,relief=GROOVE)
        #frameCustom
266 267 268 269 270 271
        self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1,
            font=('courier',12,''),cursor='hand2',width=10,height=10,
            takefocus=FALSE,highlightthickness=0)
        text=self.textHighlightSample
        text.bind('<Double-Button-1>',lambda e: 'break')
        text.bind('<B1-Motion>',lambda e: 'break')
Steven M. Gava's avatar
Steven M. Gava committed
272 273 274 275
        textAndTags=(('#you can click in here','comment'),('\n','normal'),
            ('#to choose items','comment'),('\n','normal'),('def','keyword'),
            (' ','normal'),('func','definition'),('(param):','normal'),
            ('\n  ','normal'),('"""string"""','string'),('\n  var0 = ','normal'),
Steven M. Gava's avatar
Steven M. Gava committed
276 277
            ("'string'",'string'),('\n  var1 = ','normal'),("'selected'",'hilite'),
            ('\n  var2 = ','normal'),("'found'",'hit'),('\n\n','normal'),
Steven M. Gava's avatar
Steven M. Gava committed
278
            (' error ','error'),(' ','normal'),('cursor |','cursor'),
Steven M. Gava's avatar
Steven M. Gava committed
279 280
            ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'),
            (' ','normal'),('stderr','stderr'),('\n','normal'))
Steven M. Gava's avatar
Steven M. Gava committed
281 282 283 284 285 286
        for txTa in textAndTags:
            text.insert(END,txTa[0],txTa[1])
        for element in self.themeElements.keys(): 
            text.tag_bind(self.themeElements[element][0],'<ButtonPress-1>',
                lambda event,elem=element: event.widget.winfo_toplevel()
                .highlightTarget.set(elem))
287 288
        text.config(state=DISABLED)
        self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1)
Steven M. Gava's avatar
Steven M. Gava committed
289
        frameFgBg=Frame(frameCustom)
290
        labelCustomTitle=Label(frameCustom,text='Set Custom Highlighting')
291
        buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :',
Steven M. Gava's avatar
Steven M. Gava committed
292
            command=self.GetColour,highlightthickness=0)
293
        self.optMenuHighlightTarget=DynOptionMenu(self.frameColourSet,
Steven M. Gava's avatar
Steven M. Gava committed
294
            self.highlightTarget,None,highlightthickness=0)#,command=self.SetHighlightTargetBinding
Steven M. Gava's avatar
Steven M. Gava committed
295
        self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite,
296
            value=1,text='Foreground',command=self.SetColourSampleBinding)
Steven M. Gava's avatar
Steven M. Gava committed
297
        self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite,
298
            value=0,text='Background',command=self.SetColourSampleBinding)
Steven M. Gava's avatar
Steven M. Gava committed
299
        self.fgHilite.set(1)
300
        buttonSaveCustomTheme=Button(frameCustom, 
301 302 303 304
            text='Save as a Custom Theme')
        #frameTheme
        labelThemeTitle=Label(frameTheme,text='Select a Highlighting Theme')
        labelTypeTitle=Label(frameTheme,text='Select : ')
Steven M. Gava's avatar
Steven M. Gava committed
305 306 307 308
        self.radioThemeBuiltin=Radiobutton(frameTheme,variable=self.themeIsBuiltin,
            value=1,command=self.SetThemeType,text='a Built-in Theme')
        self.radioThemeCustom=Radiobutton(frameTheme,variable=self.themeIsBuiltin,
            value=0,command=self.SetThemeType,text='a Custom Theme')
309
        self.optMenuThemeBuiltin=DynOptionMenu(frameTheme,
Steven M. Gava's avatar
Steven M. Gava committed
310
            self.builtinTheme,None,command=None)
311
        self.optMenuThemeCustom=DynOptionMenu(frameTheme,
Steven M. Gava's avatar
Steven M. Gava committed
312
            self.customTheme,None,command=None)
313
        self.buttonDeleteCustomTheme=Button(frameTheme,text='Delete Custom Theme')
314 315
        ##widget packing
        #body
316 317
        frameCustom.pack(side=LEFT,padx=5,pady=10,expand=TRUE,fill=BOTH)
        frameTheme.pack(side=LEFT,padx=5,pady=10,fill=Y)
318 319
        #frameCustom
        labelCustomTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
320
        self.frameColourSet.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=X)
Steven M. Gava's avatar
Steven M. Gava committed
321
        frameFgBg.pack(side=TOP,padx=5,pady=0)
322 323
        self.textHighlightSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,
            fill=BOTH)
Steven M. Gava's avatar
Steven M. Gava committed
324 325
        buttonSetColour.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=4)
        self.optMenuHighlightTarget.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=3)
Steven M. Gava's avatar
Steven M. Gava committed
326 327
        self.radioFg.pack(side=LEFT,anchor=E)
        self.radioBg.pack(side=RIGHT,anchor=W)
328
        buttonSaveCustomTheme.pack(side=BOTTOM,fill=X,padx=5,pady=5)        
329 330 331
        #frameTheme
        labelThemeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
        labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
332 333
        self.radioThemeBuiltin.pack(side=TOP,anchor=W,padx=5)
        self.radioThemeCustom.pack(side=TOP,anchor=W,padx=5,pady=2)
334 335
        self.optMenuThemeBuiltin.pack(side=TOP,fill=X,padx=5,pady=5)
        self.optMenuThemeCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5)
336
        self.buttonDeleteCustomTheme.pack(side=TOP,fill=X,padx=5,pady=5)
337 338 339
        return frame

    def CreatePageKeys(self):
340
        #tkVars
341 342 343 344 345 346 347 348
        self.bindingTarget=StringVar(self)
        self.builtinKeys=StringVar(self)
        self.customKeys=StringVar(self)
        self.keyChars=StringVar(self)
        self.keyCtrl=StringVar(self)
        self.keyAlt=StringVar(self)
        self.keyShift=StringVar(self)
        self.keysAreDefault=IntVar(self) 
349 350
        ##widget creation
        #body frame
351
        frame=self.tabPages.pages['Keys']['page']
352 353 354 355 356 357 358 359 360 361
        #body section frames
        frameCustom=Frame(frame,borderwidth=2,relief=GROOVE)
        frameKeySets=Frame(frame,borderwidth=2,relief=GROOVE)
        #frameCustom
        frameTarget=Frame(frameCustom)
        frameSet=Frame(frameCustom)
        labelCustomTitle=Label(frameCustom,text='Set Custom Key Bindings')
        labelTargetTitle=Label(frameTarget,text='Action')
        scrollTarget=Scrollbar(frameTarget)
        listTarget=Listbox(frameTarget)
Steven M. Gava's avatar
Steven M. Gava committed
362 363
        scrollTarget.config(command=listTarget.yview)
        listTarget.config(yscrollcommand=scrollTarget.set)
364 365 366 367 368 369 370 371 372
        labelKeyBindTitle=Label(frameSet,text='Binding')
        labelModifierTitle=Label(frameSet,text='Modifier:')
        checkCtrl=Checkbutton(frameSet,text='Ctrl')
        checkAlt=Checkbutton(frameSet,text='Alt')
        checkShift=Checkbutton(frameSet,text='Shift')
        labelKeyEntryTitle=Label(frameSet,text='Key:')        
        entryKey=Entry(frameSet,width=4)
        buttonSaveCustomKeys=Button(frameCustom,text='Save as a Custom Key Set')
        #frameKeySets
373
        labelKeysTitle=Label(frameKeySets,text='Select a Key Set')
374
        labelTypeTitle=Label(frameKeySets,text='Select : ')
Steven M. Gava's avatar
Steven M. Gava committed
375 376 377 378
        self.radioKeysBuiltin=Radiobutton(frameKeySets,variable=self.keysAreDefault,
            value=1,command=self.SetKeysType,text='a Built-in Key Set')
        self.radioKeysCustom=Radiobutton(frameKeySets,variable=self.keysAreDefault,
            value=0,command=self.SetKeysType,text='a Custom Key Set')
379 380 381 382
        self.optMenuKeysBuiltin=DynOptionMenu(frameKeySets,
            self.builtinKeys,None,command=None)
        self.optMenuKeysCustom=DynOptionMenu(frameKeySets,
            self.customKeys,None,command=None)
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
        self.buttonDeleteCustomKeys=Button(frameKeySets,text='Delete Custom Key Set')
        ##widget packing
        #body
        frameCustom.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH)
        frameKeySets.pack(side=LEFT,padx=5,pady=5,fill=Y)
        #frameCustom
        labelCustomTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
        buttonSaveCustomKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5)        
        frameTarget.pack(side=LEFT,padx=5,pady=5,fill=Y)
        frameSet.pack(side=LEFT,padx=5,pady=5,fill=Y)
        labelTargetTitle.pack(side=TOP,anchor=W)
        scrollTarget.pack(side=RIGHT,anchor=W,fill=Y)
        listTarget.pack(side=TOP,anchor=W,expand=TRUE,fill=BOTH)
        labelKeyBindTitle.pack(side=TOP,anchor=W)
        labelModifierTitle.pack(side=TOP,anchor=W,pady=5)
        checkCtrl.pack(side=TOP,anchor=W)
        checkAlt.pack(side=TOP,anchor=W,pady=2)
        checkShift.pack(side=TOP,anchor=W)
        labelKeyEntryTitle.pack(side=TOP,anchor=W,pady=5)
        entryKey.pack(side=TOP,anchor=W)
        #frameKeySets
        labelKeysTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
        labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
406 407
        self.radioKeysBuiltin.pack(side=TOP,anchor=W,padx=5)
        self.radioKeysCustom.pack(side=TOP,anchor=W,padx=5,pady=2)
408 409 410
        self.optMenuKeysBuiltin.pack(side=TOP,fill=X,padx=5,pady=5)
        self.optMenuKeysCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5)
        self.buttonDeleteCustomKeys.pack(side=TOP,fill=X,padx=5,pady=5)
411 412 413
        return frame

    def CreatePageGeneral(self):
414
        #tkVars        
415 416 417 418
        self.runType=IntVar(self)       
        self.winWidth=StringVar(self)       
        self.winHeight=StringVar(self)
        self.extState=IntVar(self)       
419 420
        #widget creation
        #body
421
        frame=self.tabPages.pages['General']['page']
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
        #body section frames        
        frameRun=Frame(frame,borderwidth=2,relief=GROOVE)
        frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE)
        frameExt=Frame(frame,borderwidth=2,relief=GROOVE)
        #frameRun
        labelRunTitle=Label(frameRun,text='Run Preferences')
        labelRunChoiceTitle=Label(frameRun,text='Run code : ')
        radioRunInternal=Radiobutton(frameRun,variable=self.runType,
            value=0,command=self.SetKeysType,text="in IDLE's Process")
        radioRunSeparate=Radiobutton(frameRun,variable=self.runType,
            value=1,command=self.SetKeysType,text='in a Separate Process')
        #frameWinSize
        labelWinSizeTitle=Label(frameWinSize,text='Initial Window Size')
        buttonWinSizeSet=Button(frameWinSize,text='Set to current window size')
        labelWinWidthTitle=Label(frameWinSize,text='Width')
        entryWinWidth=Entry(frameWinSize,textvariable=self.winWidth,
                width=3)
        labelWinHeightTitle=Label(frameWinSize,text='Height')
        entryWinHeight=Entry(frameWinSize,textvariable=self.winHeight,
                width=3)
        #frameExt
        frameExtList=Frame(frameExt)
        frameExtSet=Frame(frameExt)
        labelExtTitle=Label(frameExt,text='Configure IDLE Extensions')
        labelExtListTitle=Label(frameExtList,text='Extension')
        scrollExtList=Scrollbar(frameExtList)
        listExt=Listbox(frameExtList,height=5)
Steven M. Gava's avatar
Steven M. Gava committed
449 450
        scrollExtList.config(command=listExt.yview)
        listExt.config(yscrollcommand=scrollExtList.set)
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
        labelExtSetTitle=Label(frameExtSet,text='Settings')
        radioEnableExt=Radiobutton(frameExtSet,variable=self.extState,
            value=1,text="enable")
        radioDisableExt=Radiobutton(frameExtSet,variable=self.extState,
            value=0,text="disable")
        self.extState.set(1)
        buttonExtConfig=Button(frameExtSet,text='Configure')
        
        #widget packing
        #body
        frameRun.pack(side=TOP,padx=5,pady=5,fill=X)
        frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X)
        frameExt.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
        #frameRun
        labelRunTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
        labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
        radioRunInternal.pack(side=LEFT,anchor=W,padx=5,pady=5)
        radioRunSeparate.pack(side=LEFT,anchor=W,padx=5,pady=5)     
        #frameWinSize
        labelWinSizeTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
        buttonWinSizeSet.pack(side=LEFT,anchor=W,padx=5,pady=5)
        labelWinWidthTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
        entryWinWidth.pack(side=LEFT,anchor=W,padx=5,pady=5)
        labelWinHeightTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
        entryWinHeight.pack(side=LEFT,anchor=W,padx=5,pady=5)
        #frameExt
        labelExtTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
        frameExtSet.pack(side=RIGHT,padx=5,pady=5,fill=Y)
        frameExtList.pack(side=RIGHT,padx=5,pady=5,expand=TRUE,fill=BOTH)
        labelExtListTitle.pack(side=TOP,anchor=W)
        scrollExtList.pack(side=RIGHT,anchor=W,fill=Y)
        listExt.pack(side=LEFT,anchor=E,expand=TRUE,fill=BOTH)
        labelExtSetTitle.pack(side=TOP,anchor=W)
        radioEnableExt.pack(side=TOP,anchor=W)
        radioDisableExt.pack(side=TOP,anchor=W)
        buttonExtConfig.pack(side=TOP,anchor=W,pady=5)

488 489
        return frame

Steven M. Gava's avatar
Steven M. Gava committed
490
    def PaintThemeSample(self):
Steven M. Gava's avatar
Steven M. Gava committed
491
        if self.themeIsBuiltin.get(): #a default theme
Steven M. Gava's avatar
Steven M. Gava committed
492 493 494
            theme=self.builtinTheme.get()
        else: #a user theme
            theme=self.customTheme.get()
Steven M. Gava's avatar
Steven M. Gava committed
495 496
        for element in self.themeElements.keys():
            colours=idleConf.GetHighlight(theme, self.themeElements[element][0])
497 498
            if element=='Cursor': #cursor sample needs special painting
                colours['background']=idleConf.GetHighlight(theme, 
499
                        'normal', fgBg='bg')
Steven M. Gava's avatar
Steven M. Gava committed
500 501
            apply(self.textHighlightSample.tag_config,
                (self.themeElements[element][0],),colours)
502
    
503 504
    def LoadFontCfg(self):
        ##base editor font selection list
505 506 507 508
        fonts=list(tkFont.families(self))
        fonts.sort()
        for font in fonts:
            self.listFontName.insert(END,font)
509
        configuredFont=idleConf.GetOption('main','EditorWindow','font',
510 511 512 513 514 515
                default='courier')
        if configuredFont in fonts:
            currentFontIndex=fonts.index(configuredFont)
            self.listFontName.see(currentFontIndex)
            self.listFontName.select_set(currentFontIndex)
        ##font size dropdown
516 517 518
        fontSize=idleConf.GetOption('main','EditorWindow','font-size',default='12')
        self.optMenuFontSize.SetMenu(('10','11','12','13','14',
                '16','18','20','22'),fontSize )
519 520 521 522 523
        ##font sample 
        self.SetFontSample()
    
    def LoadTabCfg(self):
        ##indent type radibuttons
524
        spaceIndent=idleConf.GetOption('main','Indent','use-spaces',
525 526 527
                default=1,type='bool')
        self.indentType.set(spaceIndent)
        ##indent sizes
528
        spaceNum=idleConf.GetOption('main','Indent','num-spaces',
529
                default=4,type='int')
530
        tabCols=idleConf.GetOption('main','Indent','tab-cols',
531 532 533
                default=4,type='int')
        self.spaceNum.set(spaceNum)
        self.tabCols.set(tabCols)
534
    
Steven M. Gava's avatar
Steven M. Gava committed
535
    def LoadThemeCfg(self):
536
        ##current theme type radiobutton
Steven M. Gava's avatar
Steven M. Gava committed
537 538
        self.themeIsBuiltin.set(idleConf.GetOption('main','Theme','default',
            type='int',default=1))
539
        ##currently set theme
540
        currentOption=idleConf.CurrentTheme()
Steven M. Gava's avatar
Steven M. Gava committed
541
        ##load available theme option menus
Steven M. Gava's avatar
Steven M. Gava committed
542
        if self.themeIsBuiltin.get(): #default theme selected
543 544 545 546 547 548 549 550
            itemList=idleConf.GetSectionList('default','highlight')
            self.optMenuThemeBuiltin.SetMenu(itemList,currentOption)
            itemList=idleConf.GetSectionList('user','highlight')
            if not itemList:
                self.radioThemeCustom.config(state=DISABLED)
                self.customTheme.set('- no custom themes -')    
            else:
                self.optMenuThemeCustom.SetMenu(itemList,itemList[0])
Steven M. Gava's avatar
Steven M. Gava committed
551
        else: #user theme selected
552 553 554 555
            itemList=idleConf.GetSectionList('user','highlight')
            self.optMenuThemeCustom.SetMenu(itemList,currentOption)
            itemList=idleConf.GetSectionList('default','highlight')
            self.optMenuThemeBuiltin.SetMenu(itemList,itemList[0])
Steven M. Gava's avatar
Steven M. Gava committed
556 557
        self.SetThemeType()
        ##load theme element option menu
Steven M. Gava's avatar
Steven M. Gava committed
558 559 560 561
        themeNames=self.themeElements.keys()
        themeNames.sort(self.__ThemeNameIndexCompare)
        self.optMenuHighlightTarget.SetMenu(themeNames,themeNames[0])   
        self.PaintThemeSample()
562
        self.SetHighlightTarget()
Steven M. Gava's avatar
Steven M. Gava committed
563 564 565 566 567
    
    def __ThemeNameIndexCompare(self,a,b):
        if self.themeElements[a][1]<self.themeElements[b][1]: return -1
        elif self.themeElements[a][1]==self.themeElements[b][1]: return 0
        else: return 1
568
    
Steven M. Gava's avatar
Steven M. Gava committed
569
    def LoadKeyCfg(self):
570
        ##current keys type radiobutton
Steven M. Gava's avatar
Steven M. Gava committed
571 572
        self.keysAreDefault.set(idleConf.GetOption('main','Keys','default',
            type='int',default=1))
573
        ##currently set keys
574
        currentOption=idleConf.CurrentKeys()
Steven M. Gava's avatar
Steven M. Gava committed
575
        ##load available keyset option menus
Steven M. Gava's avatar
Steven M. Gava committed
576
        if self.keysAreDefault.get(): #default theme selected
577 578 579 580 581 582 583 584
            itemList=idleConf.GetSectionList('default','keys')
            self.optMenuKeysBuiltin.SetMenu(itemList,currentOption)
            itemList=idleConf.GetSectionList('user','keys')
            if not itemList:
                self.radioKeysCustom.config(state=DISABLED)    
                self.customKeys.set('- no custom keys -')    
            else:
                self.optMenuKeysCustom.SetMenu(itemList,itemList[0])
Steven M. Gava's avatar
Steven M. Gava committed
585
        else: #user theme selected
586 587 588 589 590
            itemList=idleConf.GetSectionList('user','keys')
            self.optMenuKeysCustom.SetMenu(itemList,currentOption)
            itemList=idleConf.GetSectionList('default','keys')
            self.optMenuKeysBuiltin.SetMenu(itemList,itemList[0])
        self.SetKeysType()   
Steven M. Gava's avatar
Steven M. Gava committed
591
        ##load keyset element option menu   
592
        
593 594 595 596 597 598 599 600 601
    def LoadConfigs(self):
        """
        load configuration from default and user config files and populate
        the widgets on the config dialog pages.
        """
        ### fonts / tabs page
        self.LoadFontCfg()        
        self.LoadTabCfg()        
        ### highlighting page
Steven M. Gava's avatar
Steven M. Gava committed
602
        self.LoadThemeCfg()
603
        ### keys page
Steven M. Gava's avatar
Steven M. Gava committed
604
        self.LoadKeyCfg()
605 606 607
        ### help page
        ### general page
        
608
    def SaveConfigs(self):
609 610 611
        """
        save configuration changes to user config files.
        """
612 613
        pass

614
if __name__ == '__main__':
615 616 617
    #test the dialog
    root=Tk()
    Button(root,text='Dialog',
618
            command=lambda:ConfigDialog(root,'Settings')).pack()
619
    root.mainloop()