Merge 27664db5e4
into fea45b2d5b
This commit is contained in:
commit
bcb58c2e7f
29
ui.h
29
ui.h
|
@ -1383,6 +1383,9 @@ struct uiTableParams {
|
|||
// If CellValue() for this column for any row returns NULL, that
|
||||
// row will also use the default background color.
|
||||
int RowBackgroundColorModelColumn;
|
||||
// MultiSelect sets selection mode for the table.
|
||||
// 0=single selection, 1=allow multiple rows to be selected
|
||||
int MultiSelect;
|
||||
};
|
||||
|
||||
// uiTable is a uiControl that shows tabular data, allowing users to
|
||||
|
@ -1455,6 +1458,32 @@ _UI_EXTERN void uiTableAppendButtonColumn(uiTable *t,
|
|||
int buttonModelColumn,
|
||||
int buttonClickableModelColumn);
|
||||
|
||||
// uiTableOnSelectionChanged sets a callback to invoke upon changes
|
||||
// in the set of selected items in the table.
|
||||
_UI_EXTERN void uiTableOnSelectionChanged(uiTable *t, void (*f)(uiTable *t, void *data), void *data);
|
||||
|
||||
// uiTableSelection holds an array of row indexes for a table.
|
||||
// it's safe to fiddle with the Items data in place (eg a caller
|
||||
// might want to sort them - that's ok). But probably best not to
|
||||
// change NumItems or try to reallocate Items.
|
||||
typedef struct uiTableSelection uiTableSelection;
|
||||
struct uiTableSelection
|
||||
{
|
||||
int NumItems;
|
||||
int* Items;
|
||||
};
|
||||
|
||||
// uiTableCurrentSelection returns a uiTableSelection containing
|
||||
// an array of all the selected rows in the table.
|
||||
// If no rows are selected, a uiTableSelection will still be
|
||||
// returned, with NumItems set to 0.
|
||||
// The caller is responsible for calling uiFreeTableSelection()
|
||||
// when finished with the uiTableSelection.
|
||||
_UI_EXTERN uiTableSelection* uiTableCurrentSelection(uiTable* t);
|
||||
|
||||
// uiFreeTableSelection frees any memory allocated to a uiTableSelection
|
||||
_UI_EXTERN void uiFreeTableSelection(uiTableSelection* sel);
|
||||
|
||||
// uiNewTable() creates a new uiTable with the specified parameters.
|
||||
_UI_EXTERN uiTable *uiNewTable(uiTableParams *params);
|
||||
|
||||
|
|
83
unix/table.c
83
unix/table.c
|
@ -18,6 +18,8 @@ struct uiTable {
|
|||
// TODO document this properly
|
||||
GHashTable *indeterminatePositions;
|
||||
guint indeterminateTimer;
|
||||
void (*onSelectionChanged)(uiTable *, void *);
|
||||
void *onSelectionChangedData;
|
||||
};
|
||||
|
||||
// use the same size as GtkFileChooserWidget's treeview
|
||||
|
@ -494,9 +496,82 @@ static void uiTableDestroy(uiControl *c)
|
|||
uiFreeControl(uiControl(t));
|
||||
}
|
||||
|
||||
static void onChanged(GtkTreeSelection *sel, gpointer data)
|
||||
{
|
||||
uiTable* t = uiTable(data);
|
||||
(*(t->onSelectionChanged))(t, t->onSelectionChangedData);
|
||||
}
|
||||
|
||||
static void defaultOnSelectionChanged(uiTable *t, void *data)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void uiTableOnSelectionChanged(uiTable *t, void (*f)(uiTable *, void *), void *data)
|
||||
{
|
||||
t->onSelectionChanged = f;
|
||||
t->onSelectionChangedData = data;
|
||||
}
|
||||
|
||||
// internal implementation of uiTableSelection (growable, because we
|
||||
// don't know the size of the selection in advance under Gtk+)
|
||||
// So we have extra stuff hanging on to the end of the public
|
||||
// uiTableSelection we return, but callers don't have to care.
|
||||
// Yay C!
|
||||
struct growableTableSelection
|
||||
{
|
||||
uiTableSelection sel;
|
||||
int cap;
|
||||
// TODO: could have an int here for single-selection case to avoid extra alloc...
|
||||
};
|
||||
|
||||
static void collectSelection( GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
struct growableTableSelection* it = (struct growableTableSelection*)data;
|
||||
int depth = gtk_tree_path_get_depth(path);
|
||||
gint* indices = gtk_tree_path_get_indices(path);
|
||||
if (depth < 1)
|
||||
return;
|
||||
|
||||
// append to collection
|
||||
if (it->sel.NumItems == it->cap) {
|
||||
// initial alloc or grow
|
||||
if (it->cap == 0) {
|
||||
it->cap = 16;
|
||||
} else {
|
||||
it->cap *= 2;
|
||||
}
|
||||
it->sel.Items = uiprivRealloc(it->sel.Items, sizeof(int) * it->cap, "int[]");
|
||||
}
|
||||
it->sel.Items[it->sel.NumItems++] = (int)indices[0];
|
||||
}
|
||||
|
||||
uiTableSelection* uiTableCurrentSelection(uiTable* t)
|
||||
{
|
||||
struct growableTableSelection* g = uiprivAlloc(sizeof(struct growableTableSelection), "uiTableSelection");
|
||||
g->sel.NumItems = 0;
|
||||
g->sel.Items = NULL;
|
||||
g->cap = 0;
|
||||
gtk_tree_selection_selected_foreach( gtk_tree_view_get_selection(t->tv), collectSelection, (gpointer)g);
|
||||
return (uiTableSelection*)g;
|
||||
}
|
||||
|
||||
void uiFreeTableSelection(uiTableSelection* sel)
|
||||
{
|
||||
struct growableTableSelection* g = (struct growableTableSelection*)sel;
|
||||
if (g->sel.Items)
|
||||
uiprivFree(g->sel.Items);
|
||||
uiprivFree(g);
|
||||
}
|
||||
|
||||
uiTable *uiNewTable(uiTableParams *p)
|
||||
{
|
||||
uiTable *t;
|
||||
GtkTreeSelection* sel;
|
||||
GtkSelectionMode selMode;
|
||||
|
||||
uiUnixNewControl(uiTable, t);
|
||||
|
||||
|
@ -520,5 +595,13 @@ uiTable *uiNewTable(uiTableParams *p)
|
|||
t->indeterminatePositions = g_hash_table_new_full(rowcolHash, rowcolEqual,
|
||||
uiprivFree, uiprivFree);
|
||||
|
||||
sel = gtk_tree_view_get_selection(t->tv);
|
||||
selMode = GTK_SELECTION_SINGLE;
|
||||
if (p->MultiSelect == 1)
|
||||
selMode = GTK_SELECTION_MULTIPLE;
|
||||
gtk_tree_selection_set_mode(sel, selMode);
|
||||
g_signal_connect(sel, "changed", G_CALLBACK(onChanged), t);
|
||||
uiTableOnSelectionChanged(t, defaultOnSelectionChanged, NULL);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue