summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--delegate_darwin.go61
-rw-r--r--objc_darwin.go44
2 files changed, 60 insertions, 45 deletions
diff --git a/delegate_darwin.go b/delegate_darwin.go
index 8fa8097..460e930 100644
--- a/delegate_darwin.go
+++ b/delegate_darwin.go
@@ -33,36 +33,26 @@ const (
)
var (
- _uitask = sel_getUid("uitask:")
- _windowShouldClose = sel_getUid("windowShouldClose:")
- _windowDidResize = sel_getUid("windowDidResize:")
- _buttonClicked = sel_getUid("buttonClicked:")
+ _uitask = sel_getUid("uitask:") // used by uitask_darwin.go
+ _buttonClicked = sel_getUid("buttonClicked:") // used by sysdata_darwin.go
)
+var appDelegateSels = []selector{
+ selector{"uitask:", uintptr(C.appDelegate_uitask), sel_void_id,
+ "performing/dispatching UI events"},
+ selector{"windowShouldClose:", uintptr(C.appDelegate_windowShouldClose), sel_bool_id,
+ "handling window close button events"},
+ selector{"windowDidResize:", uintptr(C.appDelegate_windowDidResize), sel_void_id,
+ "handling window resize events"},
+ selector{"buttonClicked:", uintptr(C.appDelegate_buttonClicked), sel_bool_id,
+ "handling button clicks"},
+}
+
func mkAppDelegate() error {
- appdelegateclass, err := makeDelegateClass(_goAppDelegate)
+ err := makeClass(_goAppDelegate, _NSObject, appDelegateSels,
+ "application delegate (handles events)")
if err != nil {
- return fmt.Errorf("error creating NSApplication delegate: %v", err)
- }
- err = addDelegateMethod(appdelegateclass, _uitask,
- C.appDelegate_uitask, delegate_void)
- if err != nil {
- return fmt.Errorf("error adding NSApplication delegate uitask: method (to do UI tasks): %v", err)
- }
- err = addDelegateMethod(appdelegateclass, _windowShouldClose,
- C.appDelegate_windowShouldClose, delegate_bool)
- if err != nil {
- return fmt.Errorf("error adding NSApplication delegate windowShouldClose: method (to handle window close button events): %v", err)
- }
- err = addDelegateMethod(appdelegateclass, _windowDidResize,
- C.appDelegate_windowDidResize, delegate_void)
- if err != nil {
- return fmt.Errorf("error adding NSApplication delegate windowDidResize: method (to handle window resize events): %v", err)
- }
- err = addDelegateMethod(appdelegateclass, _buttonClicked,
- C.appDelegate_buttonClicked, delegate_void)
- if err != nil {
- return fmt.Errorf("error adding NSApplication delegate buttonClicked: method (to handle button clicks): %v", err)
+ return err
}
appDelegate = C.objc_msgSend_noargs(objc_getClass(_goAppDelegate), _new)
return nil
@@ -109,25 +99,6 @@ func appDelegate_buttonClicked(self C.id, sel C.SEL, button C.id) {
// this actually constructs the delegate class
var (
- // objc_getClass() says it returns an id but it's actually a Class
- // thanks to Psy| in irc.freenode.net/##objc
- // don't call object_getClass() on this then, as I originally thought — that returns the /metaclass/ (which we don't want, and in fact I wasn't even aware we COULD subclass the metaclass directly like this)
- _NSObject_Class = C.Class(unsafe.Pointer(_NSObject))
-)
-
-func makeDelegateClass(name string) (C.Class, error) {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
-
- c := C.objc_allocateClassPair(_NSObject_Class, cname, 0)
- if c == C.NilClass {
- return C.NilClass, fmt.Errorf("unable to create Objective-C class %s for NSApplication delegate; reason unknown", name)
- }
- C.objc_registerClassPair(c)
- return c, nil
-}
-
-var (
delegate_void = []C.char{'v', '@', ':', '@', 0} // void (*)(id, SEL, id)
delegate_bool = []C.char{'c', '@', ':', '@', 0} // BOOL (*)(id, SEL, id)
)
diff --git a/objc_darwin.go b/objc_darwin.go
index f8d7771..90afd74 100644
--- a/objc_darwin.go
+++ b/objc_darwin.go
@@ -3,6 +3,7 @@
package ui
import (
+ "fmt"
"unsafe"
)
@@ -50,3 +51,46 @@ func fromNSString(str C.id) string {
cstr := C.objc_msgSend_noargs(str, _UTF8String)
return C.GoString((*C.char)(unsafe.Pointer(cstr)))
}
+
+// These create new classes.
+
+// selector contains the information for a new selector.
+type selector struct {
+ name string
+ imp uintptr // not unsafe.Pointer because https://code.google.com/p/go/issues/detail?id=7665
+ itype itype
+ desc string // for error reporting
+}
+
+type itype uint
+const (
+ sel_void_id itype = iota
+ sel_bool_id
+ nitypes
+)
+
+var itypes = [nitypes][]C.char{
+ sel_void_id: []C.char{'v', '@', ':', '@', 0},
+ sel_bool_id: []C.char{'c', '@', ':', '@', 0},
+}
+
+func makeClass(name string, super C.id, sels []selector, desc string) (err error) {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ // an id that describes a class is itself a Class
+ // thanks to Psy| in irc.freenode.net/##objc
+ c := C.objc_allocateClassPair(C.Class(unsafe.Pointer(super)), cname, 0)
+ if c == C.NilClass {
+ return fmt.Errorf("unable to create Objective-C class %s for %s; reason unknown", name, desc)
+ }
+ C.objc_registerClassPair(c)
+ for _, v := range sels {
+ ok := C.class_addMethod(c, sel_getUid(v.name),
+ C.IMP(unsafe.Pointer(v.imp)), &itypes[v.itype][0])
+ if ok == C.BOOL(C.NO) {
+ return fmt.Errorf("unable to add selector %s to class %s (needed for %s; reason unknown)", v.name, name, v.desc)
+ }
+ }
+ return nil
+}