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