blob: 4be60a36012a08d5f7dfdb45417a07522ddd25ac [file] [log] [blame]
Tim Peters231c3c82006-06-11 19:43:49 +00001"""
2A number of function that enhance IDLE on MacOSX when it used as a normal
3GUI application (as opposed to an X11 application).
4"""
5import sys
Georg Brandl6634bf22008-05-20 07:13:37 +00006import Tkinter
Ned Deily4a705502011-01-18 04:33:22 +00007from os import path
Tim Peters231c3c82006-06-11 19:43:49 +00008
Ronald Oussoren92919a62009-12-24 13:30:58 +00009
10_appbundle = None
11
Tim Peters231c3c82006-06-11 19:43:49 +000012def runningAsOSXApp():
Ronald Oussorena97063a2009-03-04 21:35:05 +000013 """
14 Returns True if Python is running from within an app on OSX.
15 If so, assume that Python was built with Aqua Tcl/Tk rather than
Guilherme Polo175e0bf2009-08-05 23:48:26 +000016 X11 Tcl/Tk.
Ronald Oussorena97063a2009-03-04 21:35:05 +000017 """
Ronald Oussoren92919a62009-12-24 13:30:58 +000018 global _appbundle
19 if _appbundle is None:
20 _appbundle = (sys.platform == 'darwin' and '.app' in sys.executable)
21 return _appbundle
Tim Peters231c3c82006-06-11 19:43:49 +000022
Ned Deily4a705502011-01-18 04:33:22 +000023_carbonaquatk = None
24
25def isCarbonAquaTk(root):
26 """
27 Returns True if IDLE is using a Carbon Aqua Tk (instead of the
28 newer Cocoa Aqua Tk).
29 """
30 global _carbonaquatk
31 if _carbonaquatk is None:
32 _carbonaquatk = (runningAsOSXApp() and
33 'aqua' in root.tk.call('tk', 'windowingsystem') and
34 'AppKit' not in root.tk.call('winfo', 'server', '.'))
35 return _carbonaquatk
36
Ned Deily2a6f4b32011-01-30 00:18:47 +000037def tkVersionWarning(root):
38 """
39 Returns a string warning message if the Tk version in use appears to
40 be one known to cause problems with IDLE. The Apple Cocoa-based Tk 8.5
41 that was shipped with Mac OS X 10.6.
42 """
43
44 if (runningAsOSXApp() and
45 ('AppKit' in root.tk.call('winfo', 'server', '.')) and
46 (root.tk.call('info', 'patchlevel') == '8.5.7') ):
47 return (r"WARNING: The version of Tcl/Tk (8.5.7) in use may"
48 r" be unstable.\n"
49 r"Visit http://www.python.org/download/mac/tcltk/"
50 r" for current information.")
51 else:
52 return False
53
Tim Peters231c3c82006-06-11 19:43:49 +000054def addOpenEventSupport(root, flist):
55 """
Ezio Melottic2077b02011-03-16 12:34:31 +020056 This ensures that the application will respond to open AppleEvents, which
57 makes is feasible to use IDLE as the default application for python files.
Tim Peters231c3c82006-06-11 19:43:49 +000058 """
59 def doOpenFile(*args):
60 for fn in args:
61 flist.open(fn)
62
63 # The command below is a hook in aquatk that is called whenever the app
64 # receives a file open event. The callback can have multiple arguments,
65 # one for every file that should be opened.
66 root.createcommand("::tk::mac::OpenDocument", doOpenFile)
67
68def hideTkConsole(root):
Ronald Oussoren9b0bcc12007-07-09 06:02:21 +000069 try:
70 root.tk.call('console', 'hide')
Georg Brandl6634bf22008-05-20 07:13:37 +000071 except Tkinter.TclError:
Ronald Oussoren9b0bcc12007-07-09 06:02:21 +000072 # Some versions of the Tk framework don't have a console object
73 pass
Tim Peters231c3c82006-06-11 19:43:49 +000074
Ronald Oussoren8133f9d2006-07-23 09:46:11 +000075def overrideRootMenu(root, flist):
76 """
77 Replace the Tk root menu by something that's more appropriate for
78 IDLE.
79 """
Tim Peters0bbfd832006-07-24 21:02:15 +000080 # The menu that is attached to the Tk root (".") is also used by AquaTk for
Ronald Oussoren8133f9d2006-07-23 09:46:11 +000081 # all windows that don't specify a menu of their own. The default menubar
82 # contains a number of menus, none of which are appropriate for IDLE. The
83 # Most annoying of those is an 'About Tck/Tk...' menu in the application
84 # menu.
85 #
86 # This function replaces the default menubar by a mostly empty one, it
87 # should only contain the correct application menu and the window menu.
88 #
89 # Due to a (mis-)feature of TkAqua the user will also see an empty Help
90 # menu.
Georg Brandl6634bf22008-05-20 07:13:37 +000091 from Tkinter import Menu, Text, Text
Florent Xiclunad630c042010-04-02 07:24:52 +000092 from idlelib.EditorWindow import prepstr, get_accelerator
93 from idlelib import Bindings
94 from idlelib import WindowList
95 from idlelib.MultiCall import MultiCallCreator
Ronald Oussoren8133f9d2006-07-23 09:46:11 +000096
97 menubar = Menu(root)
98 root.configure(menu=menubar)
99 menudict = {}
100
101 menudict['windows'] = menu = Menu(menubar, name='windows')
102 menubar.add_cascade(label='Window', menu=menu, underline=0)
103
104 def postwindowsmenu(menu=menu):
105 end = menu.index('end')
106 if end is None:
107 end = -1
108
109 if end > 0:
110 menu.delete(0, end)
111 WindowList.add_windows_to_menu(menu)
112 WindowList.register_callback(postwindowsmenu)
113
Ronald Oussoren8133f9d2006-07-23 09:46:11 +0000114 def about_dialog(event=None):
Florent Xiclunad630c042010-04-02 07:24:52 +0000115 from idlelib import aboutDialog
Ronald Oussoren8133f9d2006-07-23 09:46:11 +0000116 aboutDialog.AboutDialog(root, 'About IDLE')
117
118 def config_dialog(event=None):
Florent Xiclunad630c042010-04-02 07:24:52 +0000119 from idlelib import configDialog
Ronald Oussoren55d88282009-05-26 18:44:48 +0000120 root.instance_dict = flist.inversedict
Ronald Oussoren8133f9d2006-07-23 09:46:11 +0000121 configDialog.ConfigDialog(root, 'Settings')
122
Ned Deily4a705502011-01-18 04:33:22 +0000123 def help_dialog(event=None):
124 from idlelib import textView
125 fn = path.join(path.abspath(path.dirname(__file__)), 'help.txt')
126 textView.view_file(root, 'Help', fn)
Ronald Oussoren9b0bcc12007-07-09 06:02:21 +0000127
Ronald Oussoren8133f9d2006-07-23 09:46:11 +0000128 root.bind('<<about-idle>>', about_dialog)
129 root.bind('<<open-config-dialog>>', config_dialog)
Ned Deily4a705502011-01-18 04:33:22 +0000130 root.createcommand('::tk::mac::ShowPreferences', config_dialog)
Ronald Oussoren8133f9d2006-07-23 09:46:11 +0000131 if flist:
132 root.bind('<<close-all-windows>>', flist.close_all_callback)
133
Ronald Oussoren8ec374c2010-12-07 16:02:59 +0000134 # The binding above doesn't reliably work on all versions of Tk
135 # on MacOSX. Adding command definition below does seem to do the
136 # right thing for now.
137 root.createcommand('exit', flist.close_all_callback)
138
Ned Deily4a705502011-01-18 04:33:22 +0000139 if isCarbonAquaTk(root):
140 # for Carbon AquaTk, replace the default Tk apple menu
141 menudict['application'] = menu = Menu(menubar, name='apple')
142 menubar.add_cascade(label='IDLE', menu=menu)
143 Bindings.menudefs.insert(0,
144 ('application', [
Ronald Oussoren9b0bcc12007-07-09 06:02:21 +0000145 ('About IDLE', '<<about-idle>>'),
Ned Deily4a705502011-01-18 04:33:22 +0000146 None,
147 ]))
148 tkversion = root.tk.eval('info patchlevel')
149 if tuple(map(int, tkversion.split('.'))) < (8, 4, 14):
150 # for earlier AquaTk versions, supply a Preferences menu item
151 Bindings.menudefs[0][1].append(
152 ('_Preferences....', '<<open-config-dialog>>'),
153 )
Ronald Oussoren9b0bcc12007-07-09 06:02:21 +0000154 else:
Ned Deily4a705502011-01-18 04:33:22 +0000155 # assume Cocoa AquaTk
156 # replace default About dialog with About IDLE one
157 root.createcommand('tkAboutDialog', about_dialog)
158 # replace default "Help" item in Help menu
159 root.createcommand('::tk::mac::ShowHelp', help_dialog)
160 # remove redundant "IDLE Help" from menu
161 del Bindings.menudefs[-1][1][0]
Ronald Oussoren8133f9d2006-07-23 09:46:11 +0000162
Tim Peters231c3c82006-06-11 19:43:49 +0000163def setupApp(root, flist):
164 """
165 Perform setup for the OSX application bundle.
166 """
167 if not runningAsOSXApp(): return
168
169 hideTkConsole(root)
Ronald Oussoren8133f9d2006-07-23 09:46:11 +0000170 overrideRootMenu(root, flist)
Tim Peters231c3c82006-06-11 19:43:49 +0000171 addOpenEventSupport(root, flist)