• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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