1# Based on http://cocoawithlove.com/2010/09/minimalist-cocoa-programming.html 2# by Juraj Sukop. This demo was eventually expanded into a more complete 3# Cocoa library available at https://bitbucket.org/sukop/nspython . 4 5from cffi import FFI 6 7ffi = FFI() 8ffi.cdef(''' 9 10 typedef signed char BOOL; 11 12 typedef long NSInteger; 13 typedef unsigned long NSUInteger; 14 typedef NSInteger NSApplicationActivationPolicy; 15 typedef NSUInteger NSBackingStoreType; 16 typedef NSUInteger NSStringEncoding; 17 18 typedef double CGFloat; 19 struct CGPoint { 20 CGFloat x; 21 CGFloat y; 22 }; 23 typedef struct CGPoint CGPoint; 24 struct CGSize { 25 CGFloat width; 26 CGFloat height; 27 }; 28 typedef struct CGSize CGSize; 29 struct CGRect { 30 CGPoint origin; 31 CGSize size; 32 }; 33 typedef struct CGRect CGRect; 34 35 typedef CGPoint NSPoint; 36 typedef CGSize NSSize; 37 typedef CGRect NSRect; 38 39 typedef struct objc_class *Class; 40 typedef struct objc_object { 41 Class isa; 42 } *id; 43 typedef struct objc_selector *SEL; 44 45 SEL sel_registerName(const char *str); 46 id objc_getClass(const char *name); 47 id objc_msgSend(id theReceiver, SEL theSelector, ...); 48 49''') 50 51objc = ffi.dlopen('objc') 52appkit = ffi.dlopen('AppKit') 53 54nil = ffi.NULL 55YES = ffi.cast('BOOL', 1) 56NO = ffi.cast('BOOL', 0) 57 58NSASCIIStringEncoding = ffi.cast('NSStringEncoding', 1) 59NSApplicationActivationPolicyRegular = ffi.cast('NSApplicationActivationPolicy', 0) 60NSTitledWindowMask = ffi.cast('NSUInteger', 1) 61NSBackingStoreBuffered = ffi.cast('NSBackingStoreType', 2) 62 63NSMakePoint = lambda x, y: ffi.new('NSPoint *', (x, y))[0] 64NSMakeRect = lambda x, y, w, h: ffi.new('NSRect *', ((x, y), (w, h)))[0] 65 66get, send, sel = objc.objc_getClass, objc.objc_msgSend, objc.sel_registerName 67at = lambda s: send( 68 get('NSString'), 69 sel('stringWithCString:encoding:'), 70 ffi.new('char[]', s), NSASCIIStringEncoding) 71 72send(get('NSAutoreleasePool'), sel('new')) 73app = send(get('NSApplication'), sel('sharedApplication')) 74send(app, sel('setActivationPolicy:'), NSApplicationActivationPolicyRegular) 75 76menubar = send(send(get('NSMenu'), sel('new')), sel('autorelease')) 77appMenuItem = send(send(get('NSMenuItem'), sel('new')), sel('autorelease')) 78send(menubar, sel('addItem:'), appMenuItem) 79send(app, sel('setMainMenu:'), menubar) 80 81appMenu = send(send(get('NSMenu'), sel('new')), sel('autorelease')) 82appName = send(send(get('NSProcessInfo'), sel('processInfo')), sel('processName')) 83quitTitle = send(at('Quit '), sel('stringByAppendingString:'), appName) 84quitMenuItem = send(send(send( 85 get('NSMenuItem'), sel('alloc')), 86 sel('initWithTitle:action:keyEquivalent:'), 87 quitTitle, sel('terminate:'), at('q')), 88 sel('autorelease')) 89send(appMenu, sel('addItem:'), quitMenuItem) 90send(appMenuItem, sel('setSubmenu:'), appMenu) 91 92window = send(send(send( 93 get('NSWindow'), sel('alloc')), 94 sel('initWithContentRect:styleMask:backing:defer:'), 95 NSMakeRect(0, 0, 200, 200), NSTitledWindowMask, NSBackingStoreBuffered, NO), 96 sel('autorelease')) 97send(window, sel('cascadeTopLeftFromPoint:'), NSMakePoint(20, 20)) 98send(window, sel('setTitle:'), appName) 99send(window, sel('makeKeyAndOrderFront:'), nil) 100 101send(app, sel('activateIgnoringOtherApps:'), YES) 102send(app, sel('run')) 103