mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
This patch improves the L&F of IDLE on OSX. The changes are conditionalized on
being in an IDLE.app bundle on darwin. This does a slight reorganisation of the menus and adds support for file-open events.
This commit is contained in:
parent
6aaccc6b55
commit
19302d927e
8 changed files with 130 additions and 20 deletions
|
@ -80,6 +80,32 @@ menudefs = [
|
||||||
]),
|
]),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.platform == 'darwin' and '.app' in sys.executable:
|
||||||
|
# Running as a proper MacOS application bundle. This block restructures
|
||||||
|
# the menus a little to make them conform better to the HIG.
|
||||||
|
|
||||||
|
quitItem = menudefs[0][1][-1]
|
||||||
|
closeItem = menudefs[0][1][-2]
|
||||||
|
|
||||||
|
# Remove the last 3 items of the file menu: a separator, close window and
|
||||||
|
# quit. Close window will be reinserted just above the save item, where
|
||||||
|
# it should be according to the HIG. Quit is in the application menu.
|
||||||
|
del menudefs[0][1][-3:]
|
||||||
|
menudefs[0][1].insert(6, closeItem)
|
||||||
|
|
||||||
|
# Remove the 'About' entry from the help menu, it is in the application
|
||||||
|
# menu
|
||||||
|
del menudefs[-1][1][0:2]
|
||||||
|
|
||||||
|
menudefs.insert(0,
|
||||||
|
('application', [
|
||||||
|
('About IDLE', '<<about-idle>>'),
|
||||||
|
None,
|
||||||
|
('_Preferences....', '<<open-config-dialog>>'),
|
||||||
|
]))
|
||||||
|
|
||||||
|
|
||||||
default_keydefs = idleConf.GetCurrentKeySet()
|
default_keydefs = idleConf.GetCurrentKeySet()
|
||||||
|
|
||||||
del sys
|
del sys
|
||||||
|
|
|
@ -17,6 +17,7 @@ import ReplaceDialog
|
||||||
import PyParse
|
import PyParse
|
||||||
from configHandler import idleConf
|
from configHandler import idleConf
|
||||||
import aboutDialog, textView, configDialog
|
import aboutDialog, textView, configDialog
|
||||||
|
import macosxSupport
|
||||||
|
|
||||||
# The default tab setting for a Text widget, in average-width characters.
|
# The default tab setting for a Text widget, in average-width characters.
|
||||||
TK_TABWIDTH_DEFAULT = 8
|
TK_TABWIDTH_DEFAULT = 8
|
||||||
|
@ -66,9 +67,18 @@ class EditorWindow(object):
|
||||||
'Python%d%d.chm' % sys.version_info[:2])
|
'Python%d%d.chm' % sys.version_info[:2])
|
||||||
if os.path.isfile(chmfile):
|
if os.path.isfile(chmfile):
|
||||||
dochome = chmfile
|
dochome = chmfile
|
||||||
|
|
||||||
|
elif macosxSupport.runningAsOSXApp():
|
||||||
|
# documentation is stored inside the python framework
|
||||||
|
dochome = os.path.join(sys.prefix,
|
||||||
|
'Resources/English.lproj/Documentation/index.html')
|
||||||
|
|
||||||
dochome = os.path.normpath(dochome)
|
dochome = os.path.normpath(dochome)
|
||||||
if os.path.isfile(dochome):
|
if os.path.isfile(dochome):
|
||||||
EditorWindow.help_url = dochome
|
EditorWindow.help_url = dochome
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
# Safari requires real file:-URLs
|
||||||
|
EditorWindow.help_url = 'file://' + EditorWindow.help_url
|
||||||
else:
|
else:
|
||||||
EditorWindow.help_url = "http://www.python.org/doc/current"
|
EditorWindow.help_url = "http://www.python.org/doc/current"
|
||||||
currentTheme=idleConf.CurrentTheme()
|
currentTheme=idleConf.CurrentTheme()
|
||||||
|
@ -278,6 +288,10 @@ class EditorWindow(object):
|
||||||
|
|
||||||
def set_status_bar(self):
|
def set_status_bar(self):
|
||||||
self.status_bar = self.MultiStatusBar(self.top)
|
self.status_bar = self.MultiStatusBar(self.top)
|
||||||
|
if macosxSupport.runningAsOSXApp():
|
||||||
|
# Insert some padding to avoid obscuring some of the statusbar
|
||||||
|
# by the resize widget.
|
||||||
|
self.status_bar.set_label('_padding1', ' ', side=RIGHT)
|
||||||
self.status_bar.set_label('column', 'Col: ?', side=RIGHT)
|
self.status_bar.set_label('column', 'Col: ?', side=RIGHT)
|
||||||
self.status_bar.set_label('line', 'Ln: ?', side=RIGHT)
|
self.status_bar.set_label('line', 'Ln: ?', side=RIGHT)
|
||||||
self.status_bar.pack(side=BOTTOM, fill=X)
|
self.status_bar.pack(side=BOTTOM, fill=X)
|
||||||
|
@ -301,6 +315,11 @@ class EditorWindow(object):
|
||||||
("help", "_Help"),
|
("help", "_Help"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if macosxSupport.runningAsOSXApp():
|
||||||
|
del menu_specs[-3]
|
||||||
|
menu_specs[-2] = ("windows", "_Window")
|
||||||
|
|
||||||
|
|
||||||
def createmenubar(self):
|
def createmenubar(self):
|
||||||
mbar = self.menubar
|
mbar = self.menubar
|
||||||
self.menudict = menudict = {}
|
self.menudict = menudict = {}
|
||||||
|
@ -308,6 +327,12 @@ class EditorWindow(object):
|
||||||
underline, label = prepstr(label)
|
underline, label = prepstr(label)
|
||||||
menudict[name] = menu = Menu(mbar, name=name)
|
menudict[name] = menu = Menu(mbar, name=name)
|
||||||
mbar.add_cascade(label=label, menu=menu, underline=underline)
|
mbar.add_cascade(label=label, menu=menu, underline=underline)
|
||||||
|
|
||||||
|
if sys.platform == 'darwin' and '.framework' in sys.executable:
|
||||||
|
# Insert the application menu
|
||||||
|
menudict['application'] = menu = Menu(mbar, name='apple')
|
||||||
|
mbar.add_cascade(label='IDLE', menu=menu)
|
||||||
|
|
||||||
self.fill_menus()
|
self.fill_menus()
|
||||||
self.base_helpmenu_length = self.menudict['help'].index(END)
|
self.base_helpmenu_length = self.menudict['help'].index(END)
|
||||||
self.reset_help_menu_entries()
|
self.reset_help_menu_entries()
|
||||||
|
|
|
@ -11,6 +11,7 @@ import time
|
||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
import types
|
import types
|
||||||
|
import macosxSupport
|
||||||
|
|
||||||
import linecache
|
import linecache
|
||||||
from code import InteractiveInterpreter
|
from code import InteractiveInterpreter
|
||||||
|
@ -777,6 +778,11 @@ class PyShell(OutputWindow):
|
||||||
("help", "_Help"),
|
("help", "_Help"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if macosxSupport.runningAsOSXApp():
|
||||||
|
del menu_specs[-3]
|
||||||
|
menu_specs[-2] = ("windows", "_Window")
|
||||||
|
|
||||||
|
|
||||||
# New classes
|
# New classes
|
||||||
from IdleHistory import History
|
from IdleHistory import History
|
||||||
|
|
||||||
|
@ -1371,9 +1377,12 @@ def main():
|
||||||
enable_shell = enable_shell or not edit_start
|
enable_shell = enable_shell or not edit_start
|
||||||
# start editor and/or shell windows:
|
# start editor and/or shell windows:
|
||||||
root = Tk(className="Idle")
|
root = Tk(className="Idle")
|
||||||
|
|
||||||
fixwordbreaks(root)
|
fixwordbreaks(root)
|
||||||
root.withdraw()
|
root.withdraw()
|
||||||
flist = PyShellFileList(root)
|
flist = PyShellFileList(root)
|
||||||
|
macosxSupport.setupApp(root, flist)
|
||||||
|
|
||||||
if enable_edit:
|
if enable_edit:
|
||||||
if not (cmd or script):
|
if not (cmd or script):
|
||||||
for filename in args:
|
for filename in args:
|
||||||
|
@ -1381,8 +1390,17 @@ def main():
|
||||||
if not args:
|
if not args:
|
||||||
flist.new()
|
flist.new()
|
||||||
if enable_shell:
|
if enable_shell:
|
||||||
if not flist.open_shell():
|
shell = flist.open_shell()
|
||||||
|
if not shell:
|
||||||
return # couldn't open shell
|
return # couldn't open shell
|
||||||
|
|
||||||
|
if macosxSupport.runningAsOSXApp() and flist.dict:
|
||||||
|
# On OSX: when the user has double-clicked on a file that causes
|
||||||
|
# IDLE to be launched the shell window will open just in front of
|
||||||
|
# the file she wants to see. Lower the interpreter window when
|
||||||
|
# there are open files.
|
||||||
|
shell.top.lower()
|
||||||
|
|
||||||
shell = flist.pyshell
|
shell = flist.pyshell
|
||||||
# handle remaining options:
|
# handle remaining options:
|
||||||
if debug:
|
if debug:
|
||||||
|
@ -1403,6 +1421,7 @@ def main():
|
||||||
elif script:
|
elif script:
|
||||||
shell.interp.prepend_syspath(script)
|
shell.interp.prepend_syspath(script)
|
||||||
shell.interp.execfile(script)
|
shell.interp.execfile(script)
|
||||||
|
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
root.destroy()
|
root.destroy()
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import macosxSupport
|
||||||
|
|
||||||
class ZoomHeight:
|
class ZoomHeight:
|
||||||
|
|
||||||
|
@ -29,6 +30,14 @@ def zoom_height(top):
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
newy = 0
|
newy = 0
|
||||||
newheight = newheight - 72
|
newheight = newheight - 72
|
||||||
|
|
||||||
|
elif macosxSupport.runningAsOSXApp():
|
||||||
|
# The '88' below is a magic number that avoids placing the bottom
|
||||||
|
# of the window below the panel on my machine. I don't know how
|
||||||
|
# to calculate the correct value for this with tkinter.
|
||||||
|
newy = 22
|
||||||
|
newheight = newheight - newy - 88
|
||||||
|
|
||||||
else:
|
else:
|
||||||
#newy = 24
|
#newy = 24
|
||||||
newy = 0
|
newy = 0
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
#
|
|
||||||
# After running python setup.py install, run this program from the command
|
|
||||||
# line like so:
|
|
||||||
#
|
|
||||||
# % python2.3 buildapp.py build
|
|
||||||
#
|
|
||||||
# A double-clickable IDLE application will be created in the build/ directory.
|
|
||||||
#
|
|
||||||
|
|
||||||
from bundlebuilder import buildapp
|
|
||||||
|
|
||||||
buildapp(
|
|
||||||
name="IDLE",
|
|
||||||
mainprogram="idle.py",
|
|
||||||
argv_emulation=1,
|
|
||||||
iconfile="Icons/idle.icns",
|
|
||||||
)
|
|
|
@ -20,6 +20,7 @@ configuration problem notification and resolution.
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import string
|
import string
|
||||||
|
import macosxSupport
|
||||||
from ConfigParser import ConfigParser, NoOptionError, NoSectionError
|
from ConfigParser import ConfigParser, NoOptionError, NoSectionError
|
||||||
|
|
||||||
class InvalidConfigType(Exception): pass
|
class InvalidConfigType(Exception): pass
|
||||||
|
@ -495,7 +496,18 @@ class IdleConf:
|
||||||
return binding
|
return binding
|
||||||
|
|
||||||
def GetCurrentKeySet(self):
|
def GetCurrentKeySet(self):
|
||||||
return self.GetKeySet(self.CurrentKeys())
|
result = self.GetKeySet(self.CurrentKeys())
|
||||||
|
|
||||||
|
if macosxSupport.runningAsOSXApp():
|
||||||
|
# We're using AquaTk, replace all keybingings that use the
|
||||||
|
# Alt key by ones that use the Option key because the former
|
||||||
|
# don't work reliably.
|
||||||
|
for k, v in result.items():
|
||||||
|
v2 = [ x.replace('<Alt-', '<Option-') for x in v ]
|
||||||
|
if v != v2:
|
||||||
|
result[k] = v2
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def GetKeySet(self,keySetName):
|
def GetKeySet(self,keySetName):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -133,7 +133,7 @@ class GetKeysDialog(Toplevel):
|
||||||
config-keys.def must use the same ordering.
|
config-keys.def must use the same ordering.
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
if sys.platform == 'darwin' and sys.executable.count('.app'):
|
if sys.platform == 'darwin' and sys.argv[0].count('.app'):
|
||||||
self.modifiers = ['Shift', 'Control', 'Option', 'Command']
|
self.modifiers = ['Shift', 'Control', 'Option', 'Command']
|
||||||
else:
|
else:
|
||||||
self.modifiers = ['Control', 'Alt', 'Shift']
|
self.modifiers = ['Control', 'Alt', 'Shift']
|
||||||
|
|
36
Lib/idlelib/macosxSupport.py
Normal file
36
Lib/idlelib/macosxSupport.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
"""
|
||||||
|
A number of function that enhance IDLE on MacOSX when it used as a normal
|
||||||
|
GUI application (as opposed to an X11 application).
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def runningAsOSXApp():
|
||||||
|
""" Returns True iff running from the IDLE.app bundle on OSX """
|
||||||
|
return (sys.platform == 'darwin' and 'IDLE.app' in sys.argv[0])
|
||||||
|
|
||||||
|
def addOpenEventSupport(root, flist):
|
||||||
|
"""
|
||||||
|
This ensures that the application will respont to open AppleEvents, which
|
||||||
|
makes is feaseable to use IDLE as the default application for python files.
|
||||||
|
"""
|
||||||
|
def doOpenFile(*args):
|
||||||
|
for fn in args:
|
||||||
|
flist.open(fn)
|
||||||
|
|
||||||
|
# The command below is a hook in aquatk that is called whenever the app
|
||||||
|
# receives a file open event. The callback can have multiple arguments,
|
||||||
|
# one for every file that should be opened.
|
||||||
|
root.createcommand("::tk::mac::OpenDocument", doOpenFile)
|
||||||
|
|
||||||
|
def hideTkConsole(root):
|
||||||
|
root.tk.call('console', 'hide')
|
||||||
|
|
||||||
|
|
||||||
|
def setupApp(root, flist):
|
||||||
|
"""
|
||||||
|
Perform setup for the OSX application bundle.
|
||||||
|
"""
|
||||||
|
if not runningAsOSXApp(): return
|
||||||
|
|
||||||
|
hideTkConsole(root)
|
||||||
|
addOpenEventSupport(root, flist)
|
Loading…
Add table
Add a link
Reference in a new issue