| 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 |