Added GTK+ listboxes... sort of. This whole thing is so broken it's funny.

This commit is contained in:
Pietro Gagliardi 2014-02-16 23:50:54 -05:00
parent 919e89ca7e
commit 0856e953be
2 changed files with 161 additions and 12 deletions

View File

@ -13,6 +13,10 @@ import (
// #include <gtk/gtk.h>
// /* because cgo is flaky with macros */
// void gSignalConnect(GtkWidget *widget, char *signal, GCallback callback, void *data) { g_signal_connect(widget, signal, callback, data); }
// /* because cgo seems to choke on ... */
// void gtkTreeModelGet(GtkTreeModel *model, GtkTreeIter *iter, gchar **gs) { gtk_tree_model_get(model, iter, 0, gs, -1); }
// GtkListStore *gtkListStoreNew(void) { return gtk_list_store_new(1, G_TYPE_STRING); }
// void gtkListStoreSet(GtkListStore *ls, GtkTreeIter *iter, char *gs) { gtk_list_store_set(ls, iter, 0, (gchar *) gs, -1); }
import "C"
// BIG TODO reduce the amount of explicit casting
@ -200,3 +204,133 @@ func gtk_label_set_text(widget *gtkWidget, text string) {
func gtk_label_get_text(widget *gtkWidget) string {
return C.GoString((*C.char)(unsafe.Pointer(C.gtk_label_get_text((*C.GtkLabel)(unsafe.Pointer(widget))))))
}
func gListboxNew(multisel bool) *gtkWidget {
store := C.gtkListStoreNew()
widget := C.gtk_tree_view_new_with_model((*C.GtkTreeModel)(unsafe.Pointer(store)))
tv := (*C.GtkTreeView)(unsafe.Pointer(widget))
sel := C.GTK_SELECTION_SINGLE
if multisel {
sel = C.GTK_SELECTION_MULTIPLE
}
C.gtk_tree_selection_set_mode(C.gtk_tree_view_get_selection(tv), C.GtkSelectionMode(sel))
return (*gtkWidget)(unsafe.Pointer(widget))
}
func gListboxNewSingle() *gtkWidget {
return gListboxNew(false)
}
func gListboxNewMulti() *gtkWidget {
return gListboxNew(true)
}
func gListboxText(widget *gtkWidget) string {
var model *C.GtkTreeModel
var iter C.GtkTreeIter
var gs *C.gchar
tv := (*C.GtkTreeView)(unsafe.Pointer(widget))
sel := C.gtk_tree_view_get_selection(tv)
if !fromgbool(C.gtk_tree_selection_get_selected(sel, &model, &iter)) {
return ""
}
C.gtkTreeModelGet(model, &iter, &gs)
return C.GoString((*C.char)(unsafe.Pointer(gs)))
}
func gListboxAppend(widget *gtkWidget, what string) {
var iter C.GtkTreeIter
tv := (*C.GtkTreeView)(unsafe.Pointer(widget))
ls := (*C.GtkListStore)(unsafe.Pointer(C.gtk_tree_view_get_model(tv)))
C.gtk_list_store_append(ls, &iter)
cwhat := C.CString(what)
defer C.free(unsafe.Pointer(cwhat))
C.gtkListStoreSet(ls, &iter, cwhat)
}
func gListboxInsert(widget *gtkWidget, index int, what string) {
var iter C.GtkTreeIter
tv := (*C.GtkTreeView)(unsafe.Pointer(widget))
ls := (*C.GtkListStore)(unsafe.Pointer(C.gtk_tree_view_get_model(tv)))
C.gtk_list_store_insert(ls, &iter, C.gint(index))
cwhat := C.CString(what)
defer C.free(unsafe.Pointer(cwhat))
C.gtkListStoreSet(ls, &iter, cwhat)
}
func gListboxSelected(widget *gtkWidget) int {
var model *C.GtkTreeModel
var iter C.GtkTreeIter
tv := (*C.GtkTreeView)(unsafe.Pointer(widget))
sel := C.gtk_tree_view_get_selection(tv)
if !fromgbool(C.gtk_tree_selection_get_selected(sel, &model, &iter)) {
return -1
}
path := C.gtk_tree_model_get_path(model, &iter)
return int(*C.gtk_tree_path_get_indices(path))
}
func gListboxSelectedMulti(widget *gtkWidget) (indices []int) {
var model *C.GtkTreeModel
tv := (*C.GtkTreeView)(unsafe.Pointer(widget))
sel := C.gtk_tree_view_get_selection(tv)
rows := C.gtk_tree_selection_get_selected_rows(sel, &model)
defer C.g_list_free_full(rows, C.GDestroyNotify(unsafe.Pointer(C.gtk_tree_path_free)))
len := C.g_list_length(rows)
if len == 0 {
return nil
}
indices = make([]int, len)
for i := C.guint(0); i < len; i++ {
d := (*C.GtkTreeRowReference)(unsafe.Pointer(rows.data))
path := C.gtk_tree_row_reference_get_path(d)
indices[i] = int(*C.gtk_tree_path_get_indices(path))
rows = rows.next
}
return indices
}
func gListboxSelMultiTexts(widget *gtkWidget) (texts []string) {
var model *C.GtkTreeModel
var iter C.GtkTreeIter
var gs *C.gchar
tv := (*C.GtkTreeView)(unsafe.Pointer(widget))
sel := C.gtk_tree_view_get_selection(tv)
rows := C.gtk_tree_selection_get_selected_rows(sel, &model)
defer C.g_list_free_full(rows, C.GDestroyNotify(unsafe.Pointer(C.gtk_tree_path_free)))
len := C.g_list_length(rows)
if len == 0 {
return nil
}
texts = make([]string, len)
for i := C.guint(0); i < len; i++ {
d := (*C.GtkTreeRowReference)(unsafe.Pointer(rows.data))
path := C.gtk_tree_row_reference_get_path(d)
if !fromgbool(C.gtk_tree_model_get_iter(model, &iter, path)) {
// TODO
return
}
C.gtkTreeModelGet(model, &iter, &gs)
texts[i] = C.GoString((*C.char)(unsafe.Pointer(gs)))
rows = rows.next
}
return texts
}
func gListboxDelete(widget *gtkWidget, index int) {
var iter C.GtkTreeIter
tv := (*C.GtkTreeView)(unsafe.Pointer(widget))
ls := (*C.GtkListStore)(unsafe.Pointer(C.gtk_tree_view_get_model(tv)))
if !fromgbool(C.gtk_tree_model_iter_nth_child((*C.GtkTreeModel)(unsafe.Pointer(ls)), &iter, (*C.GtkTreeIter)(nil), C.gint(index))) { // no such index
// TODO
return
}
C.gtk_list_store_remove(ls, &iter)
}

View File

@ -23,7 +23,8 @@ type classData struct {
append func(widget *gtkWidget, text string)
insert func(widget *gtkWidget, index int, text string)
selected func(widget *gtkWidget) int
// ...
selMulti func(widget *gtkWidget) []int
smtexts func(widget *gtkWidget) []string
delete func(widget *gtkWidget, index int)
// ...
signals map[string]func(*sysData) func() bool
@ -98,6 +99,16 @@ var classTypes = [nctypes]*classData{
text: gtk_label_get_text,
},
c_listbox: &classData{
make: gListboxNewSingle,
makeAlt: gListboxNewMulti,
// TODO setText
text: gListboxText,
append: gListboxAppend,
insert: gListboxInsert,
selected: gListboxSelected,
selMulti: gListboxSelectedMulti,
smtexts: gListboxSelMultiTexts,
delete: gListboxDelete,
},
}
@ -173,7 +184,9 @@ func (s *sysData) hide() error {
}
func (s *sysData) setText(text string) error {
if classTypes[s.ctype] == nil || classTypes[s.ctype].setText == nil { return nil }
if classTypes[s.ctype].setText == nil { // does not have concept of text
return nil
}
ret := make(chan struct{})
defer close(ret)
uitask <- func() {
@ -185,7 +198,6 @@ if classTypes[s.ctype] == nil || classTypes[s.ctype].setText == nil { return nil
}
func (s *sysData) setRect(x int, y int, width int, height int) error {
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return nil }
ret := make(chan struct{})
defer close(ret)
uitask <- func() {
@ -207,7 +219,6 @@ func (s *sysData) isChecked() bool {
}
func (s *sysData) text() string {
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { println(s.ctype,"unsupported text()"); return "" }
ret := make(chan string)
defer close(ret)
uitask <- func() {
@ -217,7 +228,6 @@ if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { println(s.cty
}
func (s *sysData) append(what string) error {
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return nil }
ret := make(chan struct{})
defer close(ret)
uitask <- func() {
@ -229,7 +239,6 @@ if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return nil }
}
func (s *sysData) insertBefore(what string, before int) error {
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return nil }
ret := make(chan struct{})
defer close(ret)
uitask <- func() {
@ -241,7 +250,6 @@ if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return nil }
}
func (s *sysData) selectedIndex() int {
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return -1 }
ret := make(chan int)
defer close(ret)
uitask <- func() {
@ -251,13 +259,21 @@ if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return -1 }
}
func (s *sysData) selectedIndices() []int {
// TODO
return nil
ret := make(chan []int)
defer close(ret)
uitask <- func() {
ret <- classTypes[s.ctype].selMulti(s.widget)
}
return <-ret
}
func (s *sysData) selectedTexts() []string {
// TODO
return nil
ret := make(chan []string)
defer close(ret)
uitask <- func() {
ret <- classTypes[s.ctype].smtexts(s.widget)
}
return <-ret
}
func (s *sysData) setWindowSize(width int, height int) error {
@ -272,7 +288,6 @@ func (s *sysData) setWindowSize(width int, height int) error {
}
func (s *sysData) delete(index int) error {
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return nil }
ret := make(chan struct{})
defer close(ret)
uitask <- func() {