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