diff options
| author | Pietro Gagliardi <[email protected]> | 2014-07-08 16:47:28 -0400 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2014-07-08 16:47:28 -0400 |
| commit | b4357db4be6688c67e522b637f100ceecc4a9680 (patch) | |
| tree | 4b631edcb1e1fed7e6287b41b63a6a08d5aa3a45 | |
| parent | 60d0953fe9f16726958f709007402ea4c8b89fc6 (diff) | |
Added the beginning of the Mac OS X code.
| -rw-r--r-- | redo/common_unix.go | 2 | ||||
| -rw-r--r-- | redo/controls_unix.go | 2 | ||||
| -rw-r--r-- | redo/objc_darwin.h | 28 | ||||
| -rw-r--r-- | redo/uitask_darwin.go | 32 | ||||
| -rw-r--r-- | redo/uitask_darwin.m | 58 | ||||
| -rw-r--r-- | redo/uitask_unix.go | 2 | ||||
| -rw-r--r-- | redo/window_darwin.go | 118 | ||||
| -rw-r--r-- | redo/window_darwin.m | 45 | ||||
| -rw-r--r-- | redo/window_unix.go | 2 | ||||
| -rw-r--r-- | redo/zz_test.go | 9 |
10 files changed, 296 insertions, 2 deletions
diff --git a/redo/common_unix.go b/redo/common_unix.go index e2d9261..4b36318 100644 --- a/redo/common_unix.go +++ b/redo/common_unix.go @@ -1,3 +1,5 @@ +// +build !darwin + // 7 july 2014 package ui diff --git a/redo/controls_unix.go b/redo/controls_unix.go index 008888f..1be152b 100644 --- a/redo/controls_unix.go +++ b/redo/controls_unix.go @@ -1,3 +1,5 @@ +// +build !darwin + // 7 july 2014 package ui diff --git a/redo/objc_darwin.h b/redo/objc_darwin.h new file mode 100644 index 0000000..b3d362d --- /dev/null +++ b/redo/objc_darwin.h @@ -0,0 +1,28 @@ +/* 8 july 2014 */ + +/* cgo will include this file multiple times */ +#ifndef __GO_UI_OBJC_DARWIN_H__ +#define __GO_UI_OBJC_DARWIN_H__ + +#include <stdlib.h> +#include <stdint.h> +#include <objc/message.h> +#include <objc/objc.h> +#include <objc/runtime.h> + +/* uitask_darwin.m */ +extern id getAppDelegate(void); /* used by the other .m files */ +extern BOOL uiinit(void); +extern void uimsgloop(void); +extern void issue(void *); + +/* window_darwin.m */ +extern id newWindow(intptr_t, intptr_t); +extern void windowSetAppDelegate(id); +extern const char *windowTitle(id); +extern void windowSetTitle(id, const char *); +extern void windowShow(id); +extern void windowHide(id); +extern void windowClose(id); + +#endif diff --git a/redo/uitask_darwin.go b/redo/uitask_darwin.go new file mode 100644 index 0000000..da9a47b --- /dev/null +++ b/redo/uitask_darwin.go @@ -0,0 +1,32 @@ +// 8 july 2014 + +package ui + +import ( + "unsafe" +) + +// #cgo CFLAGS: -DTODO +// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit +// #include "objc_darwin.h" +import "C" + +func uiinit() error { + // TODO check error + C.uiinit() + return nil +} + +func uimsgloop() { + C.uimsgloop() +} + +func issue(req *Request) { + C.issue(unsafe.Pointer(req)) +} + +//export doissue +func doissue(r unsafe.Pointer) { + req := (*Request)(unsafe.Pointer(r)) + perform(req) +} diff --git a/redo/uitask_darwin.m b/redo/uitask_darwin.m new file mode 100644 index 0000000..796bc18 --- /dev/null +++ b/redo/uitask_darwin.m @@ -0,0 +1,58 @@ +// 8 july 2014 + +#import "objc_darwin.h" +#import "_cgo_export.h" +#import <Cocoa/Cocoa.h> + +@interface appDelegateClass : NSObject +@end + +@implementation appDelegateClass + +- (void)issue:(id)obj +{ + NSValue *what = (NSValue *) obj; + + doissue([what pointerValue]); +} + +@end + +appDelegateClass *appDelegate; + +id getAppDelegate(void) +{ + return appDelegate; +} + +BOOL uiinit(void) +{ + appDelegate = [appDelegateClass new]; + [NSApplication sharedApplication]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + [NSApp activateIgnoringOtherApps:YES]; // TODO rsc does this; finder says NO? + [NSApp setDelegate:appDelegate]; + return YES; +} + +void uimsgloop(void) +{ + [NSApp run]; +} + +// Ideally we would have this work like on the other platforms and issue a NSEvent to the end of the event queue +// Unfortunately, there doesn't seem to be a way for NSEvents to hold pointer values, only (signed) NSIntegers +// So we'll have to do the performSelectorOnMainThread: approach +// [TODO] +void issue(void *what) +{ + NSAutoreleasePool *p; + NSValue *v; + + p = [NSAutoreleasePool new]; + v = [NSValue valueWithPointer:what]; + [appDelegate performSelectorOnMainThread:@selector(issue:) + withObject:v + waitUntilDone:NO]; + [p release]; +} diff --git a/redo/uitask_unix.go b/redo/uitask_unix.go index e371303..d603a27 100644 --- a/redo/uitask_unix.go +++ b/redo/uitask_unix.go @@ -1,3 +1,5 @@ +// +build !darwin + // 7 july 2014 package ui diff --git a/redo/window_darwin.go b/redo/window_darwin.go new file mode 100644 index 0000000..c6d9585 --- /dev/null +++ b/redo/window_darwin.go @@ -0,0 +1,118 @@ +// 8 july 2014 + +package ui + +import ( + "unsafe" +) + +// #include "objc_darwin.h" +import "C" + +type window struct { + id C.id + + closing *event +} + +func newWindow(title string, width int, height int) *Request { + c := make(chan interface{}) + return &Request{ + op: func() { + id := C.newWindow(C.intptr_t(width), C.intptr_t(height)) + ctitle := C.CString(title) + defer C.free(unsafe.Pointer(ctitle)) + C.windowSetTitle(id, ctitle) + C.windowSetAppDelegate(id) + c <- &window{ + id: id, + closing: newEvent(), + } + }, + resp: c, + } +} + +func (w *window) SetControl(control Control) *Request { + c := make(chan interface{}) + return &Request{ + op: func() { + // TODO unparent + // TODO reparent + c <- struct{}{} + }, + resp: c, + } +} + +func (w *window) Title() *Request { + c := make(chan interface{}) + return &Request{ + op: func() { + c <- C.GoString(C.windowTitle(w.id)) + }, + resp: c, + } +} + +func (w *window) SetTitle(title string) *Request { + c := make(chan interface{}) + return &Request{ + op: func() { + ctitle := C.CString(title) + defer C.free(unsafe.Pointer(ctitle)) + C.windowSetTitle(w.id, ctitle) + c <- struct{}{} + }, + resp: c, + } +} + +func (w *window) Show() *Request { + c := make(chan interface{}) + return &Request{ + op: func() { + C.windowShow(w.id) + c <- struct{}{} + }, + resp: c, + } +} + +func (w *window) Hide() *Request { + c := make(chan interface{}) + return &Request{ + op: func() { + C.windowHide(w.id) + c <- struct{}{} + }, + resp: c, + } +} + +func (w *window) Close() *Request { + c := make(chan interface{}) + return &Request{ + op: func() { + C.windowClose(w.id) + c <- struct{}{} + }, + resp: c, + } +} + +func (w *window) OnClosing(e func(c Doer) bool) *Request { + c := make(chan interface{}) + return &Request{ + op: func() { + w.closing.setbool(e) + c <- struct{}{} + }, + resp: c, + } +} + +// TODO windowClosing + +// TODO for testing +func newButton(string) *Request { return nil } diff --git a/redo/window_darwin.m b/redo/window_darwin.m new file mode 100644 index 0000000..870243c --- /dev/null +++ b/redo/window_darwin.m @@ -0,0 +1,45 @@ +// 8 july 2014 + +#import "objc_darwin.h" +#import "_cgo_export.h" +#import <Cocoa/Cocoa.h> + +#define toNSWindow(x) ((NSWindow *) (x)) + +id newWindow(intptr_t width, intptr_t height) +{ + return [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, (CGFloat) width, (CGFloat) height) + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) + backing:NSBackingStoreBuffered + defer:YES]; +} + +void windowSetAppDelegate(id win) +{ + [toNSWindow(win) setDelegate:getAppDelegate()]; +} + +const char *windowTitle(id win) +{ + return [[toNSWindow(win) title] UTF8String]; +} + +void windowSetTitle(id win, const char * title) +{ + [toNSWindow(win) setTitle:[NSString stringWithUTF8String:title]]; +} + +void windowShow(id win) +{ + [toNSWindow(win) makeKeyAndOrderFront:toNSWindow(win)]; +} + +void windowHide(id win) +{ + [toNSWindow(win) orderOut:toNSWindow(win)]; +} + +void windowClose(id win) +{ + // TODO +} diff --git a/redo/window_unix.go b/redo/window_unix.go index c92fba6..85b8e93 100644 --- a/redo/window_unix.go +++ b/redo/window_unix.go @@ -1,3 +1,5 @@ +// +build !darwin + // 7 july 2014 package ui diff --git a/redo/zz_test.go b/redo/zz_test.go index 122005b..9df45fd 100644 --- a/redo/zz_test.go +++ b/redo/zz_test.go @@ -8,7 +8,8 @@ import ( "testing" ) -func TestPackage(t *testing.T) { +// because Cocoa hates being run off the main thread, even if it's run exclusively off the main thread +func init() { go func() { w := GetNewWindow(Do, "Hello", 320, 240) done := make(chan struct{}) @@ -21,6 +22,10 @@ func TestPackage(t *testing.T) { }() err := Go() if err != nil { - t.Error(err) + panic(err) } } + +func TestDummy(t *testing.T) { + // do nothing +} |
