1"""PythonBrowser.py -- a module and/or demo program implementing a Python 2object browser. 3 4It can be used in two ways: 51) as a standalone demo app that shows how to use the NSOutlineView class 62) as a module to add an object browser to your app. 7 8For the latter usage, include PythonBrowser.nib in your app bundle, 9make sure that PythonBrowser.py and PythonBrowserModel.py can be found 10on sys.path, and call 11 12 PythonBrowser.PythonBrowserWindowController(aBrowsableObject) 13 14from your app. The object to be browsed can't be a number, a string or 15None, any other kind of object is fine. 16 17To build the demo program, run this line in Terminal.app: 18 19 $ python setup.py py2app -A 20 21This creates a directory "dist" containing PythonBrowser.app. (The 22-A option causes the files to be symlinked to the .app bundle instead 23of copied. This means you don't have to rebuild the app if you edit the 24sources or nibs.) 25""" 26 27from Cocoa import * 28import sys 29 30 31# class defined in PythonBrowser.nib 32class PythonBrowserWindowController(NSWindowController): 33 outlineView = objc.IBOutlet() 34 35 def __new__(cls, obj): 36 # "Pythonic" constructor 37 return cls.alloc().initWithObject_(obj) 38 39 def initWithObject_(self, obj): 40 from PythonBrowserModel import PythonBrowserModel 41 self = self.initWithWindowNibName_("PythonBrowser") 42 self.setWindowTitleForObject_(obj) 43 self.model = PythonBrowserModel.alloc().initWithObject_(obj) 44 self.outlineView.setDataSource_(self.model) 45 self.outlineView.setDelegate_(self.model) 46 self.outlineView.setTarget_(self) 47 self.outlineView.setDoubleAction_("doubleClick:") 48 self.window().makeFirstResponder_(self.outlineView) 49 self.showWindow_(self) 50 # The window controller doesn't need to be retained (referenced) 51 # anywhere, so we pretend to have a reference to ourselves to avoid 52 # being garbage collected before the window is closed. The extra 53 # reference will be released in self.windowWillClose_() 54 self.retain() 55 return self 56 57 def windowWillClose_(self, notification): 58 # see comment in self.initWithObject_() 59 self.autorelease() 60 61 def setWindowTitleForObject_(self, obj): 62 if hasattr(obj, "__name__"): 63 title = "PythonBrowser -- %s: %s" % (type(obj).__name__, obj.__name__) 64 else: 65 title = "PythonBrowser -- %s" % (type(obj).__name__,) 66 self.window().setTitle_(title) 67 68 def setObject_(self, obj): 69 self.setWindowTitleForObject_(obj) 70 self.model.setObject_(obj) 71 self.outlineView.reloadData() 72 73 @objc.IBAction 74 def doubleClick_(self, sender): 75 # Open a new browser window for each selected expandable item 76 for row in self.outlineView.selectedRowEnumerator(): 77 item = self.outlineView.itemAtRow_(row) 78 if item.isExpandable(): 79 PythonBrowserWindowController(item.object) 80 81 @objc.IBAction 82 def pickRandomModule_(self, sender): 83 """Test method, hooked up from the "Pick Random Module" menu in 84 MainMenu.nib, to test changing the browsed object after the window 85 has been created.""" 86 from random import choice 87 mod = None 88 while mod is None: 89 mod = sys.modules[choice(sys.modules.keys())] 90 self.setObject_(mod) 91 92 93class PythonBrowserAppDelegate(NSObject): 94 95 def applicationDidFinishLaunching_(self, notification): 96 self.newBrowser_(self) 97 98 @objc.IBAction 99 def newBrowser_(self, sender): 100 # The PythonBrowserWindowController instance will retain itself, 101 # so we don't (have to) keep track of all instances here. 102 PythonBrowserWindowController(sys) 103 104 105if __name__ == "__main__": 106 from PyObjCTools import AppHelper 107 AppHelper.runEventLoop() 108