ui/gtk/list.c

changeset 749
0f052f6f532c
parent 745
a4ee36ff7147
child 772
fa8afa19b8b6
equal deleted inserted replaced
748:6c1fc70cd1c8 749:0f052f6f532c
189 pango_attr_list_insert(attr, pango_attr_foreground_new(r, g, b)); 189 pango_attr_list_insert(attr, pango_attr_foreground_new(r, g, b));
190 190
191 return attr; 191 return attr;
192 } 192 }
193 193
194 static void column_factory_bind(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) { 194 static void column_factory_bind(GtkListItemFactory *unused, GtkListItem *item, gpointer userdata) {
195 UiColData *col = userdata; 195 UiColData *col = userdata;
196 UiList *list = col->listview->var ? col->listview->var->value : NULL; 196 UiList *list = col->listview->var ? col->listview->var->value : NULL;
197 UiListView *listview = col->listview; 197 UiListView *listview = col->listview;
198 198
199 ObjWrapper *obj = gtk_list_item_get_item(item); 199 ObjWrapper *obj = gtk_list_item_get_item(item);
200 UiModel *model = col->listview->model; 200 UiModel *model = col->listview->model;
201 UiModelType type = model->types[col->model_column]; 201 UiModelType type = model->types[col->model_column];
202
203 // cache the GtkListItem
204 CxHashKey row_key = cx_hash_key(&obj->i, sizeof(int));
205 UiRowItems *row = cxMapGet(listview->bound_rows, row_key);
206 if(row) {
207 if(row->items[col->model_column] == NULL) {
208 row->bound++;
209 }
210 } else {
211 row = calloc(1, sizeof(UiRowItems) + listview->numcolumns * sizeof(GtkListItem*));
212 cxMapPut(listview->bound_rows, row_key, row);
213 row->bound = 1;
214 }
215 row->items[col->model_column] = item;
202 216
203 UiBool freevalue = FALSE; 217 UiBool freevalue = FALSE;
204 void *data = listview->getvalue(list, obj->data, obj->i, col->data_column, listview->getvaluedata, &freevalue); 218 void *data = listview->getvalue(list, obj->data, obj->i, col->data_column, listview->getvaluedata, &freevalue);
205 GtkWidget *child = gtk_list_item_get_child(item); 219 GtkWidget *child = gtk_list_item_get_child(item);
206 220
287 if(attributes != listview->current_row_attributes) { 301 if(attributes != listview->current_row_attributes) {
288 pango_attr_list_unref(attributes); 302 pango_attr_list_unref(attributes);
289 } 303 }
290 } 304 }
291 305
306 static void column_factory_unbind(GtkSignalListItemFactory *self, GtkListItem *item, UiColData *col) {
307 ObjWrapper *obj = gtk_list_item_get_item(item);
308 UiListView *listview = col->listview;
309 CxHashKey row_key = cx_hash_key(&obj->i, sizeof(int));
310 UiRowItems *row = cxMapGet(listview->bound_rows, row_key);
311 if(row) {
312 row->items[col->model_column] = NULL;
313 row->bound--;
314 if(row->bound == 0) {
315 cxMapRemove(listview->bound_rows, row_key);
316 }
317 } // else: should not happen
318 }
319
320
292 static GtkSelectionModel* create_selection_model(UiListView *listview, GListStore *liststore, bool multiselection) { 321 static GtkSelectionModel* create_selection_model(UiListView *listview, GListStore *liststore, bool multiselection) {
293 GtkSelectionModel *selection_model; 322 GtkSelectionModel *selection_model;
294 if(multiselection) { 323 if(multiselection) {
295 selection_model = GTK_SELECTION_MODEL(gtk_multi_selection_new(G_LIST_MODEL(liststore))); 324 selection_model = GTK_SELECTION_MODEL(gtk_multi_selection_new(G_LIST_MODEL(liststore)));
296 } else { 325 } else {
314 UiListView *listview = create_listview(obj, args); 343 UiListView *listview = create_listview(obj, args);
315 if(!args->getvalue && !args->getvalue2) { 344 if(!args->getvalue && !args->getvalue2) {
316 listview->getvalue = str_getvalue; 345 listview->getvalue = str_getvalue;
317 } 346 }
318 347
348 listview->numcolumns = 1;
319 listview->columns = malloc(sizeof(UiColData)); 349 listview->columns = malloc(sizeof(UiColData));
320 listview->columns->listview = listview; 350 listview->columns->listview = listview;
321 listview->columns->data_column = 0; 351 listview->columns->data_column = 0;
322 listview->columns->model_column = 0; 352 listview->columns->model_column = 0;
353
354 listview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128);
355 listview->bound_rows->collection.simple_destructor = (cx_destructor_func)free;
323 356
324 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); 357 GtkListItemFactory *factory = gtk_signal_list_item_factory_new();
325 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns); 358 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns);
326 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns); 359 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns);
327 360
400 433
401 if(!args->getvalue && !args->getvalue2) { 434 if(!args->getvalue && !args->getvalue2) {
402 listview->getvalue = str_getvalue; 435 listview->getvalue = str_getvalue;
403 } 436 }
404 437
438 listview->numcolumns = 1;
405 listview->columns = malloc(sizeof(UiColData)); 439 listview->columns = malloc(sizeof(UiColData));
406 listview->columns->listview = listview; 440 listview->columns->listview = listview;
407 listview->columns->data_column = 0; 441 listview->columns->data_column = 0;
408 listview->columns->model_column = 0; 442 listview->columns->model_column = 0;
443
444 listview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128);
445 listview->bound_rows->collection.simple_destructor = (cx_destructor_func)free;
409 446
410 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); 447 GtkListItemFactory *factory = gtk_signal_list_item_factory_new();
411 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns); 448 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns);
412 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns); 449 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns);
413 450
493 // create columns from UiModel 530 // create columns from UiModel
494 UiModel *model = args->model; 531 UiModel *model = args->model;
495 int columns = model ? model->columns : 0; 532 int columns = model ? model->columns : 0;
496 533
497 tableview->columns = calloc(columns, sizeof(UiColData)); 534 tableview->columns = calloc(columns, sizeof(UiColData));
535 tableview->numcolumns = columns;
536
537 tableview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128);
538 tableview->bound_rows->collection.simple_destructor = (cx_destructor_func)free;
498 539
499 int addi = 0; 540 int addi = 0;
500 for(int i=0;i<columns;i++) { 541 for(int i=0;i<columns;i++) {
501 tableview->columns[i].listview = tableview; 542 tableview->columns[i].listview = tableview;
502 tableview->columns[i].model_column = i; 543 tableview->columns[i].model_column = i;
692 if(i < 0) { 733 if(i < 0) {
693 ui_update_liststore(view->liststore, list); 734 ui_update_liststore(view->liststore, list);
694 } else { 735 } else {
695 void *value = list->get(list, i); 736 void *value = list->get(list, i);
696 if(value) { 737 if(value) {
697 ObjWrapper *obj = obj_wrapper_new(value, i); 738 ObjWrapper *obj = g_list_model_get_item(G_LIST_MODEL(view->liststore), i);
698 UiListSelection sel = list->getselection(list); 739 if(obj) {
699 // TODO: if index i is selected, the selection is lost 740 obj->data = value;
700 // is it possible to update the item without removing it? 741 }
701 // workaround: save selection and reapply it 742
702 int count = g_list_model_get_n_items(G_LIST_MODEL(view->liststore)); 743 CxHashKey row_key = cx_hash_key(&i, sizeof(int));
703 if(count <= i) { 744 UiRowItems *row = cxMapGet(view->bound_rows, row_key);
704 g_list_store_splice(view->liststore, i, 0, (void **)&obj, 1); 745 if(row) {
705 } else { 746 for(int c=0;c<view->numcolumns;c++) {
706 g_list_store_splice(view->liststore, i, 1, (void **)&obj, 1); 747 if(row->items[c] != NULL) {
707 } 748 column_factory_bind(NULL, row->items[c], &view->columns[c]);
708 if(sel.count > 0) { 749 }
709 list->setselection(list, sel); 750 }
710 } 751 }
711 ui_listselection_free(sel);
712 } 752 }
713 } 753 }
714 } 754 }
715 755
716 UiListSelection ui_listview_getselection2(UiList *list) { 756 UiListSelection ui_listview_getselection2(UiList *list) {
1868 } 1908 }
1869 #if GTK_CHECK_VERSION(4, 10, 0) 1909 #if GTK_CHECK_VERSION(4, 10, 0)
1870 free(v->columns); 1910 free(v->columns);
1871 pango_attr_list_unref(v->default_attributes); 1911 pango_attr_list_unref(v->default_attributes);
1872 pango_attr_list_unref(v->current_row_attributes); 1912 pango_attr_list_unref(v->current_row_attributes);
1913 cxMapFree(v->bound_rows);
1873 #endif 1914 #endif
1874 free(v->selection.rows); 1915 free(v->selection.rows);
1875 free(v); 1916 free(v);
1876 } 1917 }
1877 1918

mercurial