func finishNewTable(b *tablebase, ty reflect.Type) Table { id := C.newTable() t := &table{ scroller: newScroller(id, true), // border on Table tablebase: b, selected: newEvent(), } t.fpreferredSize = t.xpreferredSize // also sets the delegate C.tableMakeDataSource(t.id, unsafe.Pointer(t)) for i := 0; i < ty.NumField(); i++ { colname := ty.Field(i).Tag.Get("uicolumn") if colname == "" { colname = ty.Field(i).Name } cname := C.CString(colname) coltype := C.colTypeText editable := false switch { case ty.Field(i).Type == reflect.TypeOf((*image.RGBA)(nil)): coltype = C.colTypeImage case ty.Field(i).Type.Kind() == reflect.Bool: coltype = C.colTypeCheckbox editable = true } C.tableAppendColumn(t.id, C.intptr_t(i), cname, C.int(coltype), toBOOL(editable)) C.free(unsafe.Pointer(cname)) // free now (not deferred) to conserve memory } return t }
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 }
func finishNewTable(b *tablebase, ty reflect.Type) Table { t := &table{ _hwnd: C.newControl(C.xWC_LISTVIEW, C.LVS_REPORT|C.LVS_OWNERDATA|C.LVS_NOSORTHEADER|C.LVS_SHOWSELALWAYS|C.LVS_SINGLESEL|C.WS_HSCROLL|C.WS_VSCROLL|C.WS_TABSTOP, C.WS_EX_CLIENTEDGE), // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog) tablebase: b, hotrow: -1, hotcol: -1, pushedrow: -1, pushedcol: -1, selected: newEvent(), } C.setTableSubclass(t._hwnd, unsafe.Pointer(t)) // LVS_EX_FULLROWSELECT gives us selection across the whole row, not just the leftmost column; this makes the list view work like on other platforms // LVS_EX_SUBITEMIMAGES gives us images in subitems, which will be important when both images and checkboxes are added C.tableAddExtendedStyles(t._hwnd, C.LVS_EX_FULLROWSELECT|C.LVS_EX_SUBITEMIMAGES) // this must come after the subclass because it uses one of our private messages C.SendMessageW(t._hwnd, C.msgTableMakeInitialCheckboxImageList, 0, 0) for i := 0; i < ty.NumField(); i++ { C.tableAppendColumn(t._hwnd, C.int(i), toUTF16(ty.Field(i).Name)) } t.colcount = C.int(ty.NumField()) return t }