summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-07-08 16:47:28 -0400
committerPietro Gagliardi <[email protected]>2014-07-08 16:47:28 -0400
commitb4357db4be6688c67e522b637f100ceecc4a9680 (patch)
tree4b631edcb1e1fed7e6287b41b63a6a08d5aa3a45
parent60d0953fe9f16726958f709007402ea4c8b89fc6 (diff)
Added the beginning of the Mac OS X code.
-rw-r--r--redo/common_unix.go2
-rw-r--r--redo/controls_unix.go2
-rw-r--r--redo/objc_darwin.h28
-rw-r--r--redo/uitask_darwin.go32
-rw-r--r--redo/uitask_darwin.m58
-rw-r--r--redo/uitask_unix.go2
-rw-r--r--redo/window_darwin.go118
-rw-r--r--redo/window_darwin.m45
-rw-r--r--redo/window_unix.go2
-rw-r--r--redo/zz_test.go9
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
+}