Created a new, simpler, easier to work with, and consistent way to create the necessary Objective-C classes in our Go code, and converted the appDelegate class to use it. Now for goArea...
This commit is contained in:
parent
9488824240
commit
dd20d56f25
|
@ -33,36 +33,26 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_uitask = sel_getUid("uitask:")
|
_uitask = sel_getUid("uitask:") // used by uitask_darwin.go
|
||||||
_windowShouldClose = sel_getUid("windowShouldClose:")
|
_buttonClicked = sel_getUid("buttonClicked:") // used by sysdata_darwin.go
|
||||||
_windowDidResize = sel_getUid("windowDidResize:")
|
|
||||||
_buttonClicked = sel_getUid("buttonClicked:")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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 {
|
func mkAppDelegate() error {
|
||||||
appdelegateclass, err := makeDelegateClass(_goAppDelegate)
|
err := makeClass(_goAppDelegate, _NSObject, appDelegateSels,
|
||||||
|
"application delegate (handles events)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error creating NSApplication delegate: %v", err)
|
return 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)
|
|
||||||
}
|
}
|
||||||
appDelegate = C.objc_msgSend_noargs(objc_getClass(_goAppDelegate), _new)
|
appDelegate = C.objc_msgSend_noargs(objc_getClass(_goAppDelegate), _new)
|
||||||
return nil
|
return nil
|
||||||
|
@ -108,25 +98,6 @@ func appDelegate_buttonClicked(self C.id, sel C.SEL, button C.id) {
|
||||||
|
|
||||||
// this actually constructs the delegate class
|
// 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 (
|
var (
|
||||||
delegate_void = []C.char{'v', '@', ':', '@', 0} // void (*)(id, SEL, id)
|
delegate_void = []C.char{'v', '@', ':', '@', 0} // void (*)(id, SEL, id)
|
||||||
delegate_bool = []C.char{'c', '@', ':', '@', 0} // BOOL (*)(id, SEL, id)
|
delegate_bool = []C.char{'c', '@', ':', '@', 0} // BOOL (*)(id, SEL, id)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -50,3 +51,46 @@ func fromNSString(str C.id) string {
|
||||||
cstr := C.objc_msgSend_noargs(str, _UTF8String)
|
cstr := C.objc_msgSend_noargs(str, _UTF8String)
|
||||||
return C.GoString((*C.char)(unsafe.Pointer(cstr)))
|
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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue