From 19302d927e6688e02553df16177e4867e2d0e3b3 Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Sun, 11 Jun 2006 14:33:36 +0000 Subject: 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. --- Lib/idlelib/Bindings.py | 26 ++++++++++++++++++++++++++ Lib/idlelib/EditorWindow.py | 25 +++++++++++++++++++++++++ Lib/idlelib/PyShell.py | 21 ++++++++++++++++++++- Lib/idlelib/ZoomHeight.py | 9 +++++++++ Lib/idlelib/buildapp.py | 17 ----------------- Lib/idlelib/configHandler.py | 14 +++++++++++++- Lib/idlelib/keybindingDialog.py | 2 +- Lib/idlelib/macosxSupport.py | 36 ++++++++++++++++++++++++++++++++++++ 8 files changed, 130 insertions(+), 20 deletions(-) delete mode 100644 Lib/idlelib/buildapp.py create mode 100644 Lib/idlelib/macosxSupport.py diff --git a/Lib/idlelib/Bindings.py b/Lib/idlelib/Bindings.py index b5e90b0..a695ab7 100644 --- a/Lib/idlelib/Bindings.py +++ b/Lib/idlelib/Bindings.py @@ -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', '<>'), + None, + ('_Preferences....', '<>'), + ])) + + default_keydefs = idleConf.GetCurrentKeySet() del sys diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py index 7604293..5dca4c1 100644 --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -17,6 +17,7 @@ import ReplaceDialog import PyParse from configHandler import idleConf import aboutDialog, textView, configDialog +import macosxSupport # The default tab setting for a Text widget, in average-width characters. TK_TABWIDTH_DEFAULT = 8 @@ -66,9 +67,18 @@ class EditorWindow(object): 'Python%d%d.chm' % sys.version_info[:2]) if os.path.isfile(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) if os.path.isfile(dochome): EditorWindow.help_url = dochome + if sys.platform == 'darwin': + # Safari requires real file:-URLs + EditorWindow.help_url = 'file://' + EditorWindow.help_url else: EditorWindow.help_url = "http://www.python.org/doc/current" currentTheme=idleConf.CurrentTheme() @@ -278,6 +288,10 @@ class EditorWindow(object): def set_status_bar(self): 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('line', 'Ln: ?', side=RIGHT) self.status_bar.pack(side=BOTTOM, fill=X) @@ -301,6 +315,11 @@ class EditorWindow(object): ("help", "_Help"), ] + if macosxSupport.runningAsOSXApp(): + del menu_specs[-3] + menu_specs[-2] = ("windows", "_Window") + + def createmenubar(self): mbar = self.menubar self.menudict = menudict = {} @@ -308,6 +327,12 @@ class EditorWindow(object): underline, label = prepstr(label) menudict[name] = menu = Menu(mbar, name=name) 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.base_helpmenu_length = self.menudict['help'].index(END) self.reset_help_menu_entries() diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py index f81091b..0edd2d1 100644 --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -11,6 +11,7 @@ import time import threading import traceback import types +import macosxSupport import linecache from code import InteractiveInterpreter @@ -777,6 +778,11 @@ class PyShell(OutputWindow): ("help", "_Help"), ] + if macosxSupport.runningAsOSXApp(): + del menu_specs[-3] + menu_specs[-2] = ("windows", "_Window") + + # New classes from IdleHistory import History @@ -1371,9 +1377,12 @@ def main(): enable_shell = enable_shell or not edit_start # start editor and/or shell windows: root = Tk(className="Idle") + fixwordbreaks(root) root.withdraw() flist = PyShellFileList(root) + macosxSupport.setupApp(root, flist) + if enable_edit: if not (cmd or script): for filename in args: @@ -1381,8 +1390,17 @@ def main(): if not args: flist.new() if enable_shell: - if not flist.open_shell(): + shell = flist.open_shell() + if not 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 # handle remaining options: if debug: @@ -1403,6 +1421,7 @@ def main(): elif script: shell.interp.prepend_syspath(script) shell.interp.execfile(script) + root.mainloop() root.destroy() diff --git a/Lib/idlelib/ZoomHeight.py b/Lib/idlelib/ZoomHeight.py index 2ab4656..83ca3a6 100644 --- a/Lib/idlelib/ZoomHeight.py +++ b/Lib/idlelib/ZoomHeight.py @@ -2,6 +2,7 @@ import re import sys +import macosxSupport class ZoomHeight: @@ -29,6 +30,14 @@ def zoom_height(top): if sys.platform == 'win32': newy = 0 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: #newy = 24 newy = 0 diff --git a/Lib/idlelib/buildapp.py b/Lib/idlelib/buildapp.py deleted file mode 100644 index 672eb1e..0000000 --- a/Lib/idlelib/buildapp.py +++ /dev/null @@ -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", -) diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py index dcd9321..5ae643a 100644 --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -20,6 +20,7 @@ configuration problem notification and resolution. import os import sys import string +import macosxSupport from ConfigParser import ConfigParser, NoOptionError, NoSectionError class InvalidConfigType(Exception): pass @@ -495,7 +496,18 @@ class IdleConf: return binding 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('