Added the beginning of the Mac OS X code.

This commit is contained in:
Pietro Gagliardi 2014-07-08 16:47:28 -04:00
parent 60d0953fe9
commit b4357db4be
10 changed files with 296 additions and 2 deletions

View File

@ -1,3 +1,5 @@
// +build !darwin
// 7 july 2014
package ui

View File

@ -1,3 +1,5 @@
// +build !darwin
// 7 july 2014
package ui

28
redo/objc_darwin.h Normal file
View File

@ -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

32
redo/uitask_darwin.go Normal file
View File

@ -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)
}

58
redo/uitask_darwin.m Normal file
View File

@ -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];
}

View File

@ -1,3 +1,5 @@
// +build !darwin
// 7 july 2014
package ui

118
redo/window_darwin.go Normal file
View File

@ -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 }

45
redo/window_darwin.m Normal file
View File

@ -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
}

View File

@ -1,3 +1,5 @@
// +build !darwin
// 7 july 2014
package ui

View File

@ -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
}