You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.3 KiB
103 lines
3.3 KiB
# Based on http://cocoawithlove.com/2010/09/minimalist-cocoa-programming.html
|
|
# by Juraj Sukop. This demo was eventually expanded into a more complete
|
|
# Cocoa library available at https://bitbucket.org/sukop/nspython .
|
|
|
|
from cffi import FFI
|
|
|
|
ffi = FFI()
|
|
ffi.cdef('''
|
|
|
|
typedef signed char BOOL;
|
|
|
|
typedef long NSInteger;
|
|
typedef unsigned long NSUInteger;
|
|
typedef NSInteger NSApplicationActivationPolicy;
|
|
typedef NSUInteger NSBackingStoreType;
|
|
typedef NSUInteger NSStringEncoding;
|
|
|
|
typedef double CGFloat;
|
|
struct CGPoint {
|
|
CGFloat x;
|
|
CGFloat y;
|
|
};
|
|
typedef struct CGPoint CGPoint;
|
|
struct CGSize {
|
|
CGFloat width;
|
|
CGFloat height;
|
|
};
|
|
typedef struct CGSize CGSize;
|
|
struct CGRect {
|
|
CGPoint origin;
|
|
CGSize size;
|
|
};
|
|
typedef struct CGRect CGRect;
|
|
|
|
typedef CGPoint NSPoint;
|
|
typedef CGSize NSSize;
|
|
typedef CGRect NSRect;
|
|
|
|
typedef struct objc_class *Class;
|
|
typedef struct objc_object {
|
|
Class isa;
|
|
} *id;
|
|
typedef struct objc_selector *SEL;
|
|
|
|
SEL sel_registerName(const char *str);
|
|
id objc_getClass(const char *name);
|
|
id objc_msgSend(id theReceiver, SEL theSelector, ...);
|
|
|
|
''')
|
|
|
|
objc = ffi.dlopen('objc')
|
|
appkit = ffi.dlopen('AppKit')
|
|
|
|
nil = ffi.NULL
|
|
YES = ffi.cast('BOOL', 1)
|
|
NO = ffi.cast('BOOL', 0)
|
|
|
|
NSASCIIStringEncoding = ffi.cast('NSStringEncoding', 1)
|
|
NSApplicationActivationPolicyRegular = ffi.cast('NSApplicationActivationPolicy', 0)
|
|
NSTitledWindowMask = ffi.cast('NSUInteger', 1)
|
|
NSBackingStoreBuffered = ffi.cast('NSBackingStoreType', 2)
|
|
|
|
NSMakePoint = lambda x, y: ffi.new('NSPoint *', (x, y))[0]
|
|
NSMakeRect = lambda x, y, w, h: ffi.new('NSRect *', ((x, y), (w, h)))[0]
|
|
|
|
get, send, sel = objc.objc_getClass, objc.objc_msgSend, objc.sel_registerName
|
|
at = lambda s: send(
|
|
get('NSString'),
|
|
sel('stringWithCString:encoding:'),
|
|
ffi.new('char[]', s), NSASCIIStringEncoding)
|
|
|
|
send(get('NSAutoreleasePool'), sel('new'))
|
|
app = send(get('NSApplication'), sel('sharedApplication'))
|
|
send(app, sel('setActivationPolicy:'), NSApplicationActivationPolicyRegular)
|
|
|
|
menubar = send(send(get('NSMenu'), sel('new')), sel('autorelease'))
|
|
appMenuItem = send(send(get('NSMenuItem'), sel('new')), sel('autorelease'))
|
|
send(menubar, sel('addItem:'), appMenuItem)
|
|
send(app, sel('setMainMenu:'), menubar)
|
|
|
|
appMenu = send(send(get('NSMenu'), sel('new')), sel('autorelease'))
|
|
appName = send(send(get('NSProcessInfo'), sel('processInfo')), sel('processName'))
|
|
quitTitle = send(at('Quit '), sel('stringByAppendingString:'), appName)
|
|
quitMenuItem = send(send(send(
|
|
get('NSMenuItem'), sel('alloc')),
|
|
sel('initWithTitle:action:keyEquivalent:'),
|
|
quitTitle, sel('terminate:'), at('q')),
|
|
sel('autorelease'))
|
|
send(appMenu, sel('addItem:'), quitMenuItem)
|
|
send(appMenuItem, sel('setSubmenu:'), appMenu)
|
|
|
|
window = send(send(send(
|
|
get('NSWindow'), sel('alloc')),
|
|
sel('initWithContentRect:styleMask:backing:defer:'),
|
|
NSMakeRect(0, 0, 200, 200), NSTitledWindowMask, NSBackingStoreBuffered, NO),
|
|
sel('autorelease'))
|
|
send(window, sel('cascadeTopLeftFromPoint:'), NSMakePoint(20, 20))
|
|
send(window, sel('setTitle:'), appName)
|
|
send(window, sel('makeKeyAndOrderFront:'), nil)
|
|
|
|
send(app, sel('activateIgnoringOtherApps:'), YES)
|
|
send(app, sel('run'))
|