go-gtk
go-gtk copied to clipboard
gtk: CreateTag not working for numeric values
The function g_value_transform
doesn't seem to work for numeric values. This effects the function *TextBuffer.CreateTag
in gtk
.
I fixed this for integer values not equal to zero like this. In gtk/gtk.go
:
func (v *TextBuffer) CreateTag(tag_name string, props map[string]string) *TextTag {
ptr := C.CString(tag_name)
defer cfree(ptr)
tag := C._gtk_text_buffer_create_tag(v.GTextBuffer, gstring(ptr))
for prop, val := range props {
pprop := C.CString(prop)
pval := C.CString(val)
- C._apply_property(unsafe.Pointer(tag), gstring(pprop), gstring(pval))
+ intval, err := strconv.Atoi(val)
+ if err != nil {
+ intval = 0
+ }
+ C._apply_property(unsafe.Pointer(tag), gstring(pprop), gstring(pval), gint(intval))
cfree(pprop)
cfree(pval)
}
return newTextTag(tag)
}
And in gtk/gtk.go.h
:
-static void _apply_property(void* obj, const gchar* prop, const gchar* val) {
+static void _apply_property(void* obj, const gchar* prop, const gchar* val, const gint intval) {
GParamSpec *pspec;
GValue fromvalue = { 0, };
GValue tovalue = { 0, };
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), prop);
if (!pspec) return;
g_value_init(&fromvalue, G_TYPE_STRING);
g_value_set_string(&fromvalue, val);
+ if (intval) {
+ g_value_init(&tovalue, G_TYPE_INT);
+ g_value_set_int(&tovalue, intval);
+ } else {
g_value_init(&tovalue, G_PARAM_SPEC_VALUE_TYPE(pspec));
g_value_transform(&fromvalue, &tovalue);
+ }
g_object_set_property((GObject *)obj, prop, &tovalue);
g_value_unset(&fromvalue);
g_value_unset(&tovalue);
}
Of course, this is not a real solution. It just demonstrates that where integer values were not working in CreateTag
, now they are. So there is a problem with g_value_transform
.
Hmm, This is my bug. So how about to change type of argument to interface{}
. And handle the props as map using reflect?
That would make more sense. How many type distinctions are there for text properties? Here is my implementation differentiating between boolean, int, float, and string:
In gtk/gtk.go
:
func (v *TextBuffer) CreateTag(tag_name string, props map[string]interface{}) *TextTag {
toInt := func(val interface{}) int {
switch v := val.(type) {
case uint:
return int(v)
case uintptr:
return int(v)
case uint8:
return int(v)
case uint16:
return int(v)
case uint32:
return int(v)
case uint64:
return int(v)
case int:
return int(v)
case int8:
return int(v)
case int16:
return int(v)
case int32:
return int(v)
case int64:
return int(v)
}
return 0
}
toFloat := func(val interface{}) float64 {
switch v := val.(type) {
case float32:
return float64(v)
case float64:
return float64(v)
}
return 0
}
ptr := C.CString(tag_name)
defer cfree(ptr)
tag := C._gtk_text_buffer_create_tag(v.GTextBuffer, gstring(ptr))
for prop, val := range props {
pprop := C.CString(prop)
switch v := val.(type) {
case bool:
C._apply_property_bool(unsafe.Pointer(tag), gstring(pprop), gbool(v))
case uint, uintptr, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64:
C._apply_property_int(unsafe.Pointer(tag), gstring(pprop), gint(toInt(v)))
case float32, float64:
C._apply_property_float(unsafe.Pointer(tag), gstring(pprop), gdouble(toFloat(v)))
case string:
pval := C.CString(v)
C._apply_property_string(unsafe.Pointer(tag), gstring(pprop), gstring(pval))
cfree(pval)
}
cfree(pprop)
}
return newTextTag(tag)
}
In gtk/gtk.go.h
:
static void _apply_property_bool(void* obj, const gchar* prop, const gboolean val) {
GValue value = { 0, };
g_value_init(&value, G_TYPE_BOOLEAN);
g_value_set_boolean(&value, val);
g_object_set_property((GObject *)obj, prop, &value);
g_value_unset(&value);
}
static void _apply_property_int(void* obj, const gchar* prop, const gint val) {
GValue value = { 0, };
g_value_init(&value, G_TYPE_INT);
g_value_set_int(&value, val);
g_object_set_property((GObject *)obj, prop, &value);
g_value_unset(&value);
}
static void _apply_property_float(void* obj, const gchar* prop, const gdouble val) {
GValue value = { 0, };
g_value_init(&value, G_TYPE_DOUBLE);
g_value_set_double(&value, val);
g_object_set_property((GObject *)obj, prop, &value);
g_value_unset(&value);
}
static void _apply_property_string(void* obj, const gchar* prop, const gchar* val) {
GValue value = { 0, };
g_value_init(&value, G_TYPE_STRING);
g_value_set_string(&value, val);
g_object_set_property((GObject *)obj, prop, &value);
g_value_unset(&value);
}
Thanks. Could you please send me PR?
My current top also includes implementations for these functions:
gtk_container_child_get
gtk_calendar_new
gtk_calendar_get_date
Is it OK to make a single PR with all these changes?
Okay, I don't mind.
I submitted the PR.