mirror of
https://github.com/ziutek/glib.git
synced 2025-09-26 19:31:14 +08:00
Improved signals handling
This commit is contained in:
12
glib_test.go
12
glib_test.go
@@ -42,31 +42,31 @@ func TestSignal(t *testing.T) {
|
|||||||
// Connect a.handler(*Object, int) to the signal.
|
// Connect a.handler(*Object, int) to the signal.
|
||||||
// o will be passed as its first argument. Second argument of type int will
|
// o will be passed as its first argument. Second argument of type int will
|
||||||
// be passed from second argument passed to the Emit function.
|
// be passed from second argument passed to the Emit function.
|
||||||
o.ConnectSid(s, (*A).handler, &a)
|
o.ConnectSid(s, 0, (*A).handler, &a)
|
||||||
|
|
||||||
// Connect a.noiHandler(int) to the signal.
|
// Connect a.noiHandler(int) to the signal.
|
||||||
// o will not be passed to the method. An argument of type int will be
|
// o will not be passed to the method. An argument of type int will be
|
||||||
// passed from second argument passed to the Emit function.
|
// passed from second argument passed to the Emit function.
|
||||||
o.ConnectSidNoi(s, (*A).noiHandler, &a)
|
o.ConnectSidNoi(s, 0, (*A).noiHandler, &a)
|
||||||
|
|
||||||
// Connect funcHandler(*Object, int)to the signal.
|
// Connect funcHandler(*Object, int)to the signal.
|
||||||
// o will be passed as its first argument. Second argument of type int
|
// o will be passed as its first argument. Second argument of type int
|
||||||
// will be passed from second argument passed to the Emit function.
|
// will be passed from second argument passed to the Emit function.
|
||||||
o.ConnectSid(s, funcHandler, nil)
|
o.ConnectSid(s, 0, funcHandler, nil)
|
||||||
|
|
||||||
// Connect funcNoiHandler(int) to the signal.
|
// Connect funcNoiHandler(int) to the signal.
|
||||||
// o will not be passed to the function. An argument of type int will be
|
// o will not be passed to the function. An argument of type int will be
|
||||||
// passed from second argument passed to the Emit function.
|
// passed from second argument passed to the Emit function.
|
||||||
o.ConnectSidNoi(s, funcNoiHandler, nil)
|
o.ConnectSidNoi(s, 0, funcNoiHandler, nil)
|
||||||
|
|
||||||
// Connect funcHandlerParam0(A, *Object, int) to the signal.
|
// Connect funcHandlerParam0(A, *Object, int) to the signal.
|
||||||
// &a will be passed as its first argument, o will be passed as its second
|
// &a will be passed as its first argument, o will be passed as its second
|
||||||
// argument. The thrid argument of type int will be from second argument
|
// argument. The thrid argument of type int will be from second argument
|
||||||
// passed to the Emit function.
|
// passed to the Emit function.
|
||||||
o.ConnectSid(s, funcHandlerParam0, &a)
|
o.ConnectSid(s, 0, funcHandlerParam0, &a)
|
||||||
|
|
||||||
// Emit signal with 123 integer as argument.
|
// Emit signal with 123 integer as argument.
|
||||||
o.EmitById(s, 123)
|
o.EmitById(s, 0, 123)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Like TestSignal but uses signal names
|
// Like TestSignal but uses signal names
|
||||||
|
55
object.go
55
object.go
@@ -81,24 +81,20 @@ GoClosure* _object_closure_new(gboolean no_inst, gpointer p0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
gulong _signal_connect(GObject* inst, guint sig, GoClosure* cl) {
|
gulong _signal_connect(GObject* inst, guint id, GQuark detail, GoClosure* cl) {
|
||||||
return g_signal_connect_closure_by_id(
|
return g_signal_connect_closure_by_id(
|
||||||
inst,
|
inst,
|
||||||
sig,
|
id,
|
||||||
0,
|
detail,
|
||||||
(GClosure*) cl,
|
(GClosure*) cl,
|
||||||
TRUE
|
TRUE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void _signal_emit(const GValue *inst_and_params, guint sig, GValue *ret) {
|
void _signal_emit(const GValue *inst_and_params, guint id, GQuark detail,
|
||||||
return g_signal_emitv(
|
GValue *ret) {
|
||||||
inst_and_params,
|
return g_signal_emitv( inst_and_params, id, detail, ret);
|
||||||
sig,
|
|
||||||
0,
|
|
||||||
ret
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
@@ -174,9 +170,9 @@ func (o *Object) GetProperty(name string) interface{} {
|
|||||||
return v.Get()
|
return v.Get()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Object) EmitById(sig SignalId, args ...interface{}) interface{} {
|
func (o *Object) EmitById(sid SignalId, detail Quark, args ...interface{}) interface{} {
|
||||||
var sq C.GSignalQuery
|
var sq C.GSignalQuery
|
||||||
C.g_signal_query(C.guint(sig), &sq)
|
C.g_signal_query(C.guint(sid), &sq)
|
||||||
if len(args) != int(sq.n_params) {
|
if len(args) != int(sq.n_params) {
|
||||||
panic(fmt.Sprintf(
|
panic(fmt.Sprintf(
|
||||||
"*Object.EmitById "+
|
"*Object.EmitById "+
|
||||||
@@ -190,12 +186,13 @@ func (o *Object) EmitById(sig SignalId, args ...interface{}) interface{} {
|
|||||||
prms[i+1] = *ValueOf(a)
|
prms[i+1] = *ValueOf(a)
|
||||||
}
|
}
|
||||||
ret := new(Value)
|
ret := new(Value)
|
||||||
C._signal_emit(prms[0].g(), C.guint(sig), ret.g())
|
C._signal_emit(prms[0].g(), C.guint(sid), C.GQuark(detail), ret.g())
|
||||||
return ret.Get()
|
return ret.Get()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Object) Emit(sig_name string, args ...interface{}) interface{} {
|
func (o *Object) Emit(sig_name string, args ...interface{}) interface{} {
|
||||||
return o.EmitById(SignalLookup(sig_name, o.Type()), args...)
|
sid, detail := SignalLookup(sig_name, o.Type())
|
||||||
|
return o.EmitById(sid, detail, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SigHandlerId C.gulong
|
type SigHandlerId C.gulong
|
||||||
@@ -206,16 +203,18 @@ type sigHandler struct {
|
|||||||
|
|
||||||
var obj_handlers = make(map[uintptr]map[SigHandlerId]*sigHandler)
|
var obj_handlers = make(map[uintptr]map[SigHandlerId]*sigHandler)
|
||||||
|
|
||||||
func (o *Object) connect(noi bool, sig SignalId, cb_func, param0 interface{}) {
|
func (o *Object) connect(noi bool, sid SignalId, detail Quark, cb_func,
|
||||||
|
param0 interface{}) {
|
||||||
cb := reflect.ValueOf(cb_func)
|
cb := reflect.ValueOf(cb_func)
|
||||||
if cb.Kind() != reflect.Func {
|
if cb.Kind() != reflect.Func {
|
||||||
panic("cb_func isn't a function")
|
panic("cb_func isn't a function")
|
||||||
}
|
}
|
||||||
// Check that function parameters and return value match to signal
|
// Check that function parameters and return value match to signal
|
||||||
var sq C.GSignalQuery
|
var sq C.GSignalQuery
|
||||||
C.g_signal_query(C.guint(sig), &sq)
|
|
||||||
|
C.g_signal_query(C.guint(sid), &sq)
|
||||||
ft := cb.Type()
|
ft := cb.Type()
|
||||||
if ft.NumOut() > 1 || ft.NumOut() == 1 && Type(sq.return_type)== TYPE_NONE {
|
if ft.NumOut() > 1 || ft.NumOut() == 1 && Type(sq.return_type) == TYPE_NONE {
|
||||||
panic("Number of function return values doesn't match signal spec.")
|
panic("Number of function return values doesn't match signal spec.")
|
||||||
}
|
}
|
||||||
poffset := 2
|
poffset := 2
|
||||||
@@ -238,12 +237,12 @@ func (o *Object) connect(noi bool, sig SignalId, cb_func, param0 interface{}) {
|
|||||||
panic("Type of function return value doesn't match signal spec.")
|
panic("Type of function return value doesn't match signal spec.")
|
||||||
}
|
}
|
||||||
if n_params > 0 {
|
if n_params > 0 {
|
||||||
pt := (*[1<<16]Type)(unsafe.Pointer(sq.param_types))[:int(sq.n_params)]
|
pt := (*[1 << 16]Type)(unsafe.Pointer(sq.param_types))[:int(sq.n_params)]
|
||||||
for i := 0; i < n_params; i++ {
|
for i := 0; i < n_params; i++ {
|
||||||
if !pt[i].Match(ft.In(i + poffset)) {
|
if !pt[i].Match(ft.In(i + poffset)) {
|
||||||
panic(fmt.Sprintf(
|
panic(fmt.Sprintf(
|
||||||
"Callback #%d param. type %s doesn't match signal spec %s",
|
"Callback #%d param. type %s doesn't match signal spec %s",
|
||||||
i+1, ft.In(i + poffset), pt[i],
|
i+1, ft.In(i+poffset), pt[i],
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,7 +265,7 @@ func (o *Object) connect(noi bool, sig SignalId, cb_func, param0 interface{}) {
|
|||||||
default:
|
default:
|
||||||
panic("Callback parameter #0 isn't a pointer nor nil")
|
panic("Callback parameter #0 isn't a pointer nor nil")
|
||||||
}
|
}
|
||||||
gocl.h_id = C._signal_connect(o.g(), C.guint(sig), gocl)
|
gocl.h_id = C._signal_connect(o.g(), C.guint(sid), C.GQuark(detail), gocl)
|
||||||
oh := obj_handlers[uintptr(o.p)]
|
oh := obj_handlers[uintptr(o.p)]
|
||||||
if oh == nil {
|
if oh == nil {
|
||||||
oh = make(map[SigHandlerId]*sigHandler)
|
oh = make(map[SigHandlerId]*sigHandler)
|
||||||
@@ -276,25 +275,29 @@ func (o *Object) connect(noi bool, sig SignalId, cb_func, param0 interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connect callback to signal specified by id
|
// Connect callback to signal specified by id
|
||||||
func (o *Object) ConnectSid(sig SignalId, cb_func, param0 interface{}) {
|
func (o *Object) ConnectSid(sid SignalId, detail Quark,
|
||||||
o.connect(false, sig, cb_func, param0)
|
cb_func, param0 interface{}) {
|
||||||
|
o.connect(false, sid, detail, cb_func, param0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect callback to signal specified by id.
|
// Connect callback to signal specified by id.
|
||||||
// Doesn't pass o as first parameter to callback.
|
// Doesn't pass o as first parameter to callback.
|
||||||
func (o *Object) ConnectSidNoi(sig SignalId, cb_func, param0 interface{}) {
|
func (o *Object) ConnectSidNoi(sid SignalId, detail Quark,
|
||||||
o.connect(true, sig, cb_func, param0)
|
cb_func, param0 interface{}) {
|
||||||
|
o.connect(true, sid, detail, cb_func, param0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect callback to signal specified by name.
|
// Connect callback to signal specified by name.
|
||||||
func (o *Object) Connect(sig_name string, cb_func, param0 interface{}) {
|
func (o *Object) Connect(sig_name string, cb_func, param0 interface{}) {
|
||||||
o.ConnectSid(SignalLookup(sig_name, o.Type()), cb_func, param0)
|
sid, detail := SignalLookup(sig_name, o.Type())
|
||||||
|
o.connect(false, sid, detail, cb_func, param0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect callback to signal specified by name.
|
// Connect callback to signal specified by name.
|
||||||
// Doesn't pass o as first parameter to callback.
|
// Doesn't pass o as first parameter to callback.
|
||||||
func (o *Object) ConnectNoi(sig_name string, cb_func, param0 interface{}) {
|
func (o *Object) ConnectNoi(sig_name string, cb_func, param0 interface{}) {
|
||||||
o.ConnectSidNoi(SignalLookup(sig_name, o.Type()), cb_func, param0)
|
sid, detail := SignalLookup(sig_name, o.Type())
|
||||||
|
o.connect(true, sid, detail, cb_func, param0)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Params map[string]interface{}
|
type Params map[string]interface{}
|
||||||
|
12
signal.go
12
signal.go
@@ -8,6 +8,7 @@ import "C"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SignalFlags C.GSignalFlags
|
type SignalFlags C.GSignalFlags
|
||||||
@@ -49,8 +50,13 @@ func (s SignalId) String() string {
|
|||||||
return C.GoString((*C.char)(C.g_signal_name(C.guint(s))))
|
return C.GoString((*C.char)(C.g_signal_name(C.guint(s))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func SignalLookup(n string, t Type) SignalId {
|
func SignalLookup(name string, t Type) (sid SignalId, detail Quark) {
|
||||||
s := C.CString(n)
|
st := strings.SplitN(name, "::", 2)
|
||||||
|
if len(st) == 2 {
|
||||||
|
detail = QuarkFromString(st[1])
|
||||||
|
}
|
||||||
|
s := C.CString(st[0])
|
||||||
|
sid = SignalId(C.g_signal_lookup((*C.gchar)(s), t.g()))
|
||||||
defer C.free(unsafe.Pointer(s))
|
defer C.free(unsafe.Pointer(s))
|
||||||
return SignalId(C.g_signal_lookup((*C.gchar)(s), t.g()))
|
return
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user