2014-02-27 19:48:32 -06:00
// 27 february 2014
package main
import (
"fmt"
"unsafe"
2014-02-28 14:08:07 -06:00
"time"
2014-02-27 19:48:32 -06:00
)
2014-02-27 20:53:44 -06:00
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
2014-02-27 19:48:32 -06:00
// #include <stdlib.h>
// #include <objc/message.h>
// #include <objc/objc.h>
// #include <objc/runtime.h>
2014-02-27 20:53:44 -06:00
// /* TODO <objc/NSObjCRuntime.h not found?!?! */
// /* TODO this HAS to be unsafe */
// typedef unsigned long NSUInteger;
// /* avoid depending on Objective-C */
// #include <CoreGraphics/CGGeometry.h>
2014-02-27 19:48:32 -06:00
// /* cgo doesn't handle ... */
// id objc_msgSend_noargs(id obj, SEL sel) { return objc_msgSend(obj, sel); }
// id objc_msgSend_strarg(id obj, SEL sel, char *a) { return objc_msgSend(obj, sel, a); }
2014-02-27 20:53:44 -06:00
// id objc_msgSend_NSRect_uint_uint_bool(id obj, SEL sel, CGRect a, NSUInteger b, NSUInteger c, BOOL d) { return objc_msgSend(obj, sel, a, b, c, d); }
// id objc_msgSend_id(id obj, SEL sel, id a) { return objc_msgSend(obj, sel, a); }
2014-02-28 10:55:35 -06:00
// id objc_msgSend_NSRect(id obj, SEL sel, CGRect a) { return objc_msgSend(obj, sel, a); }
// id objc_msgSend_sel(id obj, SEL sel, SEL a) { return objc_msgSend(obj, sel, a); }
2014-02-28 11:09:15 -06:00
// id objc_msgSend_uint(id obj, SEL sel, NSUInteger a) { return objc_msgSend(obj, sel, a); }
2014-02-28 14:08:07 -06:00
// id objc_msgSend_id_sel_id_id(id obj, SEL sel, id a, SEL b, id c, id d) { return objc_msgSend(obj, sel, a, b, c, d); }
// id objc_msgSend_id_id_id(id obj, SEL sel, id a, id b, id c) { return objc_msgSend(obj, sel, a, b, c); }
// id objc_msgSend_id_id(id obj, SEL sel, id a, id b) { return objc_msgSend(obj, sel, a, b); }
2014-02-28 16:20:22 -06:00
// id objc_msgSend_sel_id_bool(id obj, SEL sel, SEL a, id b, BOOL c) { return objc_msgSend(obj, sel, a, b, c); }
2014-02-27 22:07:45 -06:00
// Class NilClass = Nil; /* for newtypes.go */
2014-02-28 14:08:07 -06:00
// id Nilid = nil;
2014-02-27 19:48:32 -06:00
import "C"
2014-02-27 19:56:08 -06:00
func objc_getClass ( class string ) C . id {
cclass := C . CString ( class )
defer C . free ( unsafe . Pointer ( cclass ) )
return C . objc_getClass ( cclass )
}
func sel_getUid ( sel string ) C . SEL {
csel := C . CString ( sel )
defer C . free ( unsafe . Pointer ( csel ) )
return C . sel_getUid ( csel )
}
2014-02-28 10:06:20 -06:00
var NSApp C . id
2014-02-28 14:08:07 -06:00
var defNC C . id
var delegate C . id
2014-02-28 16:20:22 -06:00
var notesel C . SEL
2014-02-28 10:06:20 -06:00
func init ( ) {
// need an NSApplication first - see https://github.com/TooTallNate/NodObjC/issues/21
NSApplication := objc_getClass ( "NSApplication" )
sharedApplication := sel_getUid ( "sharedApplication" )
NSApp = C . objc_msgSend_noargs ( NSApplication , sharedApplication )
2014-02-28 14:08:07 -06:00
defNC = C . objc_msgSend_noargs (
objc_getClass ( "NSNotificationCenter" ) ,
sel_getUid ( "defaultCenter" ) )
2014-02-28 10:55:35 -06:00
selW := sel_getUid ( "windowShouldClose:" )
selB := sel_getUid ( "buttonClicked:" )
2014-02-28 14:08:07 -06:00
selN := sel_getUid ( "gotNotification:" )
mk ( "hello" , selW , selB , selN )
delegate = C . objc_msgSend_noargs (
objc_getClass ( "hello" ) ,
alloc )
2014-02-28 16:20:22 -06:00
notesel = selN
2014-02-27 22:07:45 -06:00
}
2014-02-27 20:53:44 -06:00
const (
NSBorderlessWindowMask = 0
NSTitledWindowMask = 1 << 0
NSClosableWindowMask = 1 << 1
NSMiniaturizableWindowMask = 1 << 2
NSResizableWindowMask = 1 << 3
NSTexturedBackgroundWindowMask = 1 << 8
)
const (
// NSBackingStoreRetained = 0 // "You should not use this mode."
// NSBackingStoreNonretained = 1 // "You should not use this mode."
NSBackingStoreBuffered = 2
)
2014-02-28 11:09:15 -06:00
const (
NSRoundedBezelStyle = 1
)
2014-02-27 20:53:44 -06:00
var alloc = sel_getUid ( "alloc" )
2014-02-28 14:08:07 -06:00
func notify ( source string ) {
csource := C . CString ( source )
defer C . free ( unsafe . Pointer ( csource ) )
2014-02-28 16:32:55 -06:00
// we need to make an NSAutoreleasePool, otherwise we get leak warnings on stderr
pool := C . objc_msgSend_noargs (
objc_getClass ( "NSAutoreleasePool" ) ,
sel_getUid ( "new" ) )
2014-02-28 14:08:07 -06:00
src := C . objc_msgSend_strarg (
objc_getClass ( "NSString" ) ,
sel_getUid ( "stringWithUTF8String:" ) ,
csource )
2014-02-28 16:20:22 -06:00
C . objc_msgSend_sel_id_bool (
delegate ,
sel_getUid ( "performSelectorOnMainThread:withObject:waitUntilDone:" ) ,
notesel ,
2014-02-28 14:08:07 -06:00
src ,
2014-02-28 16:32:55 -06:00
C . BOOL ( C . TRUE ) ) // wait so we can properly drain the autorelease pool; on other platforms we wind up waiting anyway (since the main thread can only handle one thing at a time) so
C . objc_msgSend_noargs ( pool ,
sel_getUid ( "release" ) )
2014-02-28 14:08:07 -06:00
}
2014-02-28 10:06:20 -06:00
func main ( ) {
2014-02-27 20:53:44 -06:00
NSWindow := objc_getClass ( "NSWindow" )
NSWindowinit :=
sel_getUid ( "initWithContentRect:styleMask:backing:defer:" )
2014-02-28 10:06:20 -06:00
setDelegate := sel_getUid ( "setDelegate:" )
2014-02-27 20:53:44 -06:00
makeKeyAndOrderFront := sel_getUid ( "makeKeyAndOrderFront:" )
rect := C . CGRect {
origin : C . CGPoint { 100 , 100 } ,
size : C . CGSize { 320 , 240 } ,
}
style := C . NSUInteger ( NSTitledWindowMask | NSClosableWindowMask )
backing := C . NSUInteger ( NSBackingStoreBuffered )
deferx := C . BOOL ( C . YES )
window := C . objc_msgSend_noargs ( NSWindow , alloc )
window = C . objc_msgSend_NSRect_uint_uint_bool ( window , NSWindowinit , rect , style , backing , deferx )
C . objc_msgSend_id ( window , makeKeyAndOrderFront , window )
2014-02-28 10:06:20 -06:00
C . objc_msgSend_id ( window , setDelegate ,
delegate )
2014-02-28 10:55:35 -06:00
windowView := C . objc_msgSend_noargs ( window ,
sel_getUid ( "contentView" ) )
NSButton := objc_getClass ( "NSButton" )
button := C . objc_msgSend_noargs ( NSButton , alloc )
button = C . objc_msgSend_NSRect ( button ,
sel_getUid ( "initWithFrame:" ) ,
C . CGRect {
origin : C . CGPoint { 20 , 20 } ,
size : C . CGSize { 200 , 200 } ,
} )
C . objc_msgSend_id ( button ,
sel_getUid ( "setTarget:" ) ,
delegate )
C . objc_msgSend_sel ( button ,
sel_getUid ( "setAction:" ) ,
sel_getUid ( "buttonClicked:" ) )
2014-02-28 11:09:15 -06:00
C . objc_msgSend_uint ( button ,
sel_getUid ( "setBezelStyle:" ) ,
C . NSUInteger ( NSRoundedBezelStyle ) )
2014-02-28 10:55:35 -06:00
C . objc_msgSend_id ( windowView ,
sel_getUid ( "addSubview:" ) ,
button )
2014-02-28 14:08:07 -06:00
go func ( ) {
for {
<- time . After ( 5 * time . Second )
fmt . Println ( "five seconds passed; sending notification..." )
notify ( "timer" )
}
} ( )
2014-02-28 10:06:20 -06:00
C . objc_msgSend_noargs ( NSApp ,
sel_getUid ( "run" ) )
2014-02-27 20:53:44 -06:00
}
func helloworld ( ) {
2014-02-27 19:48:32 -06:00
_hello := C . CString ( "hello, world\n" )
defer C . free ( unsafe . Pointer ( _hello ) )
2014-02-27 19:56:08 -06:00
NSString := objc_getClass ( "NSString" )
2014-02-27 19:48:32 -06:00
stringWithUTF8String :=
2014-02-27 19:56:08 -06:00
sel_getUid ( "stringWithUTF8String:" )
2014-02-27 19:48:32 -06:00
str := C . objc_msgSend_strarg ( NSString ,
stringWithUTF8String ,
_hello )
2014-02-27 19:56:08 -06:00
UTF8String := sel_getUid ( "UTF8String" )
2014-02-27 19:48:32 -06:00
res := C . objc_msgSend_noargs ( str ,
UTF8String )
cres := ( * C . char ) ( unsafe . Pointer ( res ) )
fmt . Printf ( "%s" , C . GoString ( cres ) )
}