blob: 3c29af13763caaab10131f442ae4dc65528a5aa8 [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 Brandl6634bf22008-05-20 07:13:37 +000012from Tkinter import *
13import tkMessageBox, tkColorChooser, tkFont
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000014
Florent Xiclunad630c042010-04-02 07:24:52 +000015from idlelib.configHandler import idleConf
16from idlelib.dynOptionMenuWidget import DynOptionMenu
Florent Xiclunad630c042010-04-02 07:24:52 +000017from idlelib.keybindingDialog import GetKeysDialog
18from idlelib.configSectionNameDialog import GetCfgSectionNameDialog
19from idlelib.configHelpSourceEdit import GetHelpSourceDialog
Terry Jan Reedy7a162072014-10-22 20:15:12 -040020from idlelib.tabbedpages import TabbedPageSet
Terry Jan Reedyc0a053e2015-10-11 22:07:25 -040021from idlelib.textView import view_text
Florent Xiclunad630c042010-04-02 07:24:52 +000022from idlelib import macosxSupport
Terry Jan Reedyc0a053e2015-10-11 22:07:25 -040023
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000024class ConfigDialog(Toplevel):
Kurt B. Kaiseracdef852005-01-31 03:34:26 +000025
Terry Jan Reedycf834762014-10-17 01:31:29 -040026 def __init__(self, parent, title='', _htest=False, _utest=False):
Terry Jan Reedy76916e82014-05-29 01:46:16 -040027 """
28 _htest - bool, change box location when running htest
Terry Jan Reedyaf0dce92014-07-14 23:07:21 -040029 _utest - bool, don't wait_window when running unittest
Terry Jan Reedy76916e82014-05-29 01:46:16 -040030 """
Steven M. Gavad721c482001-07-31 10:46:53 +000031 Toplevel.__init__(self, parent)
Terry Jan Reedy19b7a752014-07-30 19:24:26 -040032 self.parent = parent
Terry Jan Reedyae410862014-08-03 23:02:53 -040033 if _htest:
34 parent.instance_dict = {}
Kurt B. Kaisere3fde8f2007-10-04 03:11:12 +000035 self.wm_withdraw()
36
Steven M. Gavad721c482001-07-31 10:46:53 +000037 self.configure(borderwidth=5)
Terry Jan Reedycf834762014-10-17 01:31:29 -040038 self.title(title or 'IDLE Preferences')
Terry Jan Reedyae410862014-08-03 23:02:53 -040039 self.geometry(
40 "+%d+%d" % (parent.winfo_rootx() + 20,
41 parent.winfo_rooty() + (30 if not _htest else 150)))
Georg Brandl7eb4b7d2005-07-22 21:49:32 +000042 #Theme Elements. Each theme element key is its display name.
Steven M. Gava9dd16b32001-11-03 14:54:25 +000043 #The first value of the tuple is the sample area tag name.
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000044 #The second value is the display name list sort index.
Terry Jan Reedyae410862014-08-03 23:02:53 -040045 self.themeElements={
Terry Jan Reedyc30475e2015-10-02 22:12:09 -040046 'Normal Text': ('normal', '00'),
47 'Python Keywords': ('keyword', '01'),
48 'Python Definitions': ('definition', '02'),
49 'Python Builtins': ('builtin', '03'),
50 'Python Comments': ('comment', '04'),
51 'Python Strings': ('string', '05'),
52 'Selected Text': ('hilite', '06'),
53 'Found Text': ('hit', '07'),
54 'Cursor': ('cursor', '08'),
55 'Editor Breakpoint': ('break', '09'),
56 'Shell Normal Text': ('console', '10'),
57 'Shell Error Text': ('error', '11'),
58 'Shell Stdout Text': ('stdout', '12'),
59 'Shell Stderr Text': ('stderr', '13'),
Kurt B. Kaiser73360a32004-03-08 18:15:31 +000060 }
Steven M. Gavaa498af22002-02-01 01:33:36 +000061 self.ResetChangedItems() #load initial values in changed items dict
Steven M. Gavad721c482001-07-31 10:46:53 +000062 self.CreateWidgets()
Terry Jan Reedyae410862014-08-03 23:02:53 -040063 self.resizable(height=FALSE, width=FALSE)
Steven M. Gavad721c482001-07-31 10:46:53 +000064 self.transient(parent)
65 self.grab_set()
66 self.protocol("WM_DELETE_WINDOW", self.Cancel)
Steven M. Gava2d4e03b2001-12-05 07:54:07 +000067 self.tabPages.focus_set()
Steven M. Gavad721c482001-07-31 10:46:53 +000068 #key bindings for this dialog
Terry Jan Reedyae410862014-08-03 23:02:53 -040069 #self.bind('<Escape>', self.Cancel) #dismiss dialog, no save
70 #self.bind('<Alt-a>', self.Apply) #apply changes, save
71 #self.bind('<F1>', self.Help) #context help
Steven M. Gava429a86a2001-10-23 10:42:12 +000072 self.LoadConfigs()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000073 self.AttachVarCallbacks() #avoid callbacks during LoadConfigs
Kurt B. Kaisere3fde8f2007-10-04 03:11:12 +000074
Terry Jan Reedyaf0dce92014-07-14 23:07:21 -040075 if not _utest:
76 self.wm_deiconify()
77 self.wait_window()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000078
Steven M. Gavad721c482001-07-31 10:46:53 +000079 def CreateWidgets(self):
Kurt B. Kaiser20172f92007-10-30 02:38:54 +000080 self.tabPages = TabbedPageSet(self,
Terry Jan Reedy1c49ec02015-10-13 22:03:44 -040081 page_names=['Fonts/Tabs', 'Highlighting', 'Keys', 'General',
82 'Extensions'])
Terry Jan Reedy23030db2014-10-08 20:29:05 -040083 self.tabPages.pack(side=TOP, expand=TRUE, fill=BOTH)
84 self.CreatePageFontTab()
85 self.CreatePageHighlight()
86 self.CreatePageKeys()
87 self.CreatePageGeneral()
Terry Jan Reedy1c49ec02015-10-13 22:03:44 -040088 self.CreatePageExtensions()
Terry Jan Reedy23030db2014-10-08 20:29:05 -040089 self.create_action_buttons().pack(side=BOTTOM)
Terry Jan Reedyc0a053e2015-10-11 22:07:25 -040090
Terry Jan Reedy23030db2014-10-08 20:29:05 -040091 def create_action_buttons(self):
Ned Deily57847df2014-03-27 20:47:04 -070092 if macosxSupport.isAquaTk():
Ronald Oussorena97063a2009-03-04 21:35:05 +000093 # Changing the default padding on OSX results in unreadable
94 # text in the buttons
Terry Jan Reedyae410862014-08-03 23:02:53 -040095 paddingArgs = {}
Ronald Oussorena97063a2009-03-04 21:35:05 +000096 else:
Terry Jan Reedyae410862014-08-03 23:02:53 -040097 paddingArgs = {'padx':6, 'pady':3}
Terry Jan Reedy7a162072014-10-22 20:15:12 -040098 outer = Frame(self, pady=2)
99 buttons = Frame(outer, pady=2)
Terry Jan Reedyc0a053e2015-10-11 22:07:25 -0400100 for txt, cmd in (
101 ('Ok', self.Ok),
102 ('Apply', self.Apply),
103 ('Cancel', self.Cancel),
104 ('Help', self.Help)):
105 Button(buttons, text=txt, command=cmd, takefocus=FALSE,
106 **paddingArgs).pack(side=LEFT, padx=5)
Terry Jan Reedy7a162072014-10-22 20:15:12 -0400107 # add space above buttons
108 Frame(outer, height=2, borderwidth=0).pack(side=TOP)
109 buttons.pack(side=BOTTOM)
110 return outer
Terry Jan Reedyc0a053e2015-10-11 22:07:25 -0400111
Steven M. Gava60fc7072001-08-04 13:58:22 +0000112 def CreatePageFontTab(self):
Terry Jan Reedy19b7a752014-07-30 19:24:26 -0400113 parent = self.parent
114 self.fontSize = StringVar(parent)
115 self.fontBold = BooleanVar(parent)
116 self.fontName = StringVar(parent)
117 self.spaceNum = IntVar(parent)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400118 self.editFont = tkFont.Font(parent, ('courier', 10, 'normal'))
Terry Jan Reedy19b7a752014-07-30 19:24:26 -0400119
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000120 ##widget creation
121 #body frame
Terry Jan Reedyae410862014-08-03 23:02:53 -0400122 frame = self.tabPages.pages['Fonts/Tabs'].frame
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000123 #body section frames
Terry Jan Reedyae410862014-08-03 23:02:53 -0400124 frameFont = LabelFrame(
125 frame, borderwidth=2, relief=GROOVE, text=' Base Editor Font ')
126 frameIndent = LabelFrame(
127 frame, borderwidth=2, relief=GROOVE, text=' Indentation Width ')
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000128 #frameFont
Terry Jan Reedyae410862014-08-03 23:02:53 -0400129 frameFontName = Frame(frameFont)
130 frameFontParam = Frame(frameFont)
131 labelFontNameTitle = Label(
132 frameFontName, justify=LEFT, text='Font Face :')
133 self.listFontName = Listbox(
134 frameFontName, height=5, takefocus=FALSE, exportselection=FALSE)
135 self.listFontName.bind(
136 '<ButtonRelease-1>', self.OnListFontButtonRelease)
137 scrollFont = Scrollbar(frameFontName)
Steven M. Gavac01e30f2001-08-11 15:48:13 +0000138 scrollFont.config(command=self.listFontName.yview)
139 self.listFontName.config(yscrollcommand=scrollFont.set)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400140 labelFontSizeTitle = Label(frameFontParam, text='Size :')
141 self.optMenuFontSize = DynOptionMenu(
142 frameFontParam, self.fontSize, None, command=self.SetFontSample)
143 checkFontBold = Checkbutton(
144 frameFontParam, variable=self.fontBold, onvalue=1,
145 offvalue=0, text='Bold', command=self.SetFontSample)
146 frameFontSample = Frame(frameFont, relief=SOLID, borderwidth=1)
147 self.labelFontSample = Label(
148 frameFontSample, justify=LEFT, font=self.editFont,
149 text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]')
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000150 #frameIndent
Terry Jan Reedyae410862014-08-03 23:02:53 -0400151 frameIndentSize = Frame(frameIndent)
152 labelSpaceNumTitle = Label(
153 frameIndentSize, justify=LEFT,
154 text='Python Standard: 4 Spaces!')
155 self.scaleSpaceNum = Scale(
156 frameIndentSize, variable=self.spaceNum,
157 orient='horizontal', tickinterval=2, from_=2, to=16)
Terry Jan Reedy19b7a752014-07-30 19:24:26 -0400158
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000159 #widget packing
160 #body
Terry Jan Reedyae410862014-08-03 23:02:53 -0400161 frameFont.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
162 frameIndent.pack(side=LEFT, padx=5, pady=5, fill=Y)
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000163 #frameFont
Terry Jan Reedyae410862014-08-03 23:02:53 -0400164 frameFontName.pack(side=TOP, padx=5, pady=5, fill=X)
165 frameFontParam.pack(side=TOP, padx=5, pady=5, fill=X)
166 labelFontNameTitle.pack(side=TOP, anchor=W)
167 self.listFontName.pack(side=LEFT, expand=TRUE, fill=X)
168 scrollFont.pack(side=LEFT, fill=Y)
169 labelFontSizeTitle.pack(side=LEFT, anchor=W)
170 self.optMenuFontSize.pack(side=LEFT, anchor=W)
171 checkFontBold.pack(side=LEFT, anchor=W, padx=20)
172 frameFontSample.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
173 self.labelFontSample.pack(expand=TRUE, fill=BOTH)
Steven M. Gavaf213ccb2001-08-05 08:00:28 +0000174 #frameIndent
Terry Jan Reedyae410862014-08-03 23:02:53 -0400175 frameIndentSize.pack(side=TOP, fill=X)
176 labelSpaceNumTitle.pack(side=TOP, anchor=W, padx=5)
177 self.scaleSpaceNum.pack(side=TOP, padx=5, fill=X)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000178 return frame
179
180 def CreatePageHighlight(self):
Terry Jan Reedy19b7a752014-07-30 19:24:26 -0400181 parent = self.parent
182 self.builtinTheme = StringVar(parent)
183 self.customTheme = StringVar(parent)
184 self.fgHilite = BooleanVar(parent)
185 self.colour = StringVar(parent)
186 self.fontName = StringVar(parent)
187 self.themeIsBuiltin = BooleanVar(parent)
188 self.highlightTarget = StringVar(parent)
189
Steven M. Gava952d0a52001-08-03 04:43:44 +0000190 ##widget creation
191 #body frame
Terry Jan Reedyae410862014-08-03 23:02:53 -0400192 frame = self.tabPages.pages['Highlighting'].frame
Steven M. Gava952d0a52001-08-03 04:43:44 +0000193 #body section frames
Terry Jan Reedyae410862014-08-03 23:02:53 -0400194 frameCustom = LabelFrame(frame, borderwidth=2, relief=GROOVE,
195 text=' Custom Highlighting ')
196 frameTheme = LabelFrame(frame, borderwidth=2, relief=GROOVE,
197 text=' Highlighting Theme ')
Steven M. Gava952d0a52001-08-03 04:43:44 +0000198 #frameCustom
Terry Jan Reedyae410862014-08-03 23:02:53 -0400199 self.textHighlightSample=Text(
200 frameCustom, relief=SOLID, borderwidth=1,
201 font=('courier', 12, ''), cursor='hand2', width=21, height=11,
202 takefocus=FALSE, highlightthickness=0, wrap=NONE)
Steven M. Gavae16d94b2001-11-03 05:07:28 +0000203 text=self.textHighlightSample
Terry Jan Reedyae410862014-08-03 23:02:53 -0400204 text.bind('<Double-Button-1>', lambda e: 'break')
205 text.bind('<B1-Motion>', lambda e: 'break')
206 textAndTags=(
207 ('#you can click here', 'comment'), ('\n', 'normal'),
208 ('#to choose items', 'comment'), ('\n', 'normal'),
209 ('def', 'keyword'), (' ', 'normal'),
210 ('func', 'definition'), ('(param):\n ', 'normal'),
211 ('"""string"""', 'string'), ('\n var0 = ', 'normal'),
212 ("'string'", 'string'), ('\n var1 = ', 'normal'),
213 ("'selected'", 'hilite'), ('\n var2 = ', 'normal'),
214 ("'found'", 'hit'), ('\n var3 = ', 'normal'),
215 ('list', 'builtin'), ('(', 'normal'),
Terry Jan Reedyc30475e2015-10-02 22:12:09 -0400216 ('None', 'builtin'), (')\n', 'normal'),
217 (' breakpoint("line")', 'break'), ('\n\n', 'normal'),
Terry Jan Reedyae410862014-08-03 23:02:53 -0400218 (' error ', 'error'), (' ', 'normal'),
219 ('cursor |', 'cursor'), ('\n ', 'normal'),
220 ('shell', 'console'), (' ', 'normal'),
221 ('stdout', 'stdout'), (' ', 'normal'),
222 ('stderr', 'stderr'), ('\n', 'normal'))
Steven M. Gava9dd16b32001-11-03 14:54:25 +0000223 for txTa in textAndTags:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400224 text.insert(END, txTa[0], txTa[1])
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400225 for element in self.themeElements:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400226 def tem(event, elem=element):
227 event.widget.winfo_toplevel().highlightTarget.set(elem)
228 text.tag_bind(
229 self.themeElements[element][0], '<ButtonPress-1>', tem)
Steven M. Gavae16d94b2001-11-03 05:07:28 +0000230 text.config(state=DISABLED)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400231 self.frameColourSet = Frame(frameCustom, relief=SOLID, borderwidth=1)
232 frameFgBg = Frame(frameCustom)
233 buttonSetColour = Button(
234 self.frameColourSet, text='Choose Colour for :',
235 command=self.GetColour, highlightthickness=0)
236 self.optMenuHighlightTarget = DynOptionMenu(
237 self.frameColourSet, self.highlightTarget, None,
238 highlightthickness=0) #, command=self.SetHighlightTargetBinding
239 self.radioFg = Radiobutton(
240 frameFgBg, variable=self.fgHilite, value=1,
241 text='Foreground', command=self.SetColourSampleBinding)
242 self.radioBg=Radiobutton(
243 frameFgBg, variable=self.fgHilite, value=0,
244 text='Background', command=self.SetColourSampleBinding)
Steven M. Gava7c017862001-10-29 11:19:46 +0000245 self.fgHilite.set(1)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400246 buttonSaveCustomTheme = Button(
247 frameCustom, text='Save as New Custom Theme',
248 command=self.SaveAsNewTheme)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000249 #frameTheme
Terry Jan Reedyae410862014-08-03 23:02:53 -0400250 labelTypeTitle = Label(frameTheme, text='Select : ')
251 self.radioThemeBuiltin = Radiobutton(
252 frameTheme, variable=self.themeIsBuiltin, value=1,
253 command=self.SetThemeType, text='a Built-in Theme')
254 self.radioThemeCustom = Radiobutton(
255 frameTheme, variable=self.themeIsBuiltin, value=0,
256 command=self.SetThemeType, text='a Custom Theme')
257 self.optMenuThemeBuiltin = DynOptionMenu(
258 frameTheme, self.builtinTheme, None, command=None)
259 self.optMenuThemeCustom=DynOptionMenu(
260 frameTheme, self.customTheme, None, command=None)
261 self.buttonDeleteCustomTheme=Button(
262 frameTheme, text='Delete Custom Theme',
Steven M. Gava49745752002-02-18 01:43:11 +0000263 command=self.DeleteCustomTheme)
Terry Jan Reedy35aa5d02015-11-12 15:02:50 -0500264 self.new_custom_theme = Label(frameTheme, bd=2)
Terry Jan Reedy19b7a752014-07-30 19:24:26 -0400265
Steven M. Gava952d0a52001-08-03 04:43:44 +0000266 ##widget packing
267 #body
Terry Jan Reedyae410862014-08-03 23:02:53 -0400268 frameCustom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
269 frameTheme.pack(side=LEFT, padx=5, pady=5, fill=Y)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000270 #frameCustom
Terry Jan Reedyae410862014-08-03 23:02:53 -0400271 self.frameColourSet.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X)
272 frameFgBg.pack(side=TOP, padx=5, pady=0)
273 self.textHighlightSample.pack(
274 side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
275 buttonSetColour.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=4)
276 self.optMenuHighlightTarget.pack(
277 side=TOP, expand=TRUE, fill=X, padx=8, pady=3)
278 self.radioFg.pack(side=LEFT, anchor=E)
279 self.radioBg.pack(side=RIGHT, anchor=W)
280 buttonSaveCustomTheme.pack(side=BOTTOM, fill=X, padx=5, pady=5)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000281 #frameTheme
Terry Jan Reedyae410862014-08-03 23:02:53 -0400282 labelTypeTitle.pack(side=TOP, anchor=W, padx=5, pady=5)
283 self.radioThemeBuiltin.pack(side=TOP, anchor=W, padx=5)
284 self.radioThemeCustom.pack(side=TOP, anchor=W, padx=5, pady=2)
285 self.optMenuThemeBuiltin.pack(side=TOP, fill=X, padx=5, pady=5)
286 self.optMenuThemeCustom.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5)
287 self.buttonDeleteCustomTheme.pack(side=TOP, fill=X, padx=5, pady=5)
Terry Jan Reedy35aa5d02015-11-12 15:02:50 -0500288 self.new_custom_theme.pack(side=TOP, fill=X, pady=5)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000289 return frame
290
291 def CreatePageKeys(self):
Terry Jan Reedy19b7a752014-07-30 19:24:26 -0400292 parent = self.parent
293 self.bindingTarget = StringVar(parent)
294 self.builtinKeys = StringVar(parent)
295 self.customKeys = StringVar(parent)
296 self.keysAreBuiltin = BooleanVar(parent)
297 self.keyBinding = StringVar(parent)
298
Steven M. Gava60fc7072001-08-04 13:58:22 +0000299 ##widget creation
300 #body frame
Terry Jan Reedyae410862014-08-03 23:02:53 -0400301 frame = self.tabPages.pages['Keys'].frame
Steven M. Gava60fc7072001-08-04 13:58:22 +0000302 #body section frames
Terry Jan Reedyae410862014-08-03 23:02:53 -0400303 frameCustom = LabelFrame(
304 frame, borderwidth=2, relief=GROOVE,
305 text=' Custom Key Bindings ')
306 frameKeySets = LabelFrame(
307 frame, borderwidth=2, relief=GROOVE, text=' Key Set ')
Steven M. Gava60fc7072001-08-04 13:58:22 +0000308 #frameCustom
Terry Jan Reedyae410862014-08-03 23:02:53 -0400309 frameTarget = Frame(frameCustom)
310 labelTargetTitle = Label(frameTarget, text='Action - Key(s)')
311 scrollTargetY = Scrollbar(frameTarget)
312 scrollTargetX = Scrollbar(frameTarget, orient=HORIZONTAL)
313 self.listBindings = Listbox(
314 frameTarget, takefocus=FALSE, exportselection=FALSE)
315 self.listBindings.bind('<ButtonRelease-1>', self.KeyBindingSelected)
Steven M. Gavafacfc092002-01-19 00:29:54 +0000316 scrollTargetY.config(command=self.listBindings.yview)
317 scrollTargetX.config(command=self.listBindings.xview)
318 self.listBindings.config(yscrollcommand=scrollTargetY.set)
319 self.listBindings.config(xscrollcommand=scrollTargetX.set)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400320 self.buttonNewKeys = Button(
321 frameCustom, text='Get New Keys for Selection',
322 command=self.GetNewKeys, state=DISABLED)
Steven M. Gava60fc7072001-08-04 13:58:22 +0000323 #frameKeySets
Kurt B. Kaiser28c7bcf2007-12-28 04:18:01 +0000324 frames = [Frame(frameKeySets, padx=2, pady=2, borderwidth=0)
325 for i in range(2)]
Terry Jan Reedyae410862014-08-03 23:02:53 -0400326 self.radioKeysBuiltin = Radiobutton(
327 frames[0], variable=self.keysAreBuiltin, value=1,
328 command=self.SetKeysType, text='Use a Built-in Key Set')
329 self.radioKeysCustom = Radiobutton(
330 frames[0], variable=self.keysAreBuiltin, value=0,
331 command=self.SetKeysType, text='Use a Custom Key Set')
332 self.optMenuKeysBuiltin = DynOptionMenu(
333 frames[0], self.builtinKeys, None, command=None)
334 self.optMenuKeysCustom = DynOptionMenu(
335 frames[0], self.customKeys, None, command=None)
336 self.buttonDeleteCustomKeys = Button(
337 frames[1], text='Delete Custom Key Set',
Steven M. Gava49745752002-02-18 01:43:11 +0000338 command=self.DeleteCustomKeys)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400339 buttonSaveCustomKeys = Button(
340 frames[1], text='Save as New Custom Key Set',
341 command=self.SaveAsNewKeySet)
Terry Jan Reedy19b7a752014-07-30 19:24:26 -0400342
Steven M. Gava60fc7072001-08-04 13:58:22 +0000343 ##widget packing
344 #body
Terry Jan Reedyae410862014-08-03 23:02:53 -0400345 frameCustom.pack(side=BOTTOM, padx=5, pady=5, expand=TRUE, fill=BOTH)
346 frameKeySets.pack(side=BOTTOM, padx=5, pady=5, fill=BOTH)
Steven M. Gava60fc7072001-08-04 13:58:22 +0000347 #frameCustom
Terry Jan Reedyae410862014-08-03 23:02:53 -0400348 self.buttonNewKeys.pack(side=BOTTOM, fill=X, padx=5, pady=5)
349 frameTarget.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
Steven M. Gavafacfc092002-01-19 00:29:54 +0000350 #frame target
Terry Jan Reedyae410862014-08-03 23:02:53 -0400351 frameTarget.columnconfigure(0, weight=1)
352 frameTarget.rowconfigure(1, weight=1)
353 labelTargetTitle.grid(row=0, column=0, columnspan=2, sticky=W)
354 self.listBindings.grid(row=1, column=0, sticky=NSEW)
355 scrollTargetY.grid(row=1, column=1, sticky=NS)
356 scrollTargetX.grid(row=2, column=0, sticky=EW)
Steven M. Gava60fc7072001-08-04 13:58:22 +0000357 #frameKeySets
Kurt B. Kaiser28c7bcf2007-12-28 04:18:01 +0000358 self.radioKeysBuiltin.grid(row=0, column=0, sticky=W+NS)
359 self.radioKeysCustom.grid(row=1, column=0, sticky=W+NS)
360 self.optMenuKeysBuiltin.grid(row=0, column=1, sticky=NSEW)
361 self.optMenuKeysCustom.grid(row=1, column=1, sticky=NSEW)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400362 self.buttonDeleteCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2)
363 buttonSaveCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2)
Kurt B. Kaiser28c7bcf2007-12-28 04:18:01 +0000364 frames[0].pack(side=TOP, fill=BOTH, expand=True)
365 frames[1].pack(side=TOP, fill=X, expand=True, pady=2)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000366 return frame
367
368 def CreatePageGeneral(self):
Terry Jan Reedy19b7a752014-07-30 19:24:26 -0400369 parent = self.parent
370 self.winWidth = StringVar(parent)
371 self.winHeight = StringVar(parent)
Terry Jan Reedy19b7a752014-07-30 19:24:26 -0400372 self.startupEdit = IntVar(parent)
373 self.autoSave = IntVar(parent)
374 self.encoding = StringVar(parent)
375 self.userHelpBrowser = BooleanVar(parent)
376 self.helpBrowser = StringVar(parent)
377
Steven M. Gava230e5782001-08-07 03:28:25 +0000378 #widget creation
379 #body
Terry Jan Reedyae410862014-08-03 23:02:53 -0400380 frame = self.tabPages.pages['General'].frame
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000381 #body section frames
Terry Jan Reedyae410862014-08-03 23:02:53 -0400382 frameRun = LabelFrame(frame, borderwidth=2, relief=GROOVE,
383 text=' Startup Preferences ')
384 frameSave = LabelFrame(frame, borderwidth=2, relief=GROOVE,
385 text=' Autosave Preferences ')
386 frameWinSize = Frame(frame, borderwidth=2, relief=GROOVE)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400387 frameEncoding = Frame(frame, borderwidth=2, relief=GROOVE)
388 frameHelp = LabelFrame(frame, borderwidth=2, relief=GROOVE,
389 text=' Additional Help Sources ')
Steven M. Gava230e5782001-08-07 03:28:25 +0000390 #frameRun
Terry Jan Reedyae410862014-08-03 23:02:53 -0400391 labelRunChoiceTitle = Label(frameRun, text='At Startup')
392 radioStartupEdit = Radiobutton(
393 frameRun, variable=self.startupEdit, value=1,
394 command=self.SetKeysType, text="Open Edit Window")
395 radioStartupShell = Radiobutton(
396 frameRun, variable=self.startupEdit, value=0,
397 command=self.SetKeysType, text='Open Shell Window')
Kurt B. Kaiser6c638b62003-05-26 06:23:10 +0000398 #frameSave
Terry Jan Reedyae410862014-08-03 23:02:53 -0400399 labelRunSaveTitle = Label(frameSave, text='At Start of Run (F5) ')
400 radioSaveAsk = Radiobutton(
401 frameSave, variable=self.autoSave, value=0,
402 command=self.SetKeysType, text="Prompt to Save")
403 radioSaveAuto = Radiobutton(
404 frameSave, variable=self.autoSave, value=1,
405 command=self.SetKeysType, text='No Prompt')
Steven M. Gava230e5782001-08-07 03:28:25 +0000406 #frameWinSize
Terry Jan Reedyae410862014-08-03 23:02:53 -0400407 labelWinSizeTitle = Label(
408 frameWinSize, text='Initial Window Size (in characters)')
409 labelWinWidthTitle = Label(frameWinSize, text='Width')
410 entryWinWidth = Entry(
411 frameWinSize, textvariable=self.winWidth, width=3)
412 labelWinHeightTitle = Label(frameWinSize, text='Height')
413 entryWinHeight = Entry(
414 frameWinSize, textvariable=self.winHeight, width=3)
Kurt B. Kaisera053f332003-05-10 00:49:56 +0000415 #frameEncoding
Terry Jan Reedyae410862014-08-03 23:02:53 -0400416 labelEncodingTitle = Label(
417 frameEncoding, text="Default Source Encoding")
418 radioEncLocale = Radiobutton(
419 frameEncoding, variable=self.encoding,
420 value="locale", text="Locale-defined")
421 radioEncUTF8 = Radiobutton(
422 frameEncoding, variable=self.encoding,
423 value="utf-8", text="UTF-8")
424 radioEncNone = Radiobutton(
425 frameEncoding, variable=self.encoding,
426 value="none", text="None")
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000427 #frameHelp
Terry Jan Reedyae410862014-08-03 23:02:53 -0400428 frameHelpList = Frame(frameHelp)
429 frameHelpListButtons = Frame(frameHelpList)
430 scrollHelpList = Scrollbar(frameHelpList)
431 self.listHelp = Listbox(
432 frameHelpList, height=5, takefocus=FALSE,
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000433 exportselection=FALSE)
434 scrollHelpList.config(command=self.listHelp.yview)
435 self.listHelp.config(yscrollcommand=scrollHelpList.set)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400436 self.listHelp.bind('<ButtonRelease-1>', self.HelpSourceSelected)
437 self.buttonHelpListEdit = Button(
438 frameHelpListButtons, text='Edit', state=DISABLED,
439 width=8, command=self.HelpListItemEdit)
440 self.buttonHelpListAdd = Button(
441 frameHelpListButtons, text='Add',
442 width=8, command=self.HelpListItemAdd)
443 self.buttonHelpListRemove = Button(
444 frameHelpListButtons, text='Remove', state=DISABLED,
445 width=8, command=self.HelpListItemRemove)
Terry Jan Reedy19b7a752014-07-30 19:24:26 -0400446
Steven M. Gava230e5782001-08-07 03:28:25 +0000447 #widget packing
448 #body
Terry Jan Reedyae410862014-08-03 23:02:53 -0400449 frameRun.pack(side=TOP, padx=5, pady=5, fill=X)
450 frameSave.pack(side=TOP, padx=5, pady=5, fill=X)
451 frameWinSize.pack(side=TOP, padx=5, pady=5, fill=X)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400452 frameEncoding.pack(side=TOP, padx=5, pady=5, fill=X)
453 frameHelp.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
Steven M. Gava230e5782001-08-07 03:28:25 +0000454 #frameRun
Terry Jan Reedyae410862014-08-03 23:02:53 -0400455 labelRunChoiceTitle.pack(side=LEFT, anchor=W, padx=5, pady=5)
456 radioStartupShell.pack(side=RIGHT, anchor=W, padx=5, pady=5)
457 radioStartupEdit.pack(side=RIGHT, anchor=W, padx=5, pady=5)
Kurt B. Kaiser6c638b62003-05-26 06:23:10 +0000458 #frameSave
Terry Jan Reedyae410862014-08-03 23:02:53 -0400459 labelRunSaveTitle.pack(side=LEFT, anchor=W, padx=5, pady=5)
460 radioSaveAuto.pack(side=RIGHT, anchor=W, padx=5, pady=5)
461 radioSaveAsk.pack(side=RIGHT, anchor=W, padx=5, pady=5)
Steven M. Gava230e5782001-08-07 03:28:25 +0000462 #frameWinSize
Terry Jan Reedyae410862014-08-03 23:02:53 -0400463 labelWinSizeTitle.pack(side=LEFT, anchor=W, padx=5, pady=5)
464 entryWinHeight.pack(side=RIGHT, anchor=E, padx=10, pady=5)
465 labelWinHeightTitle.pack(side=RIGHT, anchor=E, pady=5)
466 entryWinWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5)
467 labelWinWidthTitle.pack(side=RIGHT, anchor=E, pady=5)
Kurt B. Kaisera053f332003-05-10 00:49:56 +0000468 #frameEncoding
Terry Jan Reedyae410862014-08-03 23:02:53 -0400469 labelEncodingTitle.pack(side=LEFT, anchor=W, padx=5, pady=5)
470 radioEncNone.pack(side=RIGHT, anchor=E, pady=5)
471 radioEncUTF8.pack(side=RIGHT, anchor=E, pady=5)
472 radioEncLocale.pack(side=RIGHT, anchor=E, pady=5)
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000473 #frameHelp
Terry Jan Reedyae410862014-08-03 23:02:53 -0400474 frameHelpListButtons.pack(side=RIGHT, padx=5, pady=5, fill=Y)
475 frameHelpList.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
476 scrollHelpList.pack(side=RIGHT, anchor=W, fill=Y)
477 self.listHelp.pack(side=LEFT, anchor=E, expand=TRUE, fill=BOTH)
478 self.buttonHelpListEdit.pack(side=TOP, anchor=W, pady=5)
479 self.buttonHelpListAdd.pack(side=TOP, anchor=W)
480 self.buttonHelpListRemove.pack(side=TOP, anchor=W, pady=5)
Steven M. Gava952d0a52001-08-03 04:43:44 +0000481 return frame
482
Steven M. Gavac112cd82002-01-22 05:56:40 +0000483 def AttachVarCallbacks(self):
Terry Jan Reedy12352142015-08-01 18:57:27 -0400484 self.fontSize.trace_variable('w', self.VarChanged_font)
485 self.fontName.trace_variable('w', self.VarChanged_font)
486 self.fontBold.trace_variable('w', self.VarChanged_font)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400487 self.spaceNum.trace_variable('w', self.VarChanged_spaceNum)
488 self.colour.trace_variable('w', self.VarChanged_colour)
489 self.builtinTheme.trace_variable('w', self.VarChanged_builtinTheme)
490 self.customTheme.trace_variable('w', self.VarChanged_customTheme)
491 self.themeIsBuiltin.trace_variable('w', self.VarChanged_themeIsBuiltin)
492 self.highlightTarget.trace_variable('w', self.VarChanged_highlightTarget)
493 self.keyBinding.trace_variable('w', self.VarChanged_keyBinding)
494 self.builtinKeys.trace_variable('w', self.VarChanged_builtinKeys)
495 self.customKeys.trace_variable('w', self.VarChanged_customKeys)
496 self.keysAreBuiltin.trace_variable('w', self.VarChanged_keysAreBuiltin)
497 self.winWidth.trace_variable('w', self.VarChanged_winWidth)
498 self.winHeight.trace_variable('w', self.VarChanged_winHeight)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400499 self.startupEdit.trace_variable('w', self.VarChanged_startupEdit)
500 self.autoSave.trace_variable('w', self.VarChanged_autoSave)
501 self.encoding.trace_variable('w', self.VarChanged_encoding)
Steven M. Gava052937f2002-02-11 02:20:53 +0000502
Terry Jan Reedy0825e632016-05-16 22:27:22 -0400503 def remove_var_callbacks(self):
504 for var in (
505 self.fontSize, self.fontName, self.fontBold,
506 self.spaceNum, self.colour, self.builtinTheme,
507 self.customTheme, self.themeIsBuiltin, self.highlightTarget,
508 self.keyBinding, self.builtinKeys, self.customKeys,
509 self.keysAreBuiltin, self.winWidth, self.winHeight,
510 self.startupEdit, self.autoSave, self.encoding,):
511 var.trace_vdelete('w', var.trace_vinfo()[0][1])
512
Terry Jan Reedy12352142015-08-01 18:57:27 -0400513 def VarChanged_font(self, *params):
514 '''When one font attribute changes, save them all, as they are
515 not independent from each other. In particular, when we are
516 overriding the default font, we need to write out everything.
517 '''
Terry Jan Reedyae410862014-08-03 23:02:53 -0400518 value = self.fontName.get()
519 self.AddChangedItem('main', 'EditorWindow', 'font', value)
Terry Jan Reedy12352142015-08-01 18:57:27 -0400520 value = self.fontSize.get()
521 self.AddChangedItem('main', 'EditorWindow', 'font-size', value)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400522 value = self.fontBold.get()
523 self.AddChangedItem('main', 'EditorWindow', 'font-bold', value)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000524
Terry Jan Reedyae410862014-08-03 23:02:53 -0400525 def VarChanged_spaceNum(self, *params):
526 value = self.spaceNum.get()
527 self.AddChangedItem('main', 'Indent', 'num-spaces', value)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000528
Terry Jan Reedyae410862014-08-03 23:02:53 -0400529 def VarChanged_colour(self, *params):
Steven M. Gava052937f2002-02-11 02:20:53 +0000530 self.OnNewColourSet()
531
Terry Jan Reedyae410862014-08-03 23:02:53 -0400532 def VarChanged_builtinTheme(self, *params):
533 value = self.builtinTheme.get()
Terry Jan Reedy9f37eae2015-10-04 00:30:59 -0400534 if value == 'IDLE Dark':
Terry Jan Reedy35aa5d02015-11-12 15:02:50 -0500535 if idleConf.GetOption('main', 'Theme', 'name') != 'IDLE New':
536 self.AddChangedItem('main', 'Theme', 'name', 'IDLE Classic')
537 self.AddChangedItem('main', 'Theme', 'name2', value)
538 self.new_custom_theme.config(text='New theme, see Help',
539 fg='#500000')
540 else:
541 self.AddChangedItem('main', 'Theme', 'name', value)
542 self.AddChangedItem('main', 'Theme', 'name2', '')
543 self.new_custom_theme.config(text='', fg='black')
Steven M. Gava052937f2002-02-11 02:20:53 +0000544 self.PaintThemeSample()
545
Terry Jan Reedyae410862014-08-03 23:02:53 -0400546 def VarChanged_customTheme(self, *params):
547 value = self.customTheme.get()
Steven M. Gava49745752002-02-18 01:43:11 +0000548 if value != '- no custom themes -':
Terry Jan Reedyae410862014-08-03 23:02:53 -0400549 self.AddChangedItem('main', 'Theme', 'name', value)
Steven M. Gava49745752002-02-18 01:43:11 +0000550 self.PaintThemeSample()
Steven M. Gava052937f2002-02-11 02:20:53 +0000551
Terry Jan Reedyae410862014-08-03 23:02:53 -0400552 def VarChanged_themeIsBuiltin(self, *params):
553 value = self.themeIsBuiltin.get()
554 self.AddChangedItem('main', 'Theme', 'default', value)
Steven M. Gavaf31eec02002-03-05 00:25:58 +0000555 if value:
556 self.VarChanged_builtinTheme()
557 else:
558 self.VarChanged_customTheme()
Steven M. Gava052937f2002-02-11 02:20:53 +0000559
Terry Jan Reedyae410862014-08-03 23:02:53 -0400560 def VarChanged_highlightTarget(self, *params):
Steven M. Gava052937f2002-02-11 02:20:53 +0000561 self.SetHighlightTarget()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000562
Terry Jan Reedyae410862014-08-03 23:02:53 -0400563 def VarChanged_keyBinding(self, *params):
564 value = self.keyBinding.get()
565 keySet = self.customKeys.get()
566 event = self.listBindings.get(ANCHOR).split()[0]
Steven M. Gavaa498af22002-02-01 01:33:36 +0000567 if idleConf.IsCoreBinding(event):
568 #this is a core keybinding
Terry Jan Reedyae410862014-08-03 23:02:53 -0400569 self.AddChangedItem('keys', keySet, event, value)
Steven M. Gavaa498af22002-02-01 01:33:36 +0000570 else: #this is an extension key binding
Terry Jan Reedyae410862014-08-03 23:02:53 -0400571 extName = idleConf.GetExtnNameForEvent(event)
572 extKeybindSection = extName + '_cfgBindings'
573 self.AddChangedItem('extensions', extKeybindSection, event, value)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000574
Terry Jan Reedyae410862014-08-03 23:02:53 -0400575 def VarChanged_builtinKeys(self, *params):
576 value = self.builtinKeys.get()
577 self.AddChangedItem('main', 'Keys', 'name', value)
Steven M. Gava052937f2002-02-11 02:20:53 +0000578 self.LoadKeysList(value)
579
Terry Jan Reedyae410862014-08-03 23:02:53 -0400580 def VarChanged_customKeys(self, *params):
581 value = self.customKeys.get()
Steven M. Gava49745752002-02-18 01:43:11 +0000582 if value != '- no custom keys -':
Terry Jan Reedyae410862014-08-03 23:02:53 -0400583 self.AddChangedItem('main', 'Keys', 'name', value)
Steven M. Gava49745752002-02-18 01:43:11 +0000584 self.LoadKeysList(value)
Steven M. Gava052937f2002-02-11 02:20:53 +0000585
Terry Jan Reedyae410862014-08-03 23:02:53 -0400586 def VarChanged_keysAreBuiltin(self, *params):
587 value = self.keysAreBuiltin.get()
588 self.AddChangedItem('main', 'Keys', 'default', value)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000589 if value:
Steven M. Gavaf31eec02002-03-05 00:25:58 +0000590 self.VarChanged_builtinKeys()
Steven M. Gava052937f2002-02-11 02:20:53 +0000591 else:
Steven M. Gavaf31eec02002-03-05 00:25:58 +0000592 self.VarChanged_customKeys()
Steven M. Gava052937f2002-02-11 02:20:53 +0000593
Terry Jan Reedyae410862014-08-03 23:02:53 -0400594 def VarChanged_winWidth(self, *params):
595 value = self.winWidth.get()
596 self.AddChangedItem('main', 'EditorWindow', 'width', value)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000597
Terry Jan Reedyae410862014-08-03 23:02:53 -0400598 def VarChanged_winHeight(self, *params):
599 value = self.winHeight.get()
600 self.AddChangedItem('main', 'EditorWindow', 'height', value)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000601
Terry Jan Reedyae410862014-08-03 23:02:53 -0400602 def VarChanged_startupEdit(self, *params):
603 value = self.startupEdit.get()
604 self.AddChangedItem('main', 'General', 'editor-on-startup', value)
Steven M. Gavac112cd82002-01-22 05:56:40 +0000605
Terry Jan Reedyae410862014-08-03 23:02:53 -0400606 def VarChanged_autoSave(self, *params):
607 value = self.autoSave.get()
608 self.AddChangedItem('main', 'General', 'autosave', value)
Kurt B. Kaiser6c638b62003-05-26 06:23:10 +0000609
Terry Jan Reedyae410862014-08-03 23:02:53 -0400610 def VarChanged_encoding(self, *params):
611 value = self.encoding.get()
612 self.AddChangedItem('main', 'EditorWindow', 'encoding', value)
Kurt B. Kaisera053f332003-05-10 00:49:56 +0000613
Steven M. Gavaa498af22002-02-01 01:33:36 +0000614 def ResetChangedItems(self):
Steven M. Gavab77d3432002-03-02 07:16:21 +0000615 #When any config item is changed in this dialog, an entry
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000616 #should be made in the relevant section (config type) of this
617 #dictionary. The key should be the config file section name and the
Steven M. Gavaa498af22002-02-01 01:33:36 +0000618 #value a dictionary, whose key:value pairs are item=value pairs for
619 #that config file section.
Terry Jan Reedyae410862014-08-03 23:02:53 -0400620 self.changedItems = {'main':{}, 'highlight':{}, 'keys':{},
621 'extensions':{}}
Steven M. Gavaa498af22002-02-01 01:33:36 +0000622
Terry Jan Reedyae410862014-08-03 23:02:53 -0400623 def AddChangedItem(self, typ, section, item, value):
624 value = str(value) #make sure we use a string
625 if section not in self.changedItems[typ]:
626 self.changedItems[typ][section] = {}
627 self.changedItems[typ][section][item] = value
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000628
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000629 def GetDefaultItems(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400630 dItems={'main':{}, 'highlight':{}, 'keys':{}, 'extensions':{}}
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400631 for configType in dItems:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400632 sections = idleConf.GetSectionList('default', configType)
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000633 for section in sections:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400634 dItems[configType][section] = {}
635 options = idleConf.defaultCfg[configType].GetOptionList(section)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000636 for option in options:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400637 dItems[configType][section][option] = (
638 idleConf.defaultCfg[configType].Get(section, option))
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000639 return dItems
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000640
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000641 def SetThemeType(self):
642 if self.themeIsBuiltin.get():
643 self.optMenuThemeBuiltin.config(state=NORMAL)
644 self.optMenuThemeCustom.config(state=DISABLED)
645 self.buttonDeleteCustomTheme.config(state=DISABLED)
646 else:
647 self.optMenuThemeBuiltin.config(state=DISABLED)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000648 self.radioThemeCustom.config(state=NORMAL)
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000649 self.optMenuThemeCustom.config(state=NORMAL)
650 self.buttonDeleteCustomTheme.config(state=NORMAL)
651
652 def SetKeysType(self):
Steven M. Gava052937f2002-02-11 02:20:53 +0000653 if self.keysAreBuiltin.get():
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000654 self.optMenuKeysBuiltin.config(state=NORMAL)
655 self.optMenuKeysCustom.config(state=DISABLED)
656 self.buttonDeleteCustomKeys.config(state=DISABLED)
657 else:
658 self.optMenuKeysBuiltin.config(state=DISABLED)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000659 self.radioKeysCustom.config(state=NORMAL)
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000660 self.optMenuKeysCustom.config(state=NORMAL)
661 self.buttonDeleteCustomKeys.config(state=NORMAL)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000662
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000663 def GetNewKeys(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400664 listIndex = self.listBindings.index(ANCHOR)
665 binding = self.listBindings.get(listIndex)
666 bindName = binding.split()[0] #first part, up to first space
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000667 if self.keysAreBuiltin.get():
Terry Jan Reedyae410862014-08-03 23:02:53 -0400668 currentKeySetName = self.builtinKeys.get()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000669 else:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400670 currentKeySetName = self.customKeys.get()
671 currentBindings = idleConf.GetCurrentKeySet()
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400672 if currentKeySetName in self.changedItems['keys']: #unsaved changes
Terry Jan Reedyae410862014-08-03 23:02:53 -0400673 keySetChanges = self.changedItems['keys'][currentKeySetName]
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400674 for event in keySetChanges:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400675 currentBindings[event] = keySetChanges[event].split()
676 currentKeySequences = currentBindings.values()
677 newKeys = GetKeysDialog(self, 'Get New Keys', bindName,
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000678 currentKeySequences).result
679 if newKeys: #new keys were specified
Steven M. Gava052937f2002-02-11 02:20:53 +0000680 if self.keysAreBuiltin.get(): #current key set is a built-in
Terry Jan Reedyae410862014-08-03 23:02:53 -0400681 message = ('Your changes will be saved as a new Custom Key Set.'
682 ' Enter a name for your new Custom Key Set below.')
683 newKeySet = self.GetNewKeysName(message)
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000684 if not newKeySet: #user cancelled custom key set creation
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000685 self.listBindings.select_set(listIndex)
686 self.listBindings.select_anchor(listIndex)
687 return
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000688 else: #create new custom key set based on previously active key set
689 self.CreateNewKeySet(newKeySet)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000690 self.listBindings.delete(listIndex)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400691 self.listBindings.insert(listIndex, bindName+' - '+newKeys)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000692 self.listBindings.select_set(listIndex)
693 self.listBindings.select_anchor(listIndex)
Steven M. Gava052937f2002-02-11 02:20:53 +0000694 self.keyBinding.set(newKeys)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000695 else:
696 self.listBindings.select_set(listIndex)
697 self.listBindings.select_anchor(listIndex)
698
Terry Jan Reedyae410862014-08-03 23:02:53 -0400699 def GetNewKeysName(self, message):
700 usedNames = (idleConf.GetSectionList('user', 'keys') +
701 idleConf.GetSectionList('default', 'keys'))
702 newKeySet = GetCfgSectionNameDialog(
703 self, 'New Custom Key Set', message, usedNames).result
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000704 return newKeySet
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000705
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000706 def SaveAsNewKeySet(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400707 newKeysName = self.GetNewKeysName('New Key Set Name:')
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000708 if newKeysName:
709 self.CreateNewKeySet(newKeysName)
710
Terry Jan Reedyae410862014-08-03 23:02:53 -0400711 def KeyBindingSelected(self, event):
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000712 self.buttonNewKeys.config(state=NORMAL)
713
Terry Jan Reedyae410862014-08-03 23:02:53 -0400714 def CreateNewKeySet(self, newKeySetName):
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000715 #creates new custom key set based on the previously active key set,
716 #and makes the new key set active
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000717 if self.keysAreBuiltin.get():
Terry Jan Reedyae410862014-08-03 23:02:53 -0400718 prevKeySetName = self.builtinKeys.get()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000719 else:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400720 prevKeySetName = self.customKeys.get()
721 prevKeys = idleConf.GetCoreKeys(prevKeySetName)
722 newKeys = {}
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400723 for event in prevKeys: #add key set to changed items
Terry Jan Reedyae410862014-08-03 23:02:53 -0400724 eventName = event[2:-2] #trim off the angle brackets
725 binding = ' '.join(prevKeys[event])
726 newKeys[eventName] = binding
Steven M. Gava052937f2002-02-11 02:20:53 +0000727 #handle any unsaved changes to prev key set
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400728 if prevKeySetName in self.changedItems['keys']:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400729 keySetChanges = self.changedItems['keys'][prevKeySetName]
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400730 for event in keySetChanges:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400731 newKeys[event] = keySetChanges[event]
Steven M. Gava052937f2002-02-11 02:20:53 +0000732 #save the new theme
Terry Jan Reedyae410862014-08-03 23:02:53 -0400733 self.SaveNewKeySet(newKeySetName, newKeys)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000734 #change gui over to the new key set
Terry Jan Reedyae410862014-08-03 23:02:53 -0400735 customKeyList = idleConf.GetSectionList('user', 'keys')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000736 customKeyList.sort()
Terry Jan Reedyae410862014-08-03 23:02:53 -0400737 self.optMenuKeysCustom.SetMenu(customKeyList, newKeySetName)
Steven M. Gava052937f2002-02-11 02:20:53 +0000738 self.keysAreBuiltin.set(0)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000739 self.SetKeysType()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000740
Terry Jan Reedyae410862014-08-03 23:02:53 -0400741 def LoadKeysList(self, keySetName):
742 reselect = 0
743 newKeySet = 0
Steven M. Gava052937f2002-02-11 02:20:53 +0000744 if self.listBindings.curselection():
Terry Jan Reedyae410862014-08-03 23:02:53 -0400745 reselect = 1
746 listIndex = self.listBindings.index(ANCHOR)
747 keySet = idleConf.GetKeySet(keySetName)
748 bindNames = keySet.keys()
Steven M. Gava052937f2002-02-11 02:20:53 +0000749 bindNames.sort()
Terry Jan Reedyae410862014-08-03 23:02:53 -0400750 self.listBindings.delete(0, END)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000751 for bindName in bindNames:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400752 key = ' '.join(keySet[bindName]) #make key(s) into a string
753 bindName = bindName[2:-2] #trim off the angle brackets
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400754 if keySetName in self.changedItems['keys']:
Steven M. Gava052937f2002-02-11 02:20:53 +0000755 #handle any unsaved changes to this key set
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400756 if bindName in self.changedItems['keys'][keySetName]:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400757 key = self.changedItems['keys'][keySetName][bindName]
Steven M. Gava052937f2002-02-11 02:20:53 +0000758 self.listBindings.insert(END, bindName+' - '+key)
Steven M. Gava052937f2002-02-11 02:20:53 +0000759 if reselect:
760 self.listBindings.see(listIndex)
761 self.listBindings.select_set(listIndex)
762 self.listBindings.select_anchor(listIndex)
763
Steven M. Gava49745752002-02-18 01:43:11 +0000764 def DeleteCustomKeys(self):
765 keySetName=self.customKeys.get()
Terry Jan Reedyae410862014-08-03 23:02:53 -0400766 delmsg = 'Are you sure you wish to delete the key set %r ?'
767 if not tkMessageBox.askyesno(
768 'Delete Key Set', delmsg % keySetName, parent=self):
Steven M. Gava49745752002-02-18 01:43:11 +0000769 return
Terry Jan Reedy92390ab2016-06-14 00:53:18 -0400770 self.DeactivateCurrentConfig()
Steven M. Gava49745752002-02-18 01:43:11 +0000771 #remove key set from config
772 idleConf.userCfg['keys'].remove_section(keySetName)
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000773 if keySetName in self.changedItems['keys']:
Steven M. Gava49745752002-02-18 01:43:11 +0000774 del(self.changedItems['keys'][keySetName])
775 #write changes
776 idleConf.userCfg['keys'].Save()
777 #reload user key set list
Terry Jan Reedyae410862014-08-03 23:02:53 -0400778 itemList = idleConf.GetSectionList('user', 'keys')
Steven M. Gava49745752002-02-18 01:43:11 +0000779 itemList.sort()
780 if not itemList:
781 self.radioKeysCustom.config(state=DISABLED)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400782 self.optMenuKeysCustom.SetMenu(itemList, '- no custom keys -')
Steven M. Gava49745752002-02-18 01:43:11 +0000783 else:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400784 self.optMenuKeysCustom.SetMenu(itemList, itemList[0])
Steven M. Gava49745752002-02-18 01:43:11 +0000785 #revert to default key set
Terry Jan Reedyae410862014-08-03 23:02:53 -0400786 self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys', 'default'))
787 self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys', 'name'))
Steven M. Gava49745752002-02-18 01:43:11 +0000788 #user can't back out of these changes, they must be applied now
Terry Jan Reedy92390ab2016-06-14 00:53:18 -0400789 self.SaveAllChangedConfigs()
790 self.ActivateConfigChanges()
Steven M. Gava49745752002-02-18 01:43:11 +0000791 self.SetKeysType()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000792
Steven M. Gava49745752002-02-18 01:43:11 +0000793 def DeleteCustomTheme(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400794 themeName = self.customTheme.get()
795 delmsg = 'Are you sure you wish to delete the theme %r ?'
796 if not tkMessageBox.askyesno(
797 'Delete Theme', delmsg % themeName, parent=self):
Steven M. Gava49745752002-02-18 01:43:11 +0000798 return
Terry Jan Reedy92390ab2016-06-14 00:53:18 -0400799 self.DeactivateCurrentConfig()
Steven M. Gava49745752002-02-18 01:43:11 +0000800 #remove theme from config
801 idleConf.userCfg['highlight'].remove_section(themeName)
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000802 if themeName in self.changedItems['highlight']:
Steven M. Gava49745752002-02-18 01:43:11 +0000803 del(self.changedItems['highlight'][themeName])
804 #write changes
805 idleConf.userCfg['highlight'].Save()
806 #reload user theme list
Terry Jan Reedyae410862014-08-03 23:02:53 -0400807 itemList = idleConf.GetSectionList('user', 'highlight')
Steven M. Gava49745752002-02-18 01:43:11 +0000808 itemList.sort()
809 if not itemList:
810 self.radioThemeCustom.config(state=DISABLED)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400811 self.optMenuThemeCustom.SetMenu(itemList, '- no custom themes -')
Steven M. Gava49745752002-02-18 01:43:11 +0000812 else:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400813 self.optMenuThemeCustom.SetMenu(itemList, itemList[0])
Steven M. Gava49745752002-02-18 01:43:11 +0000814 #revert to default theme
Terry Jan Reedyae410862014-08-03 23:02:53 -0400815 self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme', 'default'))
816 self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme', 'name'))
Steven M. Gava49745752002-02-18 01:43:11 +0000817 #user can't back out of these changes, they must be applied now
Terry Jan Reedy92390ab2016-06-14 00:53:18 -0400818 self.SaveAllChangedConfigs()
819 self.ActivateConfigChanges()
Steven M. Gava49745752002-02-18 01:43:11 +0000820 self.SetThemeType()
821
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000822 def GetColour(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400823 target = self.highlightTarget.get()
824 prevColour = self.frameColourSet.cget('bg')
825 rgbTuplet, colourString = tkColorChooser.askcolor(
826 parent=self, title='Pick new colour for : '+target,
827 initialcolor=prevColour)
828 if colourString and (colourString != prevColour):
Steven M. Gava052937f2002-02-11 02:20:53 +0000829 #user didn't cancel, and they chose a new colour
Terry Jan Reedyae410862014-08-03 23:02:53 -0400830 if self.themeIsBuiltin.get(): #current theme is a built-in
831 message = ('Your changes will be saved as a new Custom Theme. '
832 'Enter a name for your new Custom Theme below.')
833 newTheme = self.GetNewThemeName(message)
834 if not newTheme: #user cancelled custom theme creation
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000835 return
Terry Jan Reedyae410862014-08-03 23:02:53 -0400836 else: #create new custom theme based on previously active theme
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000837 self.CreateNewTheme(newTheme)
Steven M. Gava052937f2002-02-11 02:20:53 +0000838 self.colour.set(colourString)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400839 else: #current theme is user defined
Steven M. Gava052937f2002-02-11 02:20:53 +0000840 self.colour.set(colourString)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000841
Steven M. Gava052937f2002-02-11 02:20:53 +0000842 def OnNewColourSet(self):
843 newColour=self.colour.get()
Terry Jan Reedyae410862014-08-03 23:02:53 -0400844 self.frameColourSet.config(bg=newColour) #set sample
845 plane ='foreground' if self.fgHilite.get() else 'background'
846 sampleElement = self.themeElements[self.highlightTarget.get()][0]
Raymond Hettinger931237e2003-07-09 18:48:24 +0000847 self.textHighlightSample.tag_config(sampleElement, **{plane:newColour})
Terry Jan Reedyae410862014-08-03 23:02:53 -0400848 theme = self.customTheme.get()
849 themeElement = sampleElement + '-' + plane
850 self.AddChangedItem('highlight', theme, themeElement, newColour)
Steven M. Gava052937f2002-02-11 02:20:53 +0000851
Terry Jan Reedyae410862014-08-03 23:02:53 -0400852 def GetNewThemeName(self, message):
853 usedNames = (idleConf.GetSectionList('user', 'highlight') +
854 idleConf.GetSectionList('default', 'highlight'))
855 newTheme = GetCfgSectionNameDialog(
856 self, 'New Custom Theme', message, usedNames).result
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000857 return newTheme
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000858
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000859 def SaveAsNewTheme(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400860 newThemeName = self.GetNewThemeName('New Theme Name:')
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000861 if newThemeName:
862 self.CreateNewTheme(newThemeName)
863
Terry Jan Reedyae410862014-08-03 23:02:53 -0400864 def CreateNewTheme(self, newThemeName):
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000865 #creates new custom theme based on the previously active theme,
866 #and makes the new theme active
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000867 if self.themeIsBuiltin.get():
Terry Jan Reedyae410862014-08-03 23:02:53 -0400868 themeType = 'default'
869 themeName = self.builtinTheme.get()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000870 else:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400871 themeType = 'user'
872 themeName = self.customTheme.get()
873 newTheme = idleConf.GetThemeDict(themeType, themeName)
Steven M. Gava052937f2002-02-11 02:20:53 +0000874 #apply any of the old theme's unsaved changes to the new theme
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400875 if themeName in self.changedItems['highlight']:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400876 themeChanges = self.changedItems['highlight'][themeName]
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400877 for element in themeChanges:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400878 newTheme[element] = themeChanges[element]
Steven M. Gava052937f2002-02-11 02:20:53 +0000879 #save the new theme
Terry Jan Reedyae410862014-08-03 23:02:53 -0400880 self.SaveNewTheme(newThemeName, newTheme)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000881 #change gui over to the new theme
Terry Jan Reedyae410862014-08-03 23:02:53 -0400882 customThemeList = idleConf.GetSectionList('user', 'highlight')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000883 customThemeList.sort()
Terry Jan Reedyae410862014-08-03 23:02:53 -0400884 self.optMenuThemeCustom.SetMenu(customThemeList, newThemeName)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000885 self.themeIsBuiltin.set(0)
886 self.SetThemeType()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000887
Terry Jan Reedyae410862014-08-03 23:02:53 -0400888 def OnListFontButtonRelease(self, event):
Kurt B. Kaiser05391692003-05-26 20:35:53 +0000889 font = self.listFontName.get(ANCHOR)
890 self.fontName.set(font.lower())
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000891 self.SetFontSample()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000892
Terry Jan Reedyae410862014-08-03 23:02:53 -0400893 def SetFontSample(self, event=None):
894 fontName = self.fontName.get()
895 fontWeight = tkFont.BOLD if self.fontBold.get() else tkFont.NORMAL
Ned Deilye3d47122012-10-22 15:13:01 -0700896 newFont = (fontName, self.fontSize.get(), fontWeight)
897 self.labelFontSample.config(font=newFont)
898 self.textHighlightSample.configure(font=newFont)
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000899
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000900 def SetHighlightTarget(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400901 if self.highlightTarget.get() == 'Cursor': #bg not possible
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000902 self.radioFg.config(state=DISABLED)
903 self.radioBg.config(state=DISABLED)
904 self.fgHilite.set(1)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400905 else: #both fg and bg can be set
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000906 self.radioFg.config(state=NORMAL)
907 self.radioBg.config(state=NORMAL)
908 self.fgHilite.set(1)
909 self.SetColourSample()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000910
Terry Jan Reedyae410862014-08-03 23:02:53 -0400911 def SetColourSampleBinding(self, *args):
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000912 self.SetColourSample()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000913
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000914 def SetColourSample(self):
915 #set the colour smaple area
Terry Jan Reedyae410862014-08-03 23:02:53 -0400916 tag = self.themeElements[self.highlightTarget.get()][0]
917 plane = 'foreground' if self.fgHilite.get() else 'background'
918 colour = self.textHighlightSample.tag_cget(tag, plane)
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000919 self.frameColourSet.config(bg=colour)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000920
Steven M. Gava9dd16b32001-11-03 14:54:25 +0000921 def PaintThemeSample(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400922 if self.themeIsBuiltin.get(): #a default theme
923 theme = self.builtinTheme.get()
924 else: #a user theme
925 theme = self.customTheme.get()
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400926 for elementTitle in self.themeElements:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400927 element = self.themeElements[elementTitle][0]
928 colours = idleConf.GetHighlight(theme, element)
929 if element == 'cursor': #cursor sample needs special painting
930 colours['background'] = idleConf.GetHighlight(
931 theme, 'normal', fgBg='bg')
Steven M. Gava052937f2002-02-11 02:20:53 +0000932 #handle any unsaved changes to this theme
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400933 if theme in self.changedItems['highlight']:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400934 themeDict = self.changedItems['highlight'][theme]
935 if element + '-foreground' in themeDict:
936 colours['foreground'] = themeDict[element + '-foreground']
937 if element + '-background' in themeDict:
938 colours['background'] = themeDict[element + '-background']
Raymond Hettinger931237e2003-07-09 18:48:24 +0000939 self.textHighlightSample.tag_config(element, **colours)
Steven M. Gava052937f2002-02-11 02:20:53 +0000940 self.SetColourSample()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000941
Terry Jan Reedyae410862014-08-03 23:02:53 -0400942 def HelpSourceSelected(self, event):
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000943 self.SetHelpListButtonStates()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000944
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000945 def SetHelpListButtonStates(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400946 if self.listHelp.size() < 1: #no entries in list
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000947 self.buttonHelpListEdit.config(state=DISABLED)
948 self.buttonHelpListRemove.config(state=DISABLED)
949 else: #there are some entries
Terry Jan Reedyae410862014-08-03 23:02:53 -0400950 if self.listHelp.curselection(): #there currently is a selection
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000951 self.buttonHelpListEdit.config(state=NORMAL)
952 self.buttonHelpListRemove.config(state=NORMAL)
953 else: #there currently is not a selection
954 self.buttonHelpListEdit.config(state=DISABLED)
955 self.buttonHelpListRemove.config(state=DISABLED)
956
957 def HelpListItemAdd(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400958 helpSource = GetHelpSourceDialog(self, 'New Help Source').result
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000959 if helpSource:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400960 self.userHelpList.append((helpSource[0], helpSource[1]))
961 self.listHelp.insert(END, helpSource[0])
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000962 self.UpdateUserHelpChangedItems()
963 self.SetHelpListButtonStates()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000964
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000965 def HelpListItemEdit(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400966 itemIndex = self.listHelp.index(ANCHOR)
967 helpSource = self.userHelpList[itemIndex]
968 newHelpSource = GetHelpSourceDialog(
969 self, 'Edit Help Source', menuItem=helpSource[0],
970 filePath=helpSource[1]).result
971 if (not newHelpSource) or (newHelpSource == helpSource):
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000972 return #no changes
Terry Jan Reedyae410862014-08-03 23:02:53 -0400973 self.userHelpList[itemIndex] = newHelpSource
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000974 self.listHelp.delete(itemIndex)
Terry Jan Reedyae410862014-08-03 23:02:53 -0400975 self.listHelp.insert(itemIndex, newHelpSource[0])
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000976 self.UpdateUserHelpChangedItems()
977 self.SetHelpListButtonStates()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000978
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000979 def HelpListItemRemove(self):
Terry Jan Reedyae410862014-08-03 23:02:53 -0400980 itemIndex = self.listHelp.index(ANCHOR)
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000981 del(self.userHelpList[itemIndex])
982 self.listHelp.delete(itemIndex)
983 self.UpdateUserHelpChangedItems()
984 self.SetHelpListButtonStates()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000985
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000986 def UpdateUserHelpChangedItems(self):
Kurt B. Kaiser8e92bf72003-01-14 22:03:31 +0000987 "Clear and rebuild the HelpFiles section in self.changedItems"
988 self.changedItems['main']['HelpFiles'] = {}
Terry Jan Reedyae410862014-08-03 23:02:53 -0400989 for num in range(1, len(self.userHelpList) + 1):
990 self.AddChangedItem(
991 'main', 'HelpFiles', str(num),
Terry Jan Reedy110796f2014-07-27 04:07:18 -0400992 ';'.join(self.userHelpList[num-1][:2]))
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000993
Steven M. Gava429a86a2001-10-23 10:42:12 +0000994 def LoadFontCfg(self):
995 ##base editor font selection list
Terry Jan Reedyae410862014-08-03 23:02:53 -0400996 fonts = list(tkFont.families(self))
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000997 fonts.sort()
998 for font in fonts:
Terry Jan Reedyae410862014-08-03 23:02:53 -0400999 self.listFontName.insert(END, font)
Terry Jan Reedy12352142015-08-01 18:57:27 -04001000 configuredFont = idleConf.GetFont(self, 'main', 'EditorWindow')
1001 fontName = configuredFont[0].lower()
1002 fontSize = configuredFont[1]
1003 fontBold = configuredFont[2]=='bold'
1004 self.fontName.set(fontName)
Kurt B. Kaiser05391692003-05-26 20:35:53 +00001005 lc_fonts = [s.lower() for s in fonts]
Terry Jan Reedy12352142015-08-01 18:57:27 -04001006 try:
1007 currentFontIndex = lc_fonts.index(fontName)
Steven M. Gava429a86a2001-10-23 10:42:12 +00001008 self.listFontName.see(currentFontIndex)
1009 self.listFontName.select_set(currentFontIndex)
Steven M. Gavac112cd82002-01-22 05:56:40 +00001010 self.listFontName.select_anchor(currentFontIndex)
Terry Jan Reedy12352142015-08-01 18:57:27 -04001011 except ValueError:
1012 pass
Steven M. Gava429a86a2001-10-23 10:42:12 +00001013 ##font size dropdown
Terry Jan Reedyae410862014-08-03 23:02:53 -04001014 self.optMenuFontSize.SetMenu(('7', '8', '9', '10', '11', '12', '13',
Terry Jan Reedy28fb4da2016-08-30 20:19:07 -04001015 '14', '16', '18', '20', '22',
1016 '25', '29', '34', '40'), fontSize )
Steven M. Gavac112cd82002-01-22 05:56:40 +00001017 ##fontWeight
Terry Jan Reedy12352142015-08-01 18:57:27 -04001018 self.fontBold.set(fontBold)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001019 ##font sample
Steven M. Gava429a86a2001-10-23 10:42:12 +00001020 self.SetFontSample()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001021
Steven M. Gava429a86a2001-10-23 10:42:12 +00001022 def LoadTabCfg(self):
Steven M. Gava429a86a2001-10-23 10:42:12 +00001023 ##indent sizes
Terry Jan Reedyae410862014-08-03 23:02:53 -04001024 spaceNum = idleConf.GetOption(
1025 'main', 'Indent', 'num-spaces', default=4, type='int')
Steven M. Gava429a86a2001-10-23 10:42:12 +00001026 self.spaceNum.set(spaceNum)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001027
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001028 def LoadThemeCfg(self):
Steven M. Gava41a85322001-10-29 08:05:34 +00001029 ##current theme type radiobutton
Terry Jan Reedyae410862014-08-03 23:02:53 -04001030 self.themeIsBuiltin.set(idleConf.GetOption(
1031 'main', 'Theme', 'default', type='bool', default=1))
Steven M. Gava41a85322001-10-29 08:05:34 +00001032 ##currently set theme
Terry Jan Reedyae410862014-08-03 23:02:53 -04001033 currentOption = idleConf.CurrentTheme()
Steven M. Gava7c017862001-10-29 11:19:46 +00001034 ##load available theme option menus
Steven M. Gavad0342cd2001-11-04 11:53:10 +00001035 if self.themeIsBuiltin.get(): #default theme selected
Terry Jan Reedyae410862014-08-03 23:02:53 -04001036 itemList = idleConf.GetSectionList('default', 'highlight')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001037 itemList.sort()
Terry Jan Reedyae410862014-08-03 23:02:53 -04001038 self.optMenuThemeBuiltin.SetMenu(itemList, currentOption)
1039 itemList = idleConf.GetSectionList('user', 'highlight')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001040 itemList.sort()
Steven M. Gava41a85322001-10-29 08:05:34 +00001041 if not itemList:
1042 self.radioThemeCustom.config(state=DISABLED)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001043 self.customTheme.set('- no custom themes -')
Steven M. Gava41a85322001-10-29 08:05:34 +00001044 else:
Terry Jan Reedyae410862014-08-03 23:02:53 -04001045 self.optMenuThemeCustom.SetMenu(itemList, itemList[0])
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001046 else: #user theme selected
Terry Jan Reedyae410862014-08-03 23:02:53 -04001047 itemList = idleConf.GetSectionList('user', 'highlight')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001048 itemList.sort()
Terry Jan Reedyae410862014-08-03 23:02:53 -04001049 self.optMenuThemeCustom.SetMenu(itemList, currentOption)
1050 itemList = idleConf.GetSectionList('default', 'highlight')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001051 itemList.sort()
Terry Jan Reedyae410862014-08-03 23:02:53 -04001052 self.optMenuThemeBuiltin.SetMenu(itemList, itemList[0])
Steven M. Gava7c017862001-10-29 11:19:46 +00001053 self.SetThemeType()
1054 ##load theme element option menu
Terry Jan Reedyae410862014-08-03 23:02:53 -04001055 themeNames = self.themeElements.keys()
Florent Xiclunaa7f242f2010-04-02 08:15:26 +00001056 themeNames.sort(key=lambda x: self.themeElements[x][1])
Terry Jan Reedyae410862014-08-03 23:02:53 -04001057 self.optMenuHighlightTarget.SetMenu(themeNames, themeNames[0])
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001058 self.PaintThemeSample()
Steven M. Gava0cae01c2002-01-04 07:53:06 +00001059 self.SetHighlightTarget()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001060
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001061 def LoadKeyCfg(self):
Steven M. Gava41a85322001-10-29 08:05:34 +00001062 ##current keys type radiobutton
Terry Jan Reedyae410862014-08-03 23:02:53 -04001063 self.keysAreBuiltin.set(idleConf.GetOption(
1064 'main', 'Keys', 'default', type='bool', default=1))
Steven M. Gava41a85322001-10-29 08:05:34 +00001065 ##currently set keys
Terry Jan Reedyae410862014-08-03 23:02:53 -04001066 currentOption = idleConf.CurrentKeys()
Steven M. Gava7c017862001-10-29 11:19:46 +00001067 ##load available keyset option menus
Steven M. Gava052937f2002-02-11 02:20:53 +00001068 if self.keysAreBuiltin.get(): #default theme selected
Terry Jan Reedyae410862014-08-03 23:02:53 -04001069 itemList = idleConf.GetSectionList('default', 'keys')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001070 itemList.sort()
Terry Jan Reedyae410862014-08-03 23:02:53 -04001071 self.optMenuKeysBuiltin.SetMenu(itemList, currentOption)
1072 itemList = idleConf.GetSectionList('user', 'keys')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001073 itemList.sort()
Steven M. Gava41a85322001-10-29 08:05:34 +00001074 if not itemList:
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001075 self.radioKeysCustom.config(state=DISABLED)
1076 self.customKeys.set('- no custom keys -')
Steven M. Gava41a85322001-10-29 08:05:34 +00001077 else:
Terry Jan Reedyae410862014-08-03 23:02:53 -04001078 self.optMenuKeysCustom.SetMenu(itemList, itemList[0])
Steven M. Gavaa498af22002-02-01 01:33:36 +00001079 else: #user key set selected
Terry Jan Reedyae410862014-08-03 23:02:53 -04001080 itemList = idleConf.GetSectionList('user', 'keys')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001081 itemList.sort()
Terry Jan Reedyae410862014-08-03 23:02:53 -04001082 self.optMenuKeysCustom.SetMenu(itemList, currentOption)
1083 itemList = idleConf.GetSectionList('default', 'keys')
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +00001084 itemList.sort()
Terry Jan Reedyae410862014-08-03 23:02:53 -04001085 self.optMenuKeysBuiltin.SetMenu(itemList, itemList[0])
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001086 self.SetKeysType()
Steven M. Gavafacfc092002-01-19 00:29:54 +00001087 ##load keyset element list
Terry Jan Reedyae410862014-08-03 23:02:53 -04001088 keySetName = idleConf.CurrentKeys()
Steven M. Gava052937f2002-02-11 02:20:53 +00001089 self.LoadKeysList(keySetName)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001090
Steven M. Gavafacfc092002-01-19 00:29:54 +00001091 def LoadGeneralCfg(self):
Steven M. Gava5f28e8f2002-01-21 06:38:21 +00001092 #startup state
Terry Jan Reedyae410862014-08-03 23:02:53 -04001093 self.startupEdit.set(idleConf.GetOption(
1094 'main', 'General', 'editor-on-startup', default=1, type='bool'))
Kurt B. Kaiser6c638b62003-05-26 06:23:10 +00001095 #autosave state
Terry Jan Reedyae410862014-08-03 23:02:53 -04001096 self.autoSave.set(idleConf.GetOption(
1097 'main', 'General', 'autosave', default=0, type='bool'))
Steven M. Gavafacfc092002-01-19 00:29:54 +00001098 #initial window size
Terry Jan Reedyae410862014-08-03 23:02:53 -04001099 self.winWidth.set(idleConf.GetOption(
1100 'main', 'EditorWindow', 'width', type='int'))
1101 self.winHeight.set(idleConf.GetOption(
1102 'main', 'EditorWindow', 'height', type='int'))
Kurt B. Kaisera053f332003-05-10 00:49:56 +00001103 # default source encoding
Terry Jan Reedyae410862014-08-03 23:02:53 -04001104 self.encoding.set(idleConf.GetOption(
1105 'main', 'EditorWindow', 'encoding', default='none'))
Kurt B. Kaiser8e92bf72003-01-14 22:03:31 +00001106 # additional help sources
1107 self.userHelpList = idleConf.GetAllExtraHelpSourcesList()
Steven M. Gava085eb1b2002-02-05 04:52:32 +00001108 for helpItem in self.userHelpList:
Terry Jan Reedyae410862014-08-03 23:02:53 -04001109 self.listHelp.insert(END, helpItem[0])
Steven M. Gava085eb1b2002-02-05 04:52:32 +00001110 self.SetHelpListButtonStates()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001111
Steven M. Gava429a86a2001-10-23 10:42:12 +00001112 def LoadConfigs(self):
1113 """
1114 load configuration from default and user config files and populate
1115 the widgets on the config dialog pages.
1116 """
1117 ### fonts / tabs page
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001118 self.LoadFontCfg()
1119 self.LoadTabCfg()
Steven M. Gava429a86a2001-10-23 10:42:12 +00001120 ### highlighting page
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001121 self.LoadThemeCfg()
Steven M. Gava429a86a2001-10-23 10:42:12 +00001122 ### keys page
Steven M. Gava9dd16b32001-11-03 14:54:25 +00001123 self.LoadKeyCfg()
Steven M. Gava429a86a2001-10-23 10:42:12 +00001124 ### general page
Steven M. Gavafacfc092002-01-19 00:29:54 +00001125 self.LoadGeneralCfg()
Terry Jan Reedy1c49ec02015-10-13 22:03:44 -04001126 # note: extension page handled separately
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001127
Terry Jan Reedyae410862014-08-03 23:02:53 -04001128 def SaveNewKeySet(self, keySetName, keySet):
Steven M. Gava052937f2002-02-11 02:20:53 +00001129 """
1130 save a newly created core key set.
1131 keySetName - string, the name of the new key set
1132 keySet - dictionary containing the new key set
1133 """
1134 if not idleConf.userCfg['keys'].has_section(keySetName):
1135 idleConf.userCfg['keys'].add_section(keySetName)
Terry Jan Reedy110796f2014-07-27 04:07:18 -04001136 for event in keySet:
Terry Jan Reedyae410862014-08-03 23:02:53 -04001137 value = keySet[event]
1138 idleConf.userCfg['keys'].SetOption(keySetName, event, value)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001139
Terry Jan Reedyae410862014-08-03 23:02:53 -04001140 def SaveNewTheme(self, themeName, theme):
Steven M. Gava052937f2002-02-11 02:20:53 +00001141 """
1142 save a newly created theme.
1143 themeName - string, the name of the new theme
1144 theme - dictionary containing the new theme
1145 """
1146 if not idleConf.userCfg['highlight'].has_section(themeName):
1147 idleConf.userCfg['highlight'].add_section(themeName)
Terry Jan Reedy110796f2014-07-27 04:07:18 -04001148 for element in theme:
Terry Jan Reedyae410862014-08-03 23:02:53 -04001149 value = theme[element]
1150 idleConf.userCfg['highlight'].SetOption(themeName, element, value)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001151
Terry Jan Reedyae410862014-08-03 23:02:53 -04001152 def SetUserValue(self, configType, section, item, value):
1153 if idleConf.defaultCfg[configType].has_option(section, item):
1154 if idleConf.defaultCfg[configType].Get(section, item) == value:
Steven M. Gava2d7bb3f2002-01-29 08:35:29 +00001155 #the setting equals a default setting, remove it from user cfg
Terry Jan Reedyae410862014-08-03 23:02:53 -04001156 return idleConf.userCfg[configType].RemoveOption(section, item)
Steven M. Gava2d7bb3f2002-01-29 08:35:29 +00001157 #if we got here set the option
Terry Jan Reedyae410862014-08-03 23:02:53 -04001158 return idleConf.userCfg[configType].SetOption(section, item, value)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001159
Steven M. Gava052937f2002-02-11 02:20:53 +00001160 def SaveAllChangedConfigs(self):
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001161 "Save configuration changes to the user config file."
Steven M. Gava0c5bc8c2002-03-27 02:25:44 +00001162 idleConf.userCfg['main'].Save()
Terry Jan Reedy110796f2014-07-27 04:07:18 -04001163 for configType in self.changedItems:
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001164 cfgTypeHasChanges = False
Terry Jan Reedy110796f2014-07-27 04:07:18 -04001165 for section in self.changedItems[configType]:
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001166 if section == 'HelpFiles':
1167 #this section gets completely replaced
1168 idleConf.userCfg['main'].remove_section('HelpFiles')
Kurt B. Kaiser8e92bf72003-01-14 22:03:31 +00001169 cfgTypeHasChanges = True
Terry Jan Reedy110796f2014-07-27 04:07:18 -04001170 for item in self.changedItems[configType][section]:
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001171 value = self.changedItems[configType][section][item]
Terry Jan Reedyae410862014-08-03 23:02:53 -04001172 if self.SetUserValue(configType, section, item, value):
Kurt B. Kaisere7a161e2003-01-10 20:13:57 +00001173 cfgTypeHasChanges = True
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001174 if cfgTypeHasChanges:
1175 idleConf.userCfg[configType].Save()
Kurt B. Kaiser5acdf932004-11-16 21:28:36 +00001176 for configType in ['keys', 'highlight']:
1177 # save these even if unchanged!
1178 idleConf.userCfg[configType].Save()
Steven M. Gavaa498af22002-02-01 01:33:36 +00001179 self.ResetChangedItems() #clear the changed items dict
Terry Jan Reedy1c49ec02015-10-13 22:03:44 -04001180 self.save_all_changed_extensions() # uses a different mechanism
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001181
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001182 def DeactivateCurrentConfig(self):
1183 #Before a config is saved, some cleanup of current
1184 #config must be done - remove the previous keybindings
Terry Jan Reedyae410862014-08-03 23:02:53 -04001185 winInstances = self.parent.instance_dict
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001186 for instance in winInstances:
1187 instance.RemoveKeybindings()
1188
Steven M. Gava49745752002-02-18 01:43:11 +00001189 def ActivateConfigChanges(self):
Kurt B. Kaiseracdef852005-01-31 03:34:26 +00001190 "Dynamically apply configuration changes"
Terry Jan Reedy110796f2014-07-27 04:07:18 -04001191 winInstances = self.parent.instance_dict.keys()
Steven M. Gavab77d3432002-03-02 07:16:21 +00001192 for instance in winInstances:
1193 instance.ResetColorizer()
Steven M. Gavab1585412002-03-12 00:21:56 +00001194 instance.ResetFont()
Kurt B. Kaiseracdef852005-01-31 03:34:26 +00001195 instance.set_notabs_indentwidth()
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001196 instance.ApplyKeybindings()
Kurt B. Kaiser8e92bf72003-01-14 22:03:31 +00001197 instance.reset_help_menu_entries()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001198
Steven M. Gava5f28e8f2002-01-21 06:38:21 +00001199 def Cancel(self):
Tal Einat894940b2018-08-02 10:21:49 +03001200 self.grab_release()
Steven M. Gava5f28e8f2002-01-21 06:38:21 +00001201 self.destroy()
1202
1203 def Ok(self):
1204 self.Apply()
Tal Einat894940b2018-08-02 10:21:49 +03001205 self.grab_release()
Steven M. Gava5f28e8f2002-01-21 06:38:21 +00001206 self.destroy()
1207
1208 def Apply(self):
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001209 self.DeactivateCurrentConfig()
Steven M. Gava052937f2002-02-11 02:20:53 +00001210 self.SaveAllChangedConfigs()
Steven M. Gava49745752002-02-18 01:43:11 +00001211 self.ActivateConfigChanges()
Steven M. Gava5f28e8f2002-01-21 06:38:21 +00001212
1213 def Help(self):
Terry Jan Reedyc0a053e2015-10-11 22:07:25 -04001214 page = self.tabPages._current_page
1215 view_text(self, title='Help for IDLE preferences',
1216 text=help_common+help_pages.get(page, ''))
1217
Terry Jan Reedy1c49ec02015-10-13 22:03:44 -04001218 def CreatePageExtensions(self):
1219 """Part of the config dialog used for configuring IDLE extensions.
1220
1221 This code is generic - it works for any and all IDLE extensions.
1222
1223 IDLE extensions save their configuration options using idleConf.
Terry Jan Reedy4922ac12015-10-13 22:08:45 -04001224 This code reads the current configuration using idleConf, supplies a
Terry Jan Reedy1c49ec02015-10-13 22:03:44 -04001225 GUI interface to change the configuration values, and saves the
1226 changes using idleConf.
1227
1228 Not all changes take effect immediately - some may require restarting IDLE.
1229 This depends on each extension's implementation.
1230
1231 All values are treated as text, and it is up to the user to supply
1232 reasonable values. The only exception to this are the 'enable*' options,
Serhiy Storchaka9a118f12016-04-17 09:37:36 +03001233 which are boolean, and can be toggled with a True/False button.
Terry Jan Reedy1c49ec02015-10-13 22:03:44 -04001234 """
1235 parent = self.parent
1236 frame = self.tabPages.pages['Extensions'].frame
1237 self.ext_defaultCfg = idleConf.defaultCfg['extensions']
1238 self.ext_userCfg = idleConf.userCfg['extensions']
1239 self.is_int = self.register(is_int)
1240 self.load_extensions()
1241 # create widgets - a listbox shows all available extensions, with the
1242 # controls for the extension selected in the listbox to the right
1243 self.extension_names = StringVar(self)
1244 frame.rowconfigure(0, weight=1)
1245 frame.columnconfigure(2, weight=1)
1246 self.extension_list = Listbox(frame, listvariable=self.extension_names,
1247 selectmode='browse')
1248 self.extension_list.bind('<<ListboxSelect>>', self.extension_selected)
1249 scroll = Scrollbar(frame, command=self.extension_list.yview)
1250 self.extension_list.yscrollcommand=scroll.set
1251 self.details_frame = LabelFrame(frame, width=250, height=250)
1252 self.extension_list.grid(column=0, row=0, sticky='nws')
1253 scroll.grid(column=1, row=0, sticky='ns')
1254 self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0])
1255 frame.configure(padx=10, pady=10)
1256 self.config_frame = {}
1257 self.current_extension = None
1258
1259 self.outerframe = self # TEMPORARY
1260 self.tabbed_page_set = self.extension_list # TEMPORARY
1261
1262 # create the frame holding controls for each extension
1263 ext_names = ''
1264 for ext_name in sorted(self.extensions):
1265 self.create_extension_frame(ext_name)
1266 ext_names = ext_names + '{' + ext_name + '} '
1267 self.extension_names.set(ext_names)
1268 self.extension_list.selection_set(0)
1269 self.extension_selected(None)
1270
1271 def load_extensions(self):
1272 "Fill self.extensions with data from the default and user configs."
1273 self.extensions = {}
1274 for ext_name in idleConf.GetExtensions(active_only=False):
1275 self.extensions[ext_name] = []
1276
1277 for ext_name in self.extensions:
1278 opt_list = sorted(self.ext_defaultCfg.GetOptionList(ext_name))
1279
1280 # bring 'enable' options to the beginning of the list
1281 enables = [opt_name for opt_name in opt_list
1282 if opt_name.startswith('enable')]
1283 for opt_name in enables:
1284 opt_list.remove(opt_name)
1285 opt_list = enables + opt_list
1286
1287 for opt_name in opt_list:
1288 def_str = self.ext_defaultCfg.Get(
1289 ext_name, opt_name, raw=True)
1290 try:
1291 def_obj = {'True':True, 'False':False}[def_str]
1292 opt_type = 'bool'
1293 except KeyError:
1294 try:
1295 def_obj = int(def_str)
1296 opt_type = 'int'
1297 except ValueError:
1298 def_obj = def_str
1299 opt_type = None
1300 try:
1301 value = self.ext_userCfg.Get(
1302 ext_name, opt_name, type=opt_type, raw=True,
1303 default=def_obj)
1304 except ValueError: # Need this until .Get fixed
1305 value = def_obj # bad values overwritten by entry
1306 var = StringVar(self)
1307 var.set(str(value))
1308
1309 self.extensions[ext_name].append({'name': opt_name,
1310 'type': opt_type,
1311 'default': def_str,
1312 'value': value,
1313 'var': var,
1314 })
1315
1316 def extension_selected(self, event):
1317 newsel = self.extension_list.curselection()
1318 if newsel:
1319 newsel = self.extension_list.get(newsel)
1320 if newsel is None or newsel != self.current_extension:
1321 if self.current_extension:
1322 self.details_frame.config(text='')
1323 self.config_frame[self.current_extension].grid_forget()
1324 self.current_extension = None
1325 if newsel:
1326 self.details_frame.config(text=newsel)
1327 self.config_frame[newsel].grid(column=0, row=0, sticky='nsew')
1328 self.current_extension = newsel
1329
1330 def create_extension_frame(self, ext_name):
1331 """Create a frame holding the widgets to configure one extension"""
1332 f = VerticalScrolledFrame(self.details_frame, height=250, width=250)
1333 self.config_frame[ext_name] = f
1334 entry_area = f.interior
1335 # create an entry for each configuration option
1336 for row, opt in enumerate(self.extensions[ext_name]):
1337 # create a row with a label and entry/checkbutton
1338 label = Label(entry_area, text=opt['name'])
1339 label.grid(row=row, column=0, sticky=NW)
1340 var = opt['var']
1341 if opt['type'] == 'bool':
1342 Checkbutton(entry_area, textvariable=var, variable=var,
1343 onvalue='True', offvalue='False',
1344 indicatoron=FALSE, selectcolor='', width=8
1345 ).grid(row=row, column=1, sticky=W, padx=7)
1346 elif opt['type'] == 'int':
1347 Entry(entry_area, textvariable=var, validate='key',
1348 validatecommand=(self.is_int, '%P')
1349 ).grid(row=row, column=1, sticky=NSEW, padx=7)
1350
1351 else:
1352 Entry(entry_area, textvariable=var
1353 ).grid(row=row, column=1, sticky=NSEW, padx=7)
1354 return
1355
1356 def set_extension_value(self, section, opt):
1357 name = opt['name']
1358 default = opt['default']
1359 value = opt['var'].get().strip() or default
1360 opt['var'].set(value)
1361 # if self.defaultCfg.has_section(section):
1362 # Currently, always true; if not, indent to return
1363 if (value == default):
1364 return self.ext_userCfg.RemoveOption(section, name)
1365 # set the option
1366 return self.ext_userCfg.SetOption(section, name, value)
1367
1368 def save_all_changed_extensions(self):
1369 """Save configuration changes to the user config file."""
1370 has_changes = False
1371 for ext_name in self.extensions:
1372 options = self.extensions[ext_name]
1373 for opt in options:
1374 if self.set_extension_value(ext_name, opt):
1375 has_changes = True
1376 if has_changes:
1377 self.ext_userCfg.Save()
1378
1379
Terry Jan Reedyc0a053e2015-10-11 22:07:25 -04001380help_common = '''\
1381When you click either the Apply or Ok buttons, settings in this
1382dialog that are different from IDLE's default are saved in
1383a .idlerc directory in your home directory. Except as noted,
Terry Jan Reedy35aa5d02015-11-12 15:02:50 -05001384these changes apply to all versions of IDLE installed on this
Terry Jan Reedyc0a053e2015-10-11 22:07:25 -04001385machine. Some do not take affect until IDLE is restarted.
1386[Cancel] only cancels changes made since the last save.
1387'''
1388help_pages = {
1389 'Highlighting':'''
1390Highlighting:
Terry Jan Reedy35aa5d02015-11-12 15:02:50 -05001391The IDLE Dark color theme is new in October 2015. It can only
Terry Jan Reedyc0a053e2015-10-11 22:07:25 -04001392be used with older IDLE releases if it is saved as a custom
1393theme, with a different name.
1394'''
1395}
1396
Steven M. Gavac11ccf32001-09-24 09:43:17 +00001397
Terry Jan Reedy1c49ec02015-10-13 22:03:44 -04001398def is_int(s):
1399 "Return 's is blank or represents an int'"
1400 if not s:
1401 return True
1402 try:
1403 int(s)
1404 return True
1405 except ValueError:
1406 return False
1407
1408
Terry Jan Reedy7a162072014-10-22 20:15:12 -04001409class VerticalScrolledFrame(Frame):
1410 """A pure Tkinter vertically scrollable frame.
1411
1412 * Use the 'interior' attribute to place widgets inside the scrollable frame
1413 * Construct and pack/place/grid normally
1414 * This frame only allows vertical scrolling
1415 """
1416 def __init__(self, parent, *args, **kw):
1417 Frame.__init__(self, parent, *args, **kw)
1418
1419 # create a canvas object and a vertical scrollbar for scrolling it
1420 vscrollbar = Scrollbar(self, orient=VERTICAL)
1421 vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
1422 canvas = Canvas(self, bd=0, highlightthickness=0,
Terry Jan Reedy1256b3c2015-10-22 03:27:27 -04001423 yscrollcommand=vscrollbar.set, width=240)
Terry Jan Reedy7a162072014-10-22 20:15:12 -04001424 canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
1425 vscrollbar.config(command=canvas.yview)
1426
1427 # reset the view
1428 canvas.xview_moveto(0)
1429 canvas.yview_moveto(0)
1430
1431 # create a frame inside the canvas which will be scrolled with it
1432 self.interior = interior = Frame(canvas)
1433 interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)
1434
1435 # track changes to the canvas and frame width and sync them,
1436 # also updating the scrollbar
1437 def _configure_interior(event):
1438 # update the scrollbars to match the size of the inner frame
1439 size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
1440 canvas.config(scrollregion="0 0 %s %s" % size)
Terry Jan Reedy7a162072014-10-22 20:15:12 -04001441 interior.bind('<Configure>', _configure_interior)
1442
1443 def _configure_canvas(event):
1444 if interior.winfo_reqwidth() != canvas.winfo_width():
1445 # update the inner frame's width to fill the canvas
1446 canvas.itemconfigure(interior_id, width=canvas.winfo_width())
1447 canvas.bind('<Configure>', _configure_canvas)
1448
1449 return
1450
Terry Jan Reedy7a162072014-10-22 20:15:12 -04001451
Steven M. Gava44d3d1a2001-07-31 06:59:02 +00001452if __name__ == '__main__':
Terry Jan Reedyaf0dce92014-07-14 23:07:21 -04001453 import unittest
1454 unittest.main('idlelib.idle_test.test_configdialog',
1455 verbosity=2, exit=False)
Terry Jan Reedy76916e82014-05-29 01:46:16 -04001456 from idlelib.idle_test.htest import run
Terry Jan Reedy91885162015-10-20 02:15:23 -04001457 run(ConfigDialog)