func finishNewTable(b *tablebase, ty reflect.Type) Table { widget := C.gtk_tree_view_new() t := &table{ scroller: newScroller(widget, true, true, false), // natively scrollable; has a border; no overlay tablebase: b, treeview: (*C.GtkTreeView)(unsafe.Pointer(widget)), crtocol: make(map[*C.GtkCellRendererToggle]int), selected: newEvent(), } model := C.newTableModel(unsafe.Pointer(t)) t.model = model t.modelgtk = (*C.GtkTreeModel)(unsafe.Pointer(model)) t.selection = C.gtk_tree_view_get_selection(t.treeview) g_signal_connect( C.gpointer(unsafe.Pointer(t.selection)), "changed", C.GCallback(C.tableSelectionChanged), C.gpointer(unsafe.Pointer(t))) C.gtk_tree_view_set_model(t.treeview, t.modelgtk) for i := 0; i < ty.NumField(); i++ { colname := ty.Field(i).Tag.Get("uicolumn") if colname == "" { colname = ty.Field(i).Name } cname := togstr(colname) switch { case ty.Field(i).Type == reflect.TypeOf((*image.RGBA)(nil)): // can't use GDK_TYPE_PIXBUF here because it's a macro that expands to a function and cgo hates that t.types = append(t.types, C.gdk_pixbuf_get_type()) C.tableAppendColumn(t.treeview, C.gint(i), cname, C.gtk_cell_renderer_pixbuf_new(), attribPixbuf) case ty.Field(i).Type.Kind() == reflect.Bool: t.types = append(t.types, C.G_TYPE_BOOLEAN) cr := C.gtk_cell_renderer_toggle_new() crt := (*C.GtkCellRendererToggle)(unsafe.Pointer(cr)) t.crtocol[crt] = i g_signal_connect(C.gpointer(unsafe.Pointer(cr)), "toggled", C.GCallback(C.goTableModel_toggled), C.gpointer(unsafe.Pointer(t))) C.tableAppendColumn(t.treeview, C.gint(i), cname, cr, attribActive) default: t.types = append(t.types, C.G_TYPE_STRING) C.tableAppendColumn(t.treeview, C.gint(i), cname, C.gtk_cell_renderer_text_new(), attribText) } freegstr(cname) // free now (not deferred) to conserve memory } // and for some GtkTreeModel boilerplate t.nColumns = C.gint(ty.NumField()) return t }
// TreeViewNew() is a wrapper around gtk_tree_view_new(). func TreeViewNew() (*TreeView, error) { return setupTreeView(unsafe.Pointer(C.gtk_tree_view_new())) }