blob: f00db39d8ffeb350f805d3b39ee3e8a47fada3c5 [file] [log] [blame]
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001"""IDLE Configuration Dialog: support user customization of IDLE by GUI
2
3Customize font faces, sizes, and colorization attributes. Set indentation
4defaults. Customize keybindings. Colorization and keybindings can be
5saved as user defined sets. Select startup options including shell/editor
6and default window size. Define additional help sources.
7
8Note that tab width in IDLE is currently fixed at eight due to Tk issues.
Kurt B. Kaiseracdef852005-01-31 03:34:26 +00009Refer to comments in EditorWindow autoindent code for details.
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +000010
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000011"""
Georg Brandl14fc4272008-05-17 18:39:55 +000012from tkinter import *
13import tkinter.messagebox as tkMessageBox
14import tkinter.colorchooser as tkColorChooser
15import tkinter.font as tkFont
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000016
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000017from idlelib.configHandler import idleConf
18from idlelib.dynOptionMenuWidget import DynOptionMenu
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000019from idlelib.keybindingDialog import GetKeysDialog
20from idlelib.configSectionNameDialog import GetCfgSectionNameDialog
21from idlelib.configHelpSourceEdit import GetHelpSourceDialog
Terry Jan Reedya9421fb2014-10-22 20:15:18 -040022from idlelib.tabbedpages import TabbedPageSet
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -040023from idlelib.textView import view_text
Ronald Oussoren9e350042009-02-12 16:02:11 +000024from idlelib import macosxSupport
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -040025
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000026class ConfigDialog(Toplevel):
Kurt B. Kaiseracdef852005-01-31 03:34:26 +000027
Terry Jan Reedycd567362014-10-17 01:31:35 -040028 def __init__(self, parent, title='', _htest=False, _utest=False):
Terry Jan Reedy2e8234a2014-05-29 01:46:26 -040029 """
30 _htest - bool, change box location when running htest
Terry Jan Reedycfa89502014-07-14 23:07:32 -040031 _utest - bool, don't wait_window when running unittest
Terry Jan Reedy2e8234a2014-05-29 01:46:26 -040032 """
Steven M. Gavad721c482001-07-31 10:46:53 +000033 Toplevel.__init__(self, parent)
Terry Jan Reedy22405332014-07-30 19:24:32 -040034 self.parent = parent
Terry Jan Reedy4036d872014-08-03 23:02:58 -040035 if _htest:
36 parent.instance_dict = {}
Guido van Rossum8ce8a782007-11-01 19:42:39 +000037 self.wm_withdraw()
38
Steven M. Gavad721c482001-07-31 10:46:53 +000039 self.configure(borderwidth=5)
Terry Jan Reedycd567362014-10-17 01:31:35 -040040 self.title(title or 'IDLE Preferences')
Terry Jan Reedy4036d872014-08-03 23:02:58 -040041 self.geometry(
42 "+%d+%d" % (parent.winfo_rootx() + 20,
43 parent.winfo_rooty() + (30 if not _htest else 150)))
Georg Brandl7eb4b7d2005-07-22 21:49:32 +000044 #Theme Elements. Each theme element key is its display name.
Steven M. Gava9dd16b32001-11-03 14:54:25 +000045 #The first value of the tuple is the sample area tag name.
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000046 #The second value is the display name list sort index.
Terry Jan Reedy4036d872014-08-03 23:02:58 -040047 self.themeElements={
Terry Jan Reedya8aa4d52015-10-02 22:12:17 -040048 'Normal Text': ('normal', '00'),
49 'Python Keywords': ('keyword', '01'),
50 'Python Definitions': ('definition', '02'),
51 'Python Builtins': ('builtin', '03'),
52 'Python Comments': ('comment', '04'),
53 'Python Strings': ('string', '05'),
54 'Selected Text': ('hilite', '06'),
55 'Found Text': ('hit', '07'),
56 'Cursor': ('cursor', '08'),
57 'Editor Breakpoint': ('break', '09'),
58 'Shell Normal Text': ('console', '10'),
59 'Shell Error Text': ('error', '11'),
60 'Shell Stdout Text': ('stdout', '12'),
61 'Shell Stderr Text': ('stderr', '13'),
Kurt B. Kaiser73360a32004-03-08 18:15:31 +000062 }
Steven M. Gavaa498af22002-02-01 01:33:36 +000063 self.ResetChangedItems() #load initial values in changed items dict
Steven M. Gavad721c482001-07-31 10:46:53 +000064 self.CreateWidgets()
Terry Jan Reedy4036d872014-08-03 23:02:58 -040065 self.resizable(height=FALSE, width=FALSE)
Steven M. Gavad721c482001-07-31 10:46:53 +000066 self.transient(parent)
67 self.grab_set()
68 self.protocol("WM_DELETE_WINDOW", self.Cancel)
Steven M. Gava2d4e03b2001-12-05 07:54:07 +000069 self.tabPages.focus_set()
Steven M. Gavad721c482001-07-31 10:46:53 +000070 #key bindings for this dialog
Terry Jan Reedy4036d872014-08-03 23:02:58 -040071 #self.bind('<Escape>', self.Cancel) #dismiss dialog, no save
72 #self.bind('<Alt-a>', self.Apply) #apply changes, save
73 #self.bind('<F1>', self.Help) #context help
Steven M. Gava429a86af2001-10-23 10:42:12 +000074 self.LoadConfigs()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000075 self.AttachVarCallbacks() #avoid callbacks during LoadConfigs
Guido van Rossum8ce8a782007-11-01 19:42:39 +000076
Terry Jan Reedycfa89502014-07-14 23:07:32 -040077 if not _utest:
78 self.wm_deiconify()
79 self.wait_window()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000080
Steven M. Gavad721c482001-07-31 10:46:53 +000081 def CreateWidgets(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +000082 self.tabPages = TabbedPageSet(self,
Terry Jan Reedy93f35422015-10-13 22:03:51 -040083 page_names=['Fonts/Tabs', 'Highlighting', 'Keys', 'General',
84 'Extensions'])
Terry Jan Reedy92cb0a32014-10-08 20:29:13 -040085 self.tabPages.pack(side=TOP, expand=TRUE, fill=BOTH)
86 self.CreatePageFontTab()
87 self.CreatePageHighlight()
88 self.CreatePageKeys()
89 self.CreatePageGeneral()
Terry Jan Reedy93f35422015-10-13 22:03:51 -040090 self.CreatePageExtensions()
Terry Jan Reedy92cb0a32014-10-08 20:29:13 -040091 self.create_action_buttons().pack(side=BOTTOM)
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -040092
Terry Jan Reedy92cb0a32014-10-08 20:29:13 -040093 def create_action_buttons(self):
Ned Deilyb7601672014-03-27 20:49:14 -070094 if macosxSupport.isAquaTk():
Terry Jan Reedye3416e62014-07-26 19:40:16 -040095 # Changing the default padding on OSX results in unreadable
96 # text in the buttons
Terry Jan Reedy4036d872014-08-03 23:02:58 -040097 paddingArgs = {}
Ronald Oussoren9e350042009-02-12 16:02:11 +000098 else:
Terry Jan Reedy4036d872014-08-03 23:02:58 -040099 paddingArgs = {'padx':6, 'pady':3}
Terry Jan Reedya9421fb2014-10-22 20:15:18 -0400100 outer = Frame(self, pady=2)
101 buttons = Frame(outer, pady=2)
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -0400102 for txt, cmd in (
103 ('Ok', self.Ok),
104 ('Apply', self.Apply),
105 ('Cancel', self.Cancel),
106 ('Help', self.Help)):
107 Button(buttons, text=txt, command=cmd, takefocus=FALSE,
108 **paddingArgs).pack(side=LEFT, padx=5)
Terry Jan Reedya9421fb2014-10-22 20:15:18 -0400109 # add space above buttons
110 Frame(outer, height=2, borderwidth=0).pack(side=TOP)
111 buttons.pack(side=BOTTOM)
112 return outer
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -0400113
Steven M. Gava60fc7072001-08-04 13:58:22 +0000114 def CreatePageFontTab(self):
Terry Jan Reedy22405332014-07-30 19:24:32 -0400115 parent = self.parent
116 self.fontSize = StringVar(parent)
117 self.fontBold = BooleanVar(parent)
118 self.fontName = StringVar(parent)
119 self.spaceNum = IntVar(parent)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400120 self.editFont = tkFont.Font(parent, ('courier', 10, 'normal'))
Terry Jan Reedy22405332014-07-30 19:24:32 -0400121
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000122 ##widget creation
123 #body frame
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400124 frame = self.tabPages.pages['Fonts/Tabs'].frame
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000125 #body section frames
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400126 frameFont = LabelFrame(
127 frame, borderwidth=2, relief=GROOVE, text=' Base Editor Font ')
128 frameIndent = LabelFrame(
129 frame, borderwidth=2, relief=GROOVE, text=' Indentation Width ')
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000130 #frameFont
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400131 frameFontName = Frame(frameFont)
132 frameFontParam = Frame(frameFont)
133 labelFontNameTitle = Label(
134 frameFontName, justify=LEFT, text='Font Face :')
135 self.listFontName = Listbox(
136 frameFontName, height=5, takefocus=FALSE, exportselection=FALSE)
137 self.listFontName.bind(
138 '<ButtonRelease-1>', self.OnListFontButtonRelease)
139 scrollFont = Scrollbar(frameFontName)
Steven M. Gavac01e30f2001-08-11 15:48:13 +0000140 scrollFont.config(command=self.listFontName.yview)
141 self.listFontName.config(yscrollcommand=scrollFont.set)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400142 labelFontSizeTitle = Label(frameFontParam, text='Size :')
143 self.optMenuFontSize = DynOptionMenu(
144 frameFontParam, self.fontSize, None, command=self.SetFontSample)
145 checkFontBold = Checkbutton(
146 frameFontParam, variable=self.fontBold, onvalue=1,
147 offvalue=0, text='Bold', command=self.SetFontSample)
148 frameFontSample = Frame(frameFont, relief=SOLID, borderwidth=1)
149 self.labelFontSample = Label(
150 frameFontSample, justify=LEFT, font=self.editFont,
151 text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]')
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000152 #frameIndent
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400153 frameIndentSize = Frame(frameIndent)
154 labelSpaceNumTitle = Label(
155 frameIndentSize, justify=LEFT,
156 text='Python Standard: 4 Spaces!')
157 self.scaleSpaceNum = Scale(
158 frameIndentSize, variable=self.spaceNum,
159 orient='horizontal', tickinterval=2, from_=2, to=16)
Terry Jan Reedy22405332014-07-30 19:24:32 -0400160
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000161 #widget packing
162 #body
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400163 frameFont.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
164 frameIndent.pack(side=LEFT, padx=5, pady=5, fill=Y)
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000165 #frameFont
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400166 frameFontName.pack(side=TOP, padx=5, pady=5, fill=X)
167 frameFontParam.pack(side=TOP, padx=5, pady=5, fill=X)
168 labelFontNameTitle.pack(side=TOP, anchor=W)
169 self.listFontName.pack(side=LEFT, expand=TRUE, fill=X)
170 scrollFont.pack(side=LEFT, fill=Y)
171 labelFontSizeTitle.pack(side=LEFT, anchor=W)
172 self.optMenuFontSize.pack(side=LEFT, anchor=W)
173 checkFontBold.pack(side=LEFT, anchor=W, padx=20)
174 frameFontSample.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
175 self.labelFontSample.pack(expand=TRUE, fill=BOTH)
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000176 #frameIndent
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400177 frameIndentSize.pack(side=TOP, fill=X)
178 labelSpaceNumTitle.pack(side=TOP, anchor=W, padx=5)
179 self.scaleSpaceNum.pack(side=TOP, padx=5, fill=X)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000180 return frame
181
182 def CreatePageHighlight(self):
Terry Jan Reedy22405332014-07-30 19:24:32 -0400183 parent = self.parent
184 self.builtinTheme = StringVar(parent)
185 self.customTheme = StringVar(parent)
186 self.fgHilite = BooleanVar(parent)
187 self.colour = StringVar(parent)
188 self.fontName = StringVar(parent)
189 self.themeIsBuiltin = BooleanVar(parent)
190 self.highlightTarget = StringVar(parent)
191
Steven M. Gava952d0a52001-08-03 04:43:44 +0000192 ##widget creation
193 #body frame
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400194 frame = self.tabPages.pages['Highlighting'].frame
Steven M. Gava952d0a52001-08-03 04:43:44 +0000195 #body section frames
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400196 frameCustom = LabelFrame(frame, borderwidth=2, relief=GROOVE,
197 text=' Custom Highlighting ')
198 frameTheme = LabelFrame(frame, borderwidth=2, relief=GROOVE,
199 text=' Highlighting Theme ')
Steven M. Gava952d0a52001-08-03 04:43:44 +0000200 #frameCustom
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400201 self.textHighlightSample=Text(
202 frameCustom, relief=SOLID, borderwidth=1,
203 font=('courier', 12, ''), cursor='hand2', width=21, height=11,
204 takefocus=FALSE, highlightthickness=0, wrap=NONE)
Steven M. Gavae16d94b2001-11-03 05:07:28 +0000205 text=self.textHighlightSample
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400206 text.bind('<Double-Button-1>', lambda e: 'break')
207 text.bind('<B1-Motion>', lambda e: 'break')
208 textAndTags=(
209 ('#you can click here', 'comment'), ('\n', 'normal'),
210 ('#to choose items', 'comment'), ('\n', 'normal'),
211 ('def', 'keyword'), (' ', 'normal'),
212 ('func', 'definition'), ('(param):\n ', 'normal'),
213 ('"""string"""', 'string'), ('\n var0 = ', 'normal'),
214 ("'string'", 'string'), ('\n var1 = ', 'normal'),
215 ("'selected'", 'hilite'), ('\n var2 = ', 'normal'),
216 ("'found'", 'hit'), ('\n var3 = ', 'normal'),
217 ('list', 'builtin'), ('(', 'normal'),
Terry Jan Reedya8aa4d52015-10-02 22:12:17 -0400218 ('None', 'keyword'), (')\n', 'normal'),
219 (' breakpoint("line")', 'break'), ('\n\n', 'normal'),
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400220 (' error ', 'error'), (' ', 'normal'),
221 ('cursor |', 'cursor'), ('\n ', 'normal'),
222 ('shell', 'console'), (' ', 'normal'),
223 ('stdout', 'stdout'), (' ', 'normal'),
224 ('stderr', 'stderr'), ('\n', 'normal'))
Steven M. Gava9dd16b32001-11-03 14:54:25 +0000225 for txTa in textAndTags:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400226 text.insert(END, txTa[0], txTa[1])
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000227 for element in self.themeElements:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400228 def tem(event, elem=element):
229 event.widget.winfo_toplevel().highlightTarget.set(elem)
230 text.tag_bind(
231 self.themeElements[element][0], '<ButtonPress-1>', tem)
Steven M. Gavae16d94b2001-11-03 05:07:28 +0000232 text.config(state=DISABLED)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400233 self.frameColourSet = Frame(frameCustom, relief=SOLID, borderwidth=1)
234 frameFgBg = Frame(frameCustom)
235 buttonSetColour = Button(
236 self.frameColourSet, text='Choose Colour for :',
237 command=self.GetColour, highlightthickness=0)
238 self.optMenuHighlightTarget = DynOptionMenu(
239 self.frameColourSet, self.highlightTarget, None,
240 highlightthickness=0) #, command=self.SetHighlightTargetBinding
241 self.radioFg = Radiobutton(
242 frameFgBg, variable=self.fgHilite, value=1,
243 text='Foreground', command=self.SetColourSampleBinding)
244 self.radioBg=Radiobutton(
245 frameFgBg, variable=self.fgHilite, value=0,
246 text='Background', command=self.SetColourSampleBinding)
Steven M. Gava7c017862001-10-29 11:19:46 +0000247 self.fgHilite.set(1)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400248 buttonSaveCustomTheme = Button(
249 frameCustom, text='Save as New Custom Theme',
250 command=self.SaveAsNewTheme)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000251 #frameTheme
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400252 labelTypeTitle = Label(frameTheme, text='Select : ')
253 self.radioThemeBuiltin = Radiobutton(
254 frameTheme, variable=self.themeIsBuiltin, value=1,
255 command=self.SetThemeType, text='a Built-in Theme')
256 self.radioThemeCustom = Radiobutton(
257 frameTheme, variable=self.themeIsBuiltin, value=0,
258 command=self.SetThemeType, text='a Custom Theme')
259 self.optMenuThemeBuiltin = DynOptionMenu(
260 frameTheme, self.builtinTheme, None, command=None)
261 self.optMenuThemeCustom=DynOptionMenu(
262 frameTheme, self.customTheme, None, command=None)
263 self.buttonDeleteCustomTheme=Button(
264 frameTheme, text='Delete Custom Theme',
Steven M. Gava49745752002-02-18 01:43:11 +0000265 command=self.DeleteCustomTheme)
Terry Jan Reedyd0c0f002015-11-12 15:02:57 -0500266 self.new_custom_theme = Label(frameTheme, bd=2)
Terry Jan Reedy22405332014-07-30 19:24:32 -0400267
Steven M. Gava952d0a52001-08-03 04:43:44 +0000268 ##widget packing
269 #body
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400270 frameCustom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
271 frameTheme.pack(side=LEFT, padx=5, pady=5, fill=Y)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000272 #frameCustom
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400273 self.frameColourSet.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X)
274 frameFgBg.pack(side=TOP, padx=5, pady=0)
275 self.textHighlightSample.pack(
276 side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
277 buttonSetColour.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=4)
278 self.optMenuHighlightTarget.pack(
279 side=TOP, expand=TRUE, fill=X, padx=8, pady=3)
280 self.radioFg.pack(side=LEFT, anchor=E)
281 self.radioBg.pack(side=RIGHT, anchor=W)
282 buttonSaveCustomTheme.pack(side=BOTTOM, fill=X, padx=5, pady=5)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000283 #frameTheme
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400284 labelTypeTitle.pack(side=TOP, anchor=W, padx=5, pady=5)
285 self.radioThemeBuiltin.pack(side=TOP, anchor=W, padx=5)
286 self.radioThemeCustom.pack(side=TOP, anchor=W, padx=5, pady=2)
287 self.optMenuThemeBuiltin.pack(side=TOP, fill=X, padx=5, pady=5)
288 self.optMenuThemeCustom.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5)
289 self.buttonDeleteCustomTheme.pack(side=TOP, fill=X, padx=5, pady=5)
Terry Jan Reedyd0c0f002015-11-12 15:02:57 -0500290 self.new_custom_theme.pack(side=TOP, fill=X, pady=5)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000291 return frame
292
293 def CreatePageKeys(self):
Terry Jan Reedy22405332014-07-30 19:24:32 -0400294 parent = self.parent
295 self.bindingTarget = StringVar(parent)
296 self.builtinKeys = StringVar(parent)
297 self.customKeys = StringVar(parent)
298 self.keysAreBuiltin = BooleanVar(parent)
299 self.keyBinding = StringVar(parent)
300
Steven M. Gava60fc7072001-08-04 13:58:22 +0000301 ##widget creation
302 #body frame
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400303 frame = self.tabPages.pages['Keys'].frame
Steven M. Gava60fc7072001-08-04 13:58:22 +0000304 #body section frames
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400305 frameCustom = LabelFrame(
306 frame, borderwidth=2, relief=GROOVE,
307 text=' Custom Key Bindings ')
308 frameKeySets = LabelFrame(
309 frame, borderwidth=2, relief=GROOVE, text=' Key Set ')
Steven M. Gava60fc7072001-08-04 13:58:22 +0000310 #frameCustom
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400311 frameTarget = Frame(frameCustom)
312 labelTargetTitle = Label(frameTarget, text='Action - Key(s)')
313 scrollTargetY = Scrollbar(frameTarget)
314 scrollTargetX = Scrollbar(frameTarget, orient=HORIZONTAL)
315 self.listBindings = Listbox(
316 frameTarget, takefocus=FALSE, exportselection=FALSE)
317 self.listBindings.bind('<ButtonRelease-1>', self.KeyBindingSelected)
Steven M. Gavafacfc092002-01-19 00:29:54 +0000318 scrollTargetY.config(command=self.listBindings.yview)
319 scrollTargetX.config(command=self.listBindings.xview)
320 self.listBindings.config(yscrollcommand=scrollTargetY.set)
321 self.listBindings.config(xscrollcommand=scrollTargetX.set)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400322 self.buttonNewKeys = Button(
323 frameCustom, text='Get New Keys for Selection',
324 command=self.GetNewKeys, state=DISABLED)
Steven M. Gava60fc7072001-08-04 13:58:22 +0000325 #frameKeySets
Christian Heimes9a371592007-12-28 14:08:13 +0000326 frames = [Frame(frameKeySets, padx=2, pady=2, borderwidth=0)
327 for i in range(2)]
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400328 self.radioKeysBuiltin = Radiobutton(
329 frames[0], variable=self.keysAreBuiltin, value=1,
330 command=self.SetKeysType, text='Use a Built-in Key Set')
331 self.radioKeysCustom = Radiobutton(
332 frames[0], variable=self.keysAreBuiltin, value=0,
333 command=self.SetKeysType, text='Use a Custom Key Set')
334 self.optMenuKeysBuiltin = DynOptionMenu(
335 frames[0], self.builtinKeys, None, command=None)
336 self.optMenuKeysCustom = DynOptionMenu(
337 frames[0], self.customKeys, None, command=None)
338 self.buttonDeleteCustomKeys = Button(
339 frames[1], text='Delete Custom Key Set',
Steven M. Gava49745752002-02-18 01:43:11 +0000340 command=self.DeleteCustomKeys)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400341 buttonSaveCustomKeys = Button(
342 frames[1], text='Save as New Custom Key Set',
343 command=self.SaveAsNewKeySet)
Terry Jan Reedy22405332014-07-30 19:24:32 -0400344
Steven M. Gava60fc7072001-08-04 13:58:22 +0000345 ##widget packing
346 #body
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400347 frameCustom.pack(side=BOTTOM, padx=5, pady=5, expand=TRUE, fill=BOTH)
348 frameKeySets.pack(side=BOTTOM, padx=5, pady=5, fill=BOTH)
Steven M. Gava60fc7072001-08-04 13:58:22 +0000349 #frameCustom
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400350 self.buttonNewKeys.pack(side=BOTTOM, fill=X, padx=5, pady=5)
351 frameTarget.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
Steven M. Gavafacfc092002-01-19 00:29:54 +0000352 #frame target
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400353 frameTarget.columnconfigure(0, weight=1)
354 frameTarget.rowconfigure(1, weight=1)
355 labelTargetTitle.grid(row=0, column=0, columnspan=2, sticky=W)
356 self.listBindings.grid(row=1, column=0, sticky=NSEW)
357 scrollTargetY.grid(row=1, column=1, sticky=NS)
358 scrollTargetX.grid(row=2, column=0, sticky=EW)
Steven M. Gava60fc7072001-08-04 13:58:22 +0000359 #frameKeySets
Christian Heimes9a371592007-12-28 14:08:13 +0000360 self.radioKeysBuiltin.grid(row=0, column=0, sticky=W+NS)
361 self.radioKeysCustom.grid(row=1, column=0, sticky=W+NS)
362 self.optMenuKeysBuiltin.grid(row=0, column=1, sticky=NSEW)
363 self.optMenuKeysCustom.grid(row=1, column=1, sticky=NSEW)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400364 self.buttonDeleteCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2)
365 buttonSaveCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2)
Christian Heimes9a371592007-12-28 14:08:13 +0000366 frames[0].pack(side=TOP, fill=BOTH, expand=True)
367 frames[1].pack(side=TOP, fill=X, expand=True, pady=2)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000368 return frame
369
370 def CreatePageGeneral(self):
Terry Jan Reedy22405332014-07-30 19:24:32 -0400371 parent = self.parent
372 self.winWidth = StringVar(parent)
373 self.winHeight = StringVar(parent)
Terry Jan Reedy22405332014-07-30 19:24:32 -0400374 self.startupEdit = IntVar(parent)
375 self.autoSave = IntVar(parent)
376 self.encoding = StringVar(parent)
377 self.userHelpBrowser = BooleanVar(parent)
378 self.helpBrowser = StringVar(parent)
379
Steven M. Gava230e5782001-08-07 03:28:25 +0000380 #widget creation
381 #body
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400382 frame = self.tabPages.pages['General'].frame
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000383 #body section frames
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400384 frameRun = LabelFrame(frame, borderwidth=2, relief=GROOVE,
385 text=' Startup Preferences ')
386 frameSave = LabelFrame(frame, borderwidth=2, relief=GROOVE,
387 text=' Autosave Preferences ')
388 frameWinSize = Frame(frame, borderwidth=2, relief=GROOVE)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400389 frameHelp = LabelFrame(frame, borderwidth=2, relief=GROOVE,
390 text=' Additional Help Sources ')
Steven M. Gava230e5782001-08-07 03:28:25 +0000391 #frameRun
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400392 labelRunChoiceTitle = Label(frameRun, text='At Startup')
393 radioStartupEdit = Radiobutton(
394 frameRun, variable=self.startupEdit, value=1,
395 command=self.SetKeysType, text="Open Edit Window")
396 radioStartupShell = Radiobutton(
397 frameRun, variable=self.startupEdit, value=0,
398 command=self.SetKeysType, text='Open Shell Window')
Kurt B. Kaiser6c638b62003-05-26 06:23:10 +0000399 #frameSave
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400400 labelRunSaveTitle = Label(frameSave, text='At Start of Run (F5) ')
401 radioSaveAsk = Radiobutton(
402 frameSave, variable=self.autoSave, value=0,
403 command=self.SetKeysType, text="Prompt to Save")
404 radioSaveAuto = Radiobutton(
405 frameSave, variable=self.autoSave, value=1,
406 command=self.SetKeysType, text='No Prompt')
Steven M. Gava230e5782001-08-07 03:28:25 +0000407 #frameWinSize
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400408 labelWinSizeTitle = Label(
409 frameWinSize, text='Initial Window Size (in characters)')
410 labelWinWidthTitle = Label(frameWinSize, text='Width')
411 entryWinWidth = Entry(
412 frameWinSize, textvariable=self.winWidth, width=3)
413 labelWinHeightTitle = Label(frameWinSize, text='Height')
414 entryWinHeight = Entry(
415 frameWinSize, textvariable=self.winHeight, width=3)
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000416 #frameHelp
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400417 frameHelpList = Frame(frameHelp)
418 frameHelpListButtons = Frame(frameHelpList)
419 scrollHelpList = Scrollbar(frameHelpList)
420 self.listHelp = Listbox(
421 frameHelpList, height=5, takefocus=FALSE,
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000422 exportselection=FALSE)
423 scrollHelpList.config(command=self.listHelp.yview)
424 self.listHelp.config(yscrollcommand=scrollHelpList.set)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400425 self.listHelp.bind('<ButtonRelease-1>', self.HelpSourceSelected)
426 self.buttonHelpListEdit = Button(
427 frameHelpListButtons, text='Edit', state=DISABLED,
428 width=8, command=self.HelpListItemEdit)
429 self.buttonHelpListAdd = Button(
430 frameHelpListButtons, text='Add',
431 width=8, command=self.HelpListItemAdd)
432 self.buttonHelpListRemove = Button(
433 frameHelpListButtons, text='Remove', state=DISABLED,
434 width=8, command=self.HelpListItemRemove)
Terry Jan Reedy22405332014-07-30 19:24:32 -0400435
Steven M. Gava230e5782001-08-07 03:28:25 +0000436 #widget packing
437 #body
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400438 frameRun.pack(side=TOP, padx=5, pady=5, fill=X)
439 frameSave.pack(side=TOP, padx=5, pady=5, fill=X)
440 frameWinSize.pack(side=TOP, padx=5, pady=5, fill=X)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400441 frameHelp.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
Steven M. Gava230e5782001-08-07 03:28:25 +0000442 #frameRun
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400443 labelRunChoiceTitle.pack(side=LEFT, anchor=W, padx=5, pady=5)
444 radioStartupShell.pack(side=RIGHT, anchor=W, padx=5, pady=5)
445 radioStartupEdit.pack(side=RIGHT, anchor=W, padx=5, pady=5)
Kurt B. Kaiser6c638b62003-05-26 06:23:10 +0000446 #frameSave
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400447 labelRunSaveTitle.pack(side=LEFT, anchor=W, padx=5, pady=5)
448 radioSaveAuto.pack(side=RIGHT, anchor=W, padx=5, pady=5)
449 radioSaveAsk.pack(side=RIGHT, anchor=W, padx=5, pady=5)
Steven M. Gava230e5782001-08-07 03:28:25 +0000450 #frameWinSize
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400451 labelWinSizeTitle.pack(side=LEFT, anchor=W, padx=5, pady=5)
452 entryWinHeight.pack(side=RIGHT, anchor=E, padx=10, pady=5)
453 labelWinHeightTitle.pack(side=RIGHT, anchor=E, pady=5)
454 entryWinWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5)
455 labelWinWidthTitle.pack(side=RIGHT, anchor=E, pady=5)
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000456 #frameHelp
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400457 frameHelpListButtons.pack(side=RIGHT, padx=5, pady=5, fill=Y)
458 frameHelpList.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
459 scrollHelpList.pack(side=RIGHT, anchor=W, fill=Y)
460 self.listHelp.pack(side=LEFT, anchor=E, expand=TRUE, fill=BOTH)
461 self.buttonHelpListEdit.pack(side=TOP, anchor=W, pady=5)
462 self.buttonHelpListAdd.pack(side=TOP, anchor=W)
463 self.buttonHelpListRemove.pack(side=TOP, anchor=W, pady=5)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000464 return frame
465
Steven M. Gavac112cd82002-01-22 05:56:40 +0000466 def AttachVarCallbacks(self):
Terry Jan Reedyd87d1682015-08-01 18:57:33 -0400467 self.fontSize.trace_variable('w', self.VarChanged_font)
468 self.fontName.trace_variable('w', self.VarChanged_font)
469 self.fontBold.trace_variable('w', self.VarChanged_font)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400470 self.spaceNum.trace_variable('w', self.VarChanged_spaceNum)
471 self.colour.trace_variable('w', self.VarChanged_colour)
472 self.builtinTheme.trace_variable('w', self.VarChanged_builtinTheme)
473 self.customTheme.trace_variable('w', self.VarChanged_customTheme)
474 self.themeIsBuiltin.trace_variable('w', self.VarChanged_themeIsBuiltin)
475 self.highlightTarget.trace_variable('w', self.VarChanged_highlightTarget)
476 self.keyBinding.trace_variable('w', self.VarChanged_keyBinding)
477 self.builtinKeys.trace_variable('w', self.VarChanged_builtinKeys)
478 self.customKeys.trace_variable('w', self.VarChanged_customKeys)
479 self.keysAreBuiltin.trace_variable('w', self.VarChanged_keysAreBuiltin)
480 self.winWidth.trace_variable('w', self.VarChanged_winWidth)
481 self.winHeight.trace_variable('w', self.VarChanged_winHeight)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400482 self.startupEdit.trace_variable('w', self.VarChanged_startupEdit)
483 self.autoSave.trace_variable('w', self.VarChanged_autoSave)
484 self.encoding.trace_variable('w', self.VarChanged_encoding)
Steven M. Gava052937f2002-02-11 02:20:53 +0000485
Terry Jan Reedyd87d1682015-08-01 18:57:33 -0400486 def VarChanged_font(self, *params):
487 '''When one font attribute changes, save them all, as they are
488 not independent from each other. In particular, when we are
489 overriding the default font, we need to write out everything.
490 '''
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400491 value = self.fontName.get()
492 self.AddChangedItem('main', 'EditorWindow', 'font', value)
Terry Jan Reedyd87d1682015-08-01 18:57:33 -0400493 value = self.fontSize.get()
494 self.AddChangedItem('main', 'EditorWindow', 'font-size', value)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400495 value = self.fontBold.get()
496 self.AddChangedItem('main', 'EditorWindow', 'font-bold', value)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000497
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400498 def VarChanged_spaceNum(self, *params):
499 value = self.spaceNum.get()
500 self.AddChangedItem('main', 'Indent', 'num-spaces', value)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000501
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400502 def VarChanged_colour(self, *params):
Steven M. Gava052937f2002-02-11 02:20:53 +0000503 self.OnNewColourSet()
504
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400505 def VarChanged_builtinTheme(self, *params):
506 value = self.builtinTheme.get()
Terry Jan Reedybe5b7a22015-10-04 00:31:05 -0400507 if value == 'IDLE Dark':
Terry Jan Reedyd0c0f002015-11-12 15:02:57 -0500508 if idleConf.GetOption('main', 'Theme', 'name') != 'IDLE New':
509 self.AddChangedItem('main', 'Theme', 'name', 'IDLE Classic')
510 self.AddChangedItem('main', 'Theme', 'name2', value)
511 self.new_custom_theme.config(text='New theme, see Help',
512 fg='#500000')
513 else:
514 self.AddChangedItem('main', 'Theme', 'name', value)
515 self.AddChangedItem('main', 'Theme', 'name2', '')
516 self.new_custom_theme.config(text='', fg='black')
Steven M. Gava052937f2002-02-11 02:20:53 +0000517 self.PaintThemeSample()
518
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400519 def VarChanged_customTheme(self, *params):
520 value = self.customTheme.get()
Steven M. Gava49745752002-02-18 01:43:11 +0000521 if value != '- no custom themes -':
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400522 self.AddChangedItem('main', 'Theme', 'name', value)
Steven M. Gava49745752002-02-18 01:43:11 +0000523 self.PaintThemeSample()
Steven M. Gava052937f2002-02-11 02:20:53 +0000524
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400525 def VarChanged_themeIsBuiltin(self, *params):
526 value = self.themeIsBuiltin.get()
527 self.AddChangedItem('main', 'Theme', 'default', value)
Steven M. Gavaf31eec02002-03-05 00:25:58 +0000528 if value:
529 self.VarChanged_builtinTheme()
530 else:
531 self.VarChanged_customTheme()
Steven M. Gava052937f2002-02-11 02:20:53 +0000532
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400533 def VarChanged_highlightTarget(self, *params):
Steven M. Gava052937f2002-02-11 02:20:53 +0000534 self.SetHighlightTarget()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000535
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400536 def VarChanged_keyBinding(self, *params):
537 value = self.keyBinding.get()
538 keySet = self.customKeys.get()
539 event = self.listBindings.get(ANCHOR).split()[0]
Steven M. Gavaa498af22002-02-01 01:33:36 +0000540 if idleConf.IsCoreBinding(event):
541 #this is a core keybinding
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400542 self.AddChangedItem('keys', keySet, event, value)
Steven M. Gavaa498af22002-02-01 01:33:36 +0000543 else: #this is an extension key binding
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400544 extName = idleConf.GetExtnNameForEvent(event)
545 extKeybindSection = extName + '_cfgBindings'
546 self.AddChangedItem('extensions', extKeybindSection, event, value)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000547
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400548 def VarChanged_builtinKeys(self, *params):
549 value = self.builtinKeys.get()
550 self.AddChangedItem('main', 'Keys', 'name', value)
Steven M. Gava052937f2002-02-11 02:20:53 +0000551 self.LoadKeysList(value)
552
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400553 def VarChanged_customKeys(self, *params):
554 value = self.customKeys.get()
Steven M. Gava49745752002-02-18 01:43:11 +0000555 if value != '- no custom keys -':
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400556 self.AddChangedItem('main', 'Keys', 'name', value)
Steven M. Gava49745752002-02-18 01:43:11 +0000557 self.LoadKeysList(value)
Steven M. Gava052937f2002-02-11 02:20:53 +0000558
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400559 def VarChanged_keysAreBuiltin(self, *params):
560 value = self.keysAreBuiltin.get()
561 self.AddChangedItem('main', 'Keys', 'default', value)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000562 if value:
Steven M. Gavaf31eec02002-03-05 00:25:58 +0000563 self.VarChanged_builtinKeys()
Steven M. Gava052937f2002-02-11 02:20:53 +0000564 else:
Steven M. Gavaf31eec02002-03-05 00:25:58 +0000565 self.VarChanged_customKeys()
Steven M. Gava052937f2002-02-11 02:20:53 +0000566
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400567 def VarChanged_winWidth(self, *params):
568 value = self.winWidth.get()
569 self.AddChangedItem('main', 'EditorWindow', 'width', value)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000570
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400571 def VarChanged_winHeight(self, *params):
572 value = self.winHeight.get()
573 self.AddChangedItem('main', 'EditorWindow', 'height', value)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000574
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400575 def VarChanged_startupEdit(self, *params):
576 value = self.startupEdit.get()
577 self.AddChangedItem('main', 'General', 'editor-on-startup', value)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000578
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400579 def VarChanged_autoSave(self, *params):
580 value = self.autoSave.get()
581 self.AddChangedItem('main', 'General', 'autosave', value)
Kurt B. Kaiser6c638b62003-05-26 06:23:10 +0000582
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400583 def VarChanged_encoding(self, *params):
584 value = self.encoding.get()
585 self.AddChangedItem('main', 'EditorWindow', 'encoding', value)
Kurt B. Kaisera053f332003-05-10 00:49:56 +0000586
Steven M. Gavaa498af22002-02-01 01:33:36 +0000587 def ResetChangedItems(self):
Steven M. Gavab77d3432002-03-02 07:16:21 +0000588 #When any config item is changed in this dialog, an entry
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000589 #should be made in the relevant section (config type) of this
590 #dictionary. The key should be the config file section name and the
Steven M. Gavaa498af22002-02-01 01:33:36 +0000591 #value a dictionary, whose key:value pairs are item=value pairs for
592 #that config file section.
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400593 self.changedItems = {'main':{}, 'highlight':{}, 'keys':{},
594 'extensions':{}}
Steven M. Gavaa498af22002-02-01 01:33:36 +0000595
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400596 def AddChangedItem(self, typ, section, item, value):
597 value = str(value) #make sure we use a string
598 if section not in self.changedItems[typ]:
599 self.changedItems[typ][section] = {}
600 self.changedItems[typ][section][item] = value
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000601
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000602 def GetDefaultItems(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400603 dItems={'main':{}, 'highlight':{}, 'keys':{}, 'extensions':{}}
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000604 for configType in dItems:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400605 sections = idleConf.GetSectionList('default', configType)
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000606 for section in sections:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400607 dItems[configType][section] = {}
608 options = idleConf.defaultCfg[configType].GetOptionList(section)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000609 for option in options:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400610 dItems[configType][section][option] = (
611 idleConf.defaultCfg[configType].Get(section, option))
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000612 return dItems
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000613
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000614 def SetThemeType(self):
615 if self.themeIsBuiltin.get():
616 self.optMenuThemeBuiltin.config(state=NORMAL)
617 self.optMenuThemeCustom.config(state=DISABLED)
618 self.buttonDeleteCustomTheme.config(state=DISABLED)
619 else:
620 self.optMenuThemeBuiltin.config(state=DISABLED)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000621 self.radioThemeCustom.config(state=NORMAL)
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000622 self.optMenuThemeCustom.config(state=NORMAL)
623 self.buttonDeleteCustomTheme.config(state=NORMAL)
624
625 def SetKeysType(self):
Steven M. Gava052937f2002-02-11 02:20:53 +0000626 if self.keysAreBuiltin.get():
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000627 self.optMenuKeysBuiltin.config(state=NORMAL)
628 self.optMenuKeysCustom.config(state=DISABLED)
629 self.buttonDeleteCustomKeys.config(state=DISABLED)
630 else:
631 self.optMenuKeysBuiltin.config(state=DISABLED)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000632 self.radioKeysCustom.config(state=NORMAL)
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000633 self.optMenuKeysCustom.config(state=NORMAL)
634 self.buttonDeleteCustomKeys.config(state=NORMAL)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000635
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000636 def GetNewKeys(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400637 listIndex = self.listBindings.index(ANCHOR)
638 binding = self.listBindings.get(listIndex)
639 bindName = binding.split()[0] #first part, up to first space
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000640 if self.keysAreBuiltin.get():
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400641 currentKeySetName = self.builtinKeys.get()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000642 else:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400643 currentKeySetName = self.customKeys.get()
644 currentBindings = idleConf.GetCurrentKeySet()
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000645 if currentKeySetName in self.changedItems['keys']: #unsaved changes
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400646 keySetChanges = self.changedItems['keys'][currentKeySetName]
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000647 for event in keySetChanges:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400648 currentBindings[event] = keySetChanges[event].split()
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000649 currentKeySequences = list(currentBindings.values())
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400650 newKeys = GetKeysDialog(self, 'Get New Keys', bindName,
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000651 currentKeySequences).result
652 if newKeys: #new keys were specified
Steven M. Gava052937f2002-02-11 02:20:53 +0000653 if self.keysAreBuiltin.get(): #current key set is a built-in
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400654 message = ('Your changes will be saved as a new Custom Key Set.'
655 ' Enter a name for your new Custom Key Set below.')
656 newKeySet = self.GetNewKeysName(message)
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000657 if not newKeySet: #user cancelled custom key set creation
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000658 self.listBindings.select_set(listIndex)
659 self.listBindings.select_anchor(listIndex)
660 return
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000661 else: #create new custom key set based on previously active key set
662 self.CreateNewKeySet(newKeySet)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000663 self.listBindings.delete(listIndex)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400664 self.listBindings.insert(listIndex, bindName+' - '+newKeys)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000665 self.listBindings.select_set(listIndex)
666 self.listBindings.select_anchor(listIndex)
Steven M. Gava052937f2002-02-11 02:20:53 +0000667 self.keyBinding.set(newKeys)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000668 else:
669 self.listBindings.select_set(listIndex)
670 self.listBindings.select_anchor(listIndex)
671
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400672 def GetNewKeysName(self, message):
673 usedNames = (idleConf.GetSectionList('user', 'keys') +
674 idleConf.GetSectionList('default', 'keys'))
675 newKeySet = GetCfgSectionNameDialog(
676 self, 'New Custom Key Set', message, usedNames).result
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000677 return newKeySet
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000678
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000679 def SaveAsNewKeySet(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400680 newKeysName = self.GetNewKeysName('New Key Set Name:')
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000681 if newKeysName:
682 self.CreateNewKeySet(newKeysName)
683
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400684 def KeyBindingSelected(self, event):
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000685 self.buttonNewKeys.config(state=NORMAL)
686
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400687 def CreateNewKeySet(self, newKeySetName):
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000688 #creates new custom key set based on the previously active key set,
689 #and makes the new key set active
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000690 if self.keysAreBuiltin.get():
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400691 prevKeySetName = self.builtinKeys.get()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000692 else:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400693 prevKeySetName = self.customKeys.get()
694 prevKeys = idleConf.GetCoreKeys(prevKeySetName)
695 newKeys = {}
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000696 for event in prevKeys: #add key set to changed items
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400697 eventName = event[2:-2] #trim off the angle brackets
698 binding = ' '.join(prevKeys[event])
699 newKeys[eventName] = binding
Steven M. Gava052937f2002-02-11 02:20:53 +0000700 #handle any unsaved changes to prev key set
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000701 if prevKeySetName in self.changedItems['keys']:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400702 keySetChanges = self.changedItems['keys'][prevKeySetName]
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000703 for event in keySetChanges:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400704 newKeys[event] = keySetChanges[event]
Steven M. Gava052937f2002-02-11 02:20:53 +0000705 #save the new theme
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400706 self.SaveNewKeySet(newKeySetName, newKeys)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000707 #change gui over to the new key set
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400708 customKeyList = idleConf.GetSectionList('user', 'keys')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000709 customKeyList.sort()
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400710 self.optMenuKeysCustom.SetMenu(customKeyList, newKeySetName)
Steven M. Gava052937f2002-02-11 02:20:53 +0000711 self.keysAreBuiltin.set(0)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000712 self.SetKeysType()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000713
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400714 def LoadKeysList(self, keySetName):
715 reselect = 0
716 newKeySet = 0
Steven M. Gava052937f2002-02-11 02:20:53 +0000717 if self.listBindings.curselection():
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400718 reselect = 1
719 listIndex = self.listBindings.index(ANCHOR)
720 keySet = idleConf.GetKeySet(keySetName)
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000721 bindNames = list(keySet.keys())
Steven M. Gava052937f2002-02-11 02:20:53 +0000722 bindNames.sort()
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400723 self.listBindings.delete(0, END)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000724 for bindName in bindNames:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400725 key = ' '.join(keySet[bindName]) #make key(s) into a string
726 bindName = bindName[2:-2] #trim off the angle brackets
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000727 if keySetName in self.changedItems['keys']:
Steven M. Gava052937f2002-02-11 02:20:53 +0000728 #handle any unsaved changes to this key set
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000729 if bindName in self.changedItems['keys'][keySetName]:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400730 key = self.changedItems['keys'][keySetName][bindName]
Steven M. Gava052937f2002-02-11 02:20:53 +0000731 self.listBindings.insert(END, bindName+' - '+key)
Steven M. Gava052937f2002-02-11 02:20:53 +0000732 if reselect:
733 self.listBindings.see(listIndex)
734 self.listBindings.select_set(listIndex)
735 self.listBindings.select_anchor(listIndex)
736
Steven M. Gava49745752002-02-18 01:43:11 +0000737 def DeleteCustomKeys(self):
738 keySetName=self.customKeys.get()
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400739 delmsg = 'Are you sure you wish to delete the key set %r ?'
740 if not tkMessageBox.askyesno(
741 'Delete Key Set', delmsg % keySetName, parent=self):
Steven M. Gava49745752002-02-18 01:43:11 +0000742 return
743 #remove key set from config
744 idleConf.userCfg['keys'].remove_section(keySetName)
Guido van Rossum811c4e02006-08-22 15:45:46 +0000745 if keySetName in self.changedItems['keys']:
Steven M. Gava49745752002-02-18 01:43:11 +0000746 del(self.changedItems['keys'][keySetName])
747 #write changes
748 idleConf.userCfg['keys'].Save()
749 #reload user key set list
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400750 itemList = idleConf.GetSectionList('user', 'keys')
Steven M. Gava49745752002-02-18 01:43:11 +0000751 itemList.sort()
752 if not itemList:
753 self.radioKeysCustom.config(state=DISABLED)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400754 self.optMenuKeysCustom.SetMenu(itemList, '- no custom keys -')
Steven M. Gava49745752002-02-18 01:43:11 +0000755 else:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400756 self.optMenuKeysCustom.SetMenu(itemList, itemList[0])
Steven M. Gava49745752002-02-18 01:43:11 +0000757 #revert to default key set
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400758 self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys', 'default'))
759 self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys', 'name'))
Steven M. Gava49745752002-02-18 01:43:11 +0000760 #user can't back out of these changes, they must be applied now
761 self.Apply()
762 self.SetKeysType()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000763
Steven M. Gava49745752002-02-18 01:43:11 +0000764 def DeleteCustomTheme(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400765 themeName = self.customTheme.get()
766 delmsg = 'Are you sure you wish to delete the theme %r ?'
767 if not tkMessageBox.askyesno(
768 'Delete Theme', delmsg % themeName, parent=self):
Steven M. Gava49745752002-02-18 01:43:11 +0000769 return
770 #remove theme from config
771 idleConf.userCfg['highlight'].remove_section(themeName)
Guido van Rossum811c4e02006-08-22 15:45:46 +0000772 if themeName in self.changedItems['highlight']:
Steven M. Gava49745752002-02-18 01:43:11 +0000773 del(self.changedItems['highlight'][themeName])
774 #write changes
775 idleConf.userCfg['highlight'].Save()
776 #reload user theme list
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400777 itemList = idleConf.GetSectionList('user', 'highlight')
Steven M. Gava49745752002-02-18 01:43:11 +0000778 itemList.sort()
779 if not itemList:
780 self.radioThemeCustom.config(state=DISABLED)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400781 self.optMenuThemeCustom.SetMenu(itemList, '- no custom themes -')
Steven M. Gava49745752002-02-18 01:43:11 +0000782 else:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400783 self.optMenuThemeCustom.SetMenu(itemList, itemList[0])
Steven M. Gava49745752002-02-18 01:43:11 +0000784 #revert to default theme
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400785 self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme', 'default'))
786 self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme', 'name'))
Steven M. Gava49745752002-02-18 01:43:11 +0000787 #user can't back out of these changes, they must be applied now
788 self.Apply()
789 self.SetThemeType()
790
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000791 def GetColour(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400792 target = self.highlightTarget.get()
793 prevColour = self.frameColourSet.cget('bg')
794 rgbTuplet, colourString = tkColorChooser.askcolor(
795 parent=self, title='Pick new colour for : '+target,
796 initialcolor=prevColour)
797 if colourString and (colourString != prevColour):
Steven M. Gava052937f2002-02-11 02:20:53 +0000798 #user didn't cancel, and they chose a new colour
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400799 if self.themeIsBuiltin.get(): #current theme is a built-in
800 message = ('Your changes will be saved as a new Custom Theme. '
801 'Enter a name for your new Custom Theme below.')
802 newTheme = self.GetNewThemeName(message)
803 if not newTheme: #user cancelled custom theme creation
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000804 return
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400805 else: #create new custom theme based on previously active theme
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000806 self.CreateNewTheme(newTheme)
Steven M. Gava052937f2002-02-11 02:20:53 +0000807 self.colour.set(colourString)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400808 else: #current theme is user defined
Steven M. Gava052937f2002-02-11 02:20:53 +0000809 self.colour.set(colourString)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000810
Steven M. Gava052937f2002-02-11 02:20:53 +0000811 def OnNewColourSet(self):
812 newColour=self.colour.get()
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400813 self.frameColourSet.config(bg=newColour) #set sample
814 plane ='foreground' if self.fgHilite.get() else 'background'
815 sampleElement = self.themeElements[self.highlightTarget.get()][0]
Raymond Hettinger931237e2003-07-09 18:48:24 +0000816 self.textHighlightSample.tag_config(sampleElement, **{plane:newColour})
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400817 theme = self.customTheme.get()
818 themeElement = sampleElement + '-' + plane
819 self.AddChangedItem('highlight', theme, themeElement, newColour)
Steven M. Gava052937f2002-02-11 02:20:53 +0000820
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400821 def GetNewThemeName(self, message):
822 usedNames = (idleConf.GetSectionList('user', 'highlight') +
823 idleConf.GetSectionList('default', 'highlight'))
824 newTheme = GetCfgSectionNameDialog(
825 self, 'New Custom Theme', message, usedNames).result
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000826 return newTheme
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000827
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000828 def SaveAsNewTheme(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400829 newThemeName = self.GetNewThemeName('New Theme Name:')
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000830 if newThemeName:
831 self.CreateNewTheme(newThemeName)
832
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400833 def CreateNewTheme(self, newThemeName):
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000834 #creates new custom theme based on the previously active theme,
835 #and makes the new theme active
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000836 if self.themeIsBuiltin.get():
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400837 themeType = 'default'
838 themeName = self.builtinTheme.get()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000839 else:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400840 themeType = 'user'
841 themeName = self.customTheme.get()
842 newTheme = idleConf.GetThemeDict(themeType, themeName)
Steven M. Gava052937f2002-02-11 02:20:53 +0000843 #apply any of the old theme's unsaved changes to the new theme
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000844 if themeName in self.changedItems['highlight']:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400845 themeChanges = self.changedItems['highlight'][themeName]
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000846 for element in themeChanges:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400847 newTheme[element] = themeChanges[element]
Steven M. Gava052937f2002-02-11 02:20:53 +0000848 #save the new theme
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400849 self.SaveNewTheme(newThemeName, newTheme)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000850 #change gui over to the new theme
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400851 customThemeList = idleConf.GetSectionList('user', 'highlight')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000852 customThemeList.sort()
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400853 self.optMenuThemeCustom.SetMenu(customThemeList, newThemeName)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000854 self.themeIsBuiltin.set(0)
855 self.SetThemeType()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000856
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400857 def OnListFontButtonRelease(self, event):
Kurt B. Kaiser05391692003-05-26 20:35:53 +0000858 font = self.listFontName.get(ANCHOR)
859 self.fontName.set(font.lower())
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000860 self.SetFontSample()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000861
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400862 def SetFontSample(self, event=None):
863 fontName = self.fontName.get()
864 fontWeight = tkFont.BOLD if self.fontBold.get() else tkFont.NORMAL
Ned Deilyfdf0f272012-10-22 15:14:31 -0700865 newFont = (fontName, self.fontSize.get(), fontWeight)
866 self.labelFontSample.config(font=newFont)
867 self.textHighlightSample.configure(font=newFont)
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000868
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000869 def SetHighlightTarget(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400870 if self.highlightTarget.get() == 'Cursor': #bg not possible
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000871 self.radioFg.config(state=DISABLED)
872 self.radioBg.config(state=DISABLED)
873 self.fgHilite.set(1)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400874 else: #both fg and bg can be set
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000875 self.radioFg.config(state=NORMAL)
876 self.radioBg.config(state=NORMAL)
877 self.fgHilite.set(1)
878 self.SetColourSample()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000879
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400880 def SetColourSampleBinding(self, *args):
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000881 self.SetColourSample()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000882
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000883 def SetColourSample(self):
884 #set the colour smaple area
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400885 tag = self.themeElements[self.highlightTarget.get()][0]
886 plane = 'foreground' if self.fgHilite.get() else 'background'
887 colour = self.textHighlightSample.tag_cget(tag, plane)
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000888 self.frameColourSet.config(bg=colour)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000889
Steven M. Gava9dd16b32001-11-03 14:54:25 +0000890 def PaintThemeSample(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400891 if self.themeIsBuiltin.get(): #a default theme
892 theme = self.builtinTheme.get()
893 else: #a user theme
894 theme = self.customTheme.get()
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000895 for elementTitle in self.themeElements:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400896 element = self.themeElements[elementTitle][0]
897 colours = idleConf.GetHighlight(theme, element)
898 if element == 'cursor': #cursor sample needs special painting
899 colours['background'] = idleConf.GetHighlight(
900 theme, 'normal', fgBg='bg')
Steven M. Gava052937f2002-02-11 02:20:53 +0000901 #handle any unsaved changes to this theme
Kurt B. Kaisere0712772007-08-23 05:25:55 +0000902 if theme in self.changedItems['highlight']:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400903 themeDict = self.changedItems['highlight'][theme]
904 if element + '-foreground' in themeDict:
905 colours['foreground'] = themeDict[element + '-foreground']
906 if element + '-background' in themeDict:
907 colours['background'] = themeDict[element + '-background']
Raymond Hettinger931237e2003-07-09 18:48:24 +0000908 self.textHighlightSample.tag_config(element, **colours)
Steven M. Gava052937f2002-02-11 02:20:53 +0000909 self.SetColourSample()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000910
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400911 def HelpSourceSelected(self, event):
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000912 self.SetHelpListButtonStates()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000913
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000914 def SetHelpListButtonStates(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400915 if self.listHelp.size() < 1: #no entries in list
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000916 self.buttonHelpListEdit.config(state=DISABLED)
917 self.buttonHelpListRemove.config(state=DISABLED)
918 else: #there are some entries
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400919 if self.listHelp.curselection(): #there currently is a selection
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000920 self.buttonHelpListEdit.config(state=NORMAL)
921 self.buttonHelpListRemove.config(state=NORMAL)
922 else: #there currently is not a selection
923 self.buttonHelpListEdit.config(state=DISABLED)
924 self.buttonHelpListRemove.config(state=DISABLED)
925
926 def HelpListItemAdd(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400927 helpSource = GetHelpSourceDialog(self, 'New Help Source').result
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000928 if helpSource:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400929 self.userHelpList.append((helpSource[0], helpSource[1]))
930 self.listHelp.insert(END, helpSource[0])
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000931 self.UpdateUserHelpChangedItems()
932 self.SetHelpListButtonStates()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000933
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000934 def HelpListItemEdit(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400935 itemIndex = self.listHelp.index(ANCHOR)
936 helpSource = self.userHelpList[itemIndex]
937 newHelpSource = GetHelpSourceDialog(
938 self, 'Edit Help Source', menuItem=helpSource[0],
939 filePath=helpSource[1]).result
940 if (not newHelpSource) or (newHelpSource == helpSource):
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000941 return #no changes
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400942 self.userHelpList[itemIndex] = newHelpSource
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000943 self.listHelp.delete(itemIndex)
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400944 self.listHelp.insert(itemIndex, newHelpSource[0])
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000945 self.UpdateUserHelpChangedItems()
946 self.SetHelpListButtonStates()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000947
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000948 def HelpListItemRemove(self):
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400949 itemIndex = self.listHelp.index(ANCHOR)
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000950 del(self.userHelpList[itemIndex])
951 self.listHelp.delete(itemIndex)
952 self.UpdateUserHelpChangedItems()
953 self.SetHelpListButtonStates()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000954
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000955 def UpdateUserHelpChangedItems(self):
Kurt B. Kaiser8e92bf72003-01-14 22:03:31 +0000956 "Clear and rebuild the HelpFiles section in self.changedItems"
957 self.changedItems['main']['HelpFiles'] = {}
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400958 for num in range(1, len(self.userHelpList) + 1):
959 self.AddChangedItem(
960 'main', 'HelpFiles', str(num),
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000961 ';'.join(self.userHelpList[num-1][:2]))
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000962
Steven M. Gava429a86af2001-10-23 10:42:12 +0000963 def LoadFontCfg(self):
964 ##base editor font selection list
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400965 fonts = list(tkFont.families(self))
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000966 fonts.sort()
967 for font in fonts:
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400968 self.listFontName.insert(END, font)
Terry Jan Reedyd87d1682015-08-01 18:57:33 -0400969 configuredFont = idleConf.GetFont(self, 'main', 'EditorWindow')
970 fontName = configuredFont[0].lower()
971 fontSize = configuredFont[1]
972 fontBold = configuredFont[2]=='bold'
973 self.fontName.set(fontName)
Kurt B. Kaiser05391692003-05-26 20:35:53 +0000974 lc_fonts = [s.lower() for s in fonts]
Terry Jan Reedyd87d1682015-08-01 18:57:33 -0400975 try:
976 currentFontIndex = lc_fonts.index(fontName)
Steven M. Gava429a86af2001-10-23 10:42:12 +0000977 self.listFontName.see(currentFontIndex)
978 self.listFontName.select_set(currentFontIndex)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000979 self.listFontName.select_anchor(currentFontIndex)
Terry Jan Reedyd87d1682015-08-01 18:57:33 -0400980 except ValueError:
981 pass
Steven M. Gava429a86af2001-10-23 10:42:12 +0000982 ##font size dropdown
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400983 self.optMenuFontSize.SetMenu(('7', '8', '9', '10', '11', '12', '13',
984 '14', '16', '18', '20', '22'), fontSize )
Steven M. Gavac112cd82002-01-22 05:56:40 +0000985 ##fontWeight
Terry Jan Reedyd87d1682015-08-01 18:57:33 -0400986 self.fontBold.set(fontBold)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000987 ##font sample
Steven M. Gava429a86af2001-10-23 10:42:12 +0000988 self.SetFontSample()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000989
Steven M. Gava429a86af2001-10-23 10:42:12 +0000990 def LoadTabCfg(self):
Steven M. Gava429a86af2001-10-23 10:42:12 +0000991 ##indent sizes
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400992 spaceNum = idleConf.GetOption(
993 'main', 'Indent', 'num-spaces', default=4, type='int')
Steven M. Gava429a86af2001-10-23 10:42:12 +0000994 self.spaceNum.set(spaceNum)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000995
Steven M. Gava9dd16b32001-11-03 14:54:25 +0000996 def LoadThemeCfg(self):
Steven M. Gava41a85322001-10-29 08:05:34 +0000997 ##current theme type radiobutton
Terry Jan Reedy4036d872014-08-03 23:02:58 -0400998 self.themeIsBuiltin.set(idleConf.GetOption(
999 'main', 'Theme', 'default', type='bool', default=1))
Steven M. Gava41a85322001-10-29 08:05:34 +00001000 ##currently set theme
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001001 currentOption = idleConf.CurrentTheme()
Steven M. Gava7c017862001-10-29 11:19:46 +00001002 ##load available theme option menus
Steven M. Gavad0342cd2001-11-04 11:53:10 +00001003 if self.themeIsBuiltin.get(): #default theme selected
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001004 itemList = idleConf.GetSectionList('default', 'highlight')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001005 itemList.sort()
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001006 self.optMenuThemeBuiltin.SetMenu(itemList, currentOption)
1007 itemList = idleConf.GetSectionList('user', 'highlight')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001008 itemList.sort()
Steven M. Gava41a85322001-10-29 08:05:34 +00001009 if not itemList:
1010 self.radioThemeCustom.config(state=DISABLED)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001011 self.customTheme.set('- no custom themes -')
Steven M. Gava41a85322001-10-29 08:05:34 +00001012 else:
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001013 self.optMenuThemeCustom.SetMenu(itemList, itemList[0])
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001014 else: #user theme selected
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001015 itemList = idleConf.GetSectionList('user', 'highlight')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001016 itemList.sort()
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001017 self.optMenuThemeCustom.SetMenu(itemList, currentOption)
1018 itemList = idleConf.GetSectionList('default', 'highlight')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001019 itemList.sort()
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001020 self.optMenuThemeBuiltin.SetMenu(itemList, itemList[0])
Steven M. Gava7c017862001-10-29 11:19:46 +00001021 self.SetThemeType()
1022 ##load theme element option menu
Kurt B. Kaisere0712772007-08-23 05:25:55 +00001023 themeNames = list(self.themeElements.keys())
Kurt B. Kaiser4718bf82008-02-12 21:34:12 +00001024 themeNames.sort(key=lambda x: self.themeElements[x][1])
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001025 self.optMenuHighlightTarget.SetMenu(themeNames, themeNames[0])
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001026 self.PaintThemeSample()
Steven M. Gava0cae01c2002-01-04 07:53:06 +00001027 self.SetHighlightTarget()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001028
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001029 def LoadKeyCfg(self):
Steven M. Gava41a85322001-10-29 08:05:34 +00001030 ##current keys type radiobutton
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001031 self.keysAreBuiltin.set(idleConf.GetOption(
1032 'main', 'Keys', 'default', type='bool', default=1))
Steven M. Gava41a85322001-10-29 08:05:34 +00001033 ##currently set keys
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001034 currentOption = idleConf.CurrentKeys()
Steven M. Gava7c017862001-10-29 11:19:46 +00001035 ##load available keyset option menus
Steven M. Gava052937f2002-02-11 02:20:53 +00001036 if self.keysAreBuiltin.get(): #default theme selected
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001037 itemList = idleConf.GetSectionList('default', 'keys')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001038 itemList.sort()
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001039 self.optMenuKeysBuiltin.SetMenu(itemList, currentOption)
1040 itemList = idleConf.GetSectionList('user', 'keys')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001041 itemList.sort()
Steven M. Gava41a85322001-10-29 08:05:34 +00001042 if not itemList:
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001043 self.radioKeysCustom.config(state=DISABLED)
1044 self.customKeys.set('- no custom keys -')
Steven M. Gava41a85322001-10-29 08:05:34 +00001045 else:
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001046 self.optMenuKeysCustom.SetMenu(itemList, itemList[0])
Steven M. Gavaa498af22002-02-01 01:33:36 +00001047 else: #user key set selected
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001048 itemList = idleConf.GetSectionList('user', 'keys')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001049 itemList.sort()
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001050 self.optMenuKeysCustom.SetMenu(itemList, currentOption)
1051 itemList = idleConf.GetSectionList('default', 'keys')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001052 itemList.sort()
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001053 self.optMenuKeysBuiltin.SetMenu(itemList, itemList[0])
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001054 self.SetKeysType()
Steven M. Gavafacfc092002-01-19 00:29:54 +00001055 ##load keyset element list
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001056 keySetName = idleConf.CurrentKeys()
Steven M. Gava052937f2002-02-11 02:20:53 +00001057 self.LoadKeysList(keySetName)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001058
Steven M. Gavafacfc092002-01-19 00:29:54 +00001059 def LoadGeneralCfg(self):
Steven M. Gava5f28e8f2002-01-21 06:38:21 +00001060 #startup state
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001061 self.startupEdit.set(idleConf.GetOption(
1062 'main', 'General', 'editor-on-startup', default=1, type='bool'))
Kurt B. Kaiser6c638b62003-05-26 06:23:10 +00001063 #autosave state
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001064 self.autoSave.set(idleConf.GetOption(
1065 'main', 'General', 'autosave', default=0, type='bool'))
Steven M. Gavafacfc092002-01-19 00:29:54 +00001066 #initial window size
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001067 self.winWidth.set(idleConf.GetOption(
1068 'main', 'EditorWindow', 'width', type='int'))
1069 self.winHeight.set(idleConf.GetOption(
1070 'main', 'EditorWindow', 'height', type='int'))
Kurt B. Kaisera053f332003-05-10 00:49:56 +00001071 # default source encoding
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001072 self.encoding.set(idleConf.GetOption(
1073 'main', 'EditorWindow', 'encoding', default='none'))
Kurt B. Kaiser8e92bf72003-01-14 22:03:31 +00001074 # additional help sources
1075 self.userHelpList = idleConf.GetAllExtraHelpSourcesList()
Steven M. Gava085eb1b2002-02-05 04:52:32 +00001076 for helpItem in self.userHelpList:
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001077 self.listHelp.insert(END, helpItem[0])
Steven M. Gava085eb1b2002-02-05 04:52:32 +00001078 self.SetHelpListButtonStates()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001079
Steven M. Gava429a86af2001-10-23 10:42:12 +00001080 def LoadConfigs(self):
1081 """
1082 load configuration from default and user config files and populate
1083 the widgets on the config dialog pages.
1084 """
1085 ### fonts / tabs page
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001086 self.LoadFontCfg()
1087 self.LoadTabCfg()
Steven M. Gava429a86af2001-10-23 10:42:12 +00001088 ### highlighting page
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001089 self.LoadThemeCfg()
Steven M. Gava429a86af2001-10-23 10:42:12 +00001090 ### keys page
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001091 self.LoadKeyCfg()
Steven M. Gava429a86af2001-10-23 10:42:12 +00001092 ### general page
Steven M. Gavafacfc092002-01-19 00:29:54 +00001093 self.LoadGeneralCfg()
Terry Jan Reedy93f35422015-10-13 22:03:51 -04001094 # note: extension page handled separately
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001095
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001096 def SaveNewKeySet(self, keySetName, keySet):
Steven M. Gava052937f2002-02-11 02:20:53 +00001097 """
1098 save a newly created core key set.
1099 keySetName - string, the name of the new key set
1100 keySet - dictionary containing the new key set
1101 """
1102 if not idleConf.userCfg['keys'].has_section(keySetName):
1103 idleConf.userCfg['keys'].add_section(keySetName)
Kurt B. Kaisere0712772007-08-23 05:25:55 +00001104 for event in keySet:
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001105 value = keySet[event]
1106 idleConf.userCfg['keys'].SetOption(keySetName, event, value)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001107
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001108 def SaveNewTheme(self, themeName, theme):
Steven M. Gava052937f2002-02-11 02:20:53 +00001109 """
1110 save a newly created theme.
1111 themeName - string, the name of the new theme
1112 theme - dictionary containing the new theme
1113 """
1114 if not idleConf.userCfg['highlight'].has_section(themeName):
1115 idleConf.userCfg['highlight'].add_section(themeName)
Kurt B. Kaisere0712772007-08-23 05:25:55 +00001116 for element in theme:
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001117 value = theme[element]
1118 idleConf.userCfg['highlight'].SetOption(themeName, element, value)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001119
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001120 def SetUserValue(self, configType, section, item, value):
1121 if idleConf.defaultCfg[configType].has_option(section, item):
1122 if idleConf.defaultCfg[configType].Get(section, item) == value:
Steven M. Gava2d7bb3f2002-01-29 08:35:29 +00001123 #the setting equals a default setting, remove it from user cfg
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001124 return idleConf.userCfg[configType].RemoveOption(section, item)
Steven M. Gava2d7bb3f2002-01-29 08:35:29 +00001125 #if we got here set the option
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001126 return idleConf.userCfg[configType].SetOption(section, item, value)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001127
Steven M. Gava052937f2002-02-11 02:20:53 +00001128 def SaveAllChangedConfigs(self):
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001129 "Save configuration changes to the user config file."
Steven M. Gava0c5bc8c2002-03-27 02:25:44 +00001130 idleConf.userCfg['main'].Save()
Kurt B. Kaisere0712772007-08-23 05:25:55 +00001131 for configType in self.changedItems:
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001132 cfgTypeHasChanges = False
Kurt B. Kaisere0712772007-08-23 05:25:55 +00001133 for section in self.changedItems[configType]:
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001134 if section == 'HelpFiles':
1135 #this section gets completely replaced
1136 idleConf.userCfg['main'].remove_section('HelpFiles')
Kurt B. Kaiser8e92bf72003-01-14 22:03:31 +00001137 cfgTypeHasChanges = True
Kurt B. Kaisere0712772007-08-23 05:25:55 +00001138 for item in self.changedItems[configType][section]:
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001139 value = self.changedItems[configType][section][item]
Terry Jan Reedy4036d872014-08-03 23:02:58 -04001140 if self.SetUserValue(configType, section, item, value):
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001141 cfgTypeHasChanges = True
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001142 if cfgTypeHasChanges:
1143 idleConf.userCfg[configType].Save()
Kurt B. Kaiser5acdf932004-11-16 21:28:36 +00001144 for configType in ['keys', 'highlight']:
1145 # save these even if unchanged!
1146 idleConf.userCfg[configType].Save()
Steven M. Gavaa498af22002-02-01 01:33:36 +00001147 self.ResetChangedItems() #clear the changed items dict
Terry Jan Reedy93f35422015-10-13 22:03:51 -04001148 self.save_all_changed_extensions() # uses a different mechanism
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001149
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001150 def DeactivateCurrentConfig(self):
1151 #Before a config is saved, some cleanup of current
1152 #config must be done - remove the previous keybindings
Kurt B. Kaisere0712772007-08-23 05:25:55 +00001153 winInstances = self.parent.instance_dict.keys()
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001154 for instance in winInstances:
1155 instance.RemoveKeybindings()
1156
Steven M. Gava49745752002-02-18 01:43:11 +00001157 def ActivateConfigChanges(self):
Kurt B. Kaiseracdef852005-01-31 03:34:26 +00001158 "Dynamically apply configuration changes"
Kurt B. Kaisere0712772007-08-23 05:25:55 +00001159 winInstances = self.parent.instance_dict.keys()
Steven M. Gavab77d3432002-03-02 07:16:21 +00001160 for instance in winInstances:
1161 instance.ResetColorizer()
Steven M. Gavab1585412002-03-12 00:21:56 +00001162 instance.ResetFont()
Kurt B. Kaiseracdef852005-01-31 03:34:26 +00001163 instance.set_notabs_indentwidth()
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001164 instance.ApplyKeybindings()
Kurt B. Kaiser8e92bf72003-01-14 22:03:31 +00001165 instance.reset_help_menu_entries()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001166
Steven M. Gava5f28e8f2002-01-21 06:38:21 +00001167 def Cancel(self):
1168 self.destroy()
1169
1170 def Ok(self):
1171 self.Apply()
1172 self.destroy()
1173
1174 def Apply(self):
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001175 self.DeactivateCurrentConfig()
Steven M. Gava052937f2002-02-11 02:20:53 +00001176 self.SaveAllChangedConfigs()
Steven M. Gava49745752002-02-18 01:43:11 +00001177 self.ActivateConfigChanges()
Steven M. Gava5f28e8f2002-01-21 06:38:21 +00001178
1179 def Help(self):
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -04001180 page = self.tabPages._current_page
1181 view_text(self, title='Help for IDLE preferences',
1182 text=help_common+help_pages.get(page, ''))
1183
Terry Jan Reedy93f35422015-10-13 22:03:51 -04001184 def CreatePageExtensions(self):
1185 """Part of the config dialog used for configuring IDLE extensions.
1186
1187 This code is generic - it works for any and all IDLE extensions.
1188
1189 IDLE extensions save their configuration options using idleConf.
Terry Jan Reedyb2f87602015-10-13 22:09:06 -04001190 This code reads the current configuration using idleConf, supplies a
Terry Jan Reedy93f35422015-10-13 22:03:51 -04001191 GUI interface to change the configuration values, and saves the
1192 changes using idleConf.
1193
1194 Not all changes take effect immediately - some may require restarting IDLE.
1195 This depends on each extension's implementation.
1196
1197 All values are treated as text, and it is up to the user to supply
1198 reasonable values. The only exception to this are the 'enable*' options,
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +03001199 which are boolean, and can be toggled with a True/False button.
Terry Jan Reedy93f35422015-10-13 22:03:51 -04001200 """
1201 parent = self.parent
1202 frame = self.tabPages.pages['Extensions'].frame
1203 self.ext_defaultCfg = idleConf.defaultCfg['extensions']
1204 self.ext_userCfg = idleConf.userCfg['extensions']
1205 self.is_int = self.register(is_int)
1206 self.load_extensions()
1207 # create widgets - a listbox shows all available extensions, with the
1208 # controls for the extension selected in the listbox to the right
1209 self.extension_names = StringVar(self)
1210 frame.rowconfigure(0, weight=1)
1211 frame.columnconfigure(2, weight=1)
1212 self.extension_list = Listbox(frame, listvariable=self.extension_names,
1213 selectmode='browse')
1214 self.extension_list.bind('<<ListboxSelect>>', self.extension_selected)
1215 scroll = Scrollbar(frame, command=self.extension_list.yview)
1216 self.extension_list.yscrollcommand=scroll.set
1217 self.details_frame = LabelFrame(frame, width=250, height=250)
1218 self.extension_list.grid(column=0, row=0, sticky='nws')
1219 scroll.grid(column=1, row=0, sticky='ns')
1220 self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0])
1221 frame.configure(padx=10, pady=10)
1222 self.config_frame = {}
1223 self.current_extension = None
1224
1225 self.outerframe = self # TEMPORARY
1226 self.tabbed_page_set = self.extension_list # TEMPORARY
1227
1228 # create the frame holding controls for each extension
1229 ext_names = ''
1230 for ext_name in sorted(self.extensions):
1231 self.create_extension_frame(ext_name)
1232 ext_names = ext_names + '{' + ext_name + '} '
1233 self.extension_names.set(ext_names)
1234 self.extension_list.selection_set(0)
1235 self.extension_selected(None)
1236
1237 def load_extensions(self):
1238 "Fill self.extensions with data from the default and user configs."
1239 self.extensions = {}
1240 for ext_name in idleConf.GetExtensions(active_only=False):
1241 self.extensions[ext_name] = []
1242
1243 for ext_name in self.extensions:
1244 opt_list = sorted(self.ext_defaultCfg.GetOptionList(ext_name))
1245
1246 # bring 'enable' options to the beginning of the list
1247 enables = [opt_name for opt_name in opt_list
1248 if opt_name.startswith('enable')]
1249 for opt_name in enables:
1250 opt_list.remove(opt_name)
1251 opt_list = enables + opt_list
1252
1253 for opt_name in opt_list:
1254 def_str = self.ext_defaultCfg.Get(
1255 ext_name, opt_name, raw=True)
1256 try:
1257 def_obj = {'True':True, 'False':False}[def_str]
1258 opt_type = 'bool'
1259 except KeyError:
1260 try:
1261 def_obj = int(def_str)
1262 opt_type = 'int'
1263 except ValueError:
1264 def_obj = def_str
1265 opt_type = None
1266 try:
1267 value = self.ext_userCfg.Get(
1268 ext_name, opt_name, type=opt_type, raw=True,
1269 default=def_obj)
1270 except ValueError: # Need this until .Get fixed
1271 value = def_obj # bad values overwritten by entry
1272 var = StringVar(self)
1273 var.set(str(value))
1274
1275 self.extensions[ext_name].append({'name': opt_name,
1276 'type': opt_type,
1277 'default': def_str,
1278 'value': value,
1279 'var': var,
1280 })
1281
1282 def extension_selected(self, event):
1283 newsel = self.extension_list.curselection()
1284 if newsel:
1285 newsel = self.extension_list.get(newsel)
1286 if newsel is None or newsel != self.current_extension:
1287 if self.current_extension:
1288 self.details_frame.config(text='')
1289 self.config_frame[self.current_extension].grid_forget()
1290 self.current_extension = None
1291 if newsel:
1292 self.details_frame.config(text=newsel)
1293 self.config_frame[newsel].grid(column=0, row=0, sticky='nsew')
1294 self.current_extension = newsel
1295
1296 def create_extension_frame(self, ext_name):
1297 """Create a frame holding the widgets to configure one extension"""
1298 f = VerticalScrolledFrame(self.details_frame, height=250, width=250)
1299 self.config_frame[ext_name] = f
1300 entry_area = f.interior
1301 # create an entry for each configuration option
1302 for row, opt in enumerate(self.extensions[ext_name]):
1303 # create a row with a label and entry/checkbutton
1304 label = Label(entry_area, text=opt['name'])
1305 label.grid(row=row, column=0, sticky=NW)
1306 var = opt['var']
1307 if opt['type'] == 'bool':
1308 Checkbutton(entry_area, textvariable=var, variable=var,
1309 onvalue='True', offvalue='False',
1310 indicatoron=FALSE, selectcolor='', width=8
1311 ).grid(row=row, column=1, sticky=W, padx=7)
1312 elif opt['type'] == 'int':
1313 Entry(entry_area, textvariable=var, validate='key',
1314 validatecommand=(self.is_int, '%P')
1315 ).grid(row=row, column=1, sticky=NSEW, padx=7)
1316
1317 else:
1318 Entry(entry_area, textvariable=var
1319 ).grid(row=row, column=1, sticky=NSEW, padx=7)
1320 return
1321
1322 def set_extension_value(self, section, opt):
1323 name = opt['name']
1324 default = opt['default']
1325 value = opt['var'].get().strip() or default
1326 opt['var'].set(value)
1327 # if self.defaultCfg.has_section(section):
1328 # Currently, always true; if not, indent to return
1329 if (value == default):
1330 return self.ext_userCfg.RemoveOption(section, name)
1331 # set the option
1332 return self.ext_userCfg.SetOption(section, name, value)
1333
1334 def save_all_changed_extensions(self):
1335 """Save configuration changes to the user config file."""
1336 has_changes = False
1337 for ext_name in self.extensions:
1338 options = self.extensions[ext_name]
1339 for opt in options:
1340 if self.set_extension_value(ext_name, opt):
1341 has_changes = True
1342 if has_changes:
1343 self.ext_userCfg.Save()
1344
1345
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -04001346help_common = '''\
1347When you click either the Apply or Ok buttons, settings in this
1348dialog that are different from IDLE's default are saved in
1349a .idlerc directory in your home directory. Except as noted,
Terry Jan Reedyd0c0f002015-11-12 15:02:57 -05001350these changes apply to all versions of IDLE installed on this
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -04001351machine. Some do not take affect until IDLE is restarted.
1352[Cancel] only cancels changes made since the last save.
1353'''
1354help_pages = {
1355 'Highlighting':'''
1356Highlighting:
Terry Jan Reedyd0c0f002015-11-12 15:02:57 -05001357The IDLE Dark color theme is new in October 2015. It can only
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -04001358be used with older IDLE releases if it is saved as a custom
1359theme, with a different name.
1360'''
1361}
1362
Steven M. Gavac11ccf32001-09-24 09:43:17 +00001363
Terry Jan Reedy93f35422015-10-13 22:03:51 -04001364def is_int(s):
1365 "Return 's is blank or represents an int'"
1366 if not s:
1367 return True
1368 try:
1369 int(s)
1370 return True
1371 except ValueError:
1372 return False
1373
1374
Terry Jan Reedya9421fb2014-10-22 20:15:18 -04001375class VerticalScrolledFrame(Frame):
1376 """A pure Tkinter vertically scrollable frame.
1377
1378 * Use the 'interior' attribute to place widgets inside the scrollable frame
1379 * Construct and pack/place/grid normally
1380 * This frame only allows vertical scrolling
1381 """
1382 def __init__(self, parent, *args, **kw):
1383 Frame.__init__(self, parent, *args, **kw)
1384
1385 # create a canvas object and a vertical scrollbar for scrolling it
1386 vscrollbar = Scrollbar(self, orient=VERTICAL)
1387 vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
1388 canvas = Canvas(self, bd=0, highlightthickness=0,
Terry Jan Reedyd0812292015-10-22 03:27:31 -04001389 yscrollcommand=vscrollbar.set, width=240)
Terry Jan Reedya9421fb2014-10-22 20:15:18 -04001390 canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
1391 vscrollbar.config(command=canvas.yview)
1392
1393 # reset the view
1394 canvas.xview_moveto(0)
1395 canvas.yview_moveto(0)
1396
1397 # create a frame inside the canvas which will be scrolled with it
1398 self.interior = interior = Frame(canvas)
1399 interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)
1400
1401 # track changes to the canvas and frame width and sync them,
1402 # also updating the scrollbar
1403 def _configure_interior(event):
1404 # update the scrollbars to match the size of the inner frame
1405 size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
1406 canvas.config(scrollregion="0 0 %s %s" % size)
Terry Jan Reedya9421fb2014-10-22 20:15:18 -04001407 interior.bind('<Configure>', _configure_interior)
1408
1409 def _configure_canvas(event):
1410 if interior.winfo_reqwidth() != canvas.winfo_width():
1411 # update the inner frame's width to fill the canvas
1412 canvas.itemconfigure(interior_id, width=canvas.winfo_width())
1413 canvas.bind('<Configure>', _configure_canvas)
1414
1415 return
1416
Terry Jan Reedya9421fb2014-10-22 20:15:18 -04001417
Steven M. Gava44d3d1a2001-07-31 06:59:02 +00001418if __name__ == '__main__':
Terry Jan Reedycfa89502014-07-14 23:07:32 -04001419 import unittest
1420 unittest.main('idlelib.idle_test.test_configdialog',
1421 verbosity=2, exit=False)
Terry Jan Reedy2e8234a2014-05-29 01:46:26 -04001422 from idlelib.idle_test.htest import run
Terry Jan Reedy47304c02015-10-20 02:15:28 -04001423 run(ConfigDialog)