7 days ago
implement single row list updates (GTK)
application/main.c | file | annotate | diff | comparison | revisions | |
ui/common/types.c | file | annotate | diff | comparison | revisions | |
ui/gtk/list.c | file | annotate | diff | comparison | revisions |
--- a/application/main.c Tue Mar 18 17:47:40 2025 +0100 +++ b/application/main.c Sun Mar 23 18:09:24 2025 +0100 @@ -35,6 +35,7 @@ #include <cx/utils.h> #include "cx/string.h" +#include "cx/list.h" #if !defined(UI_COCOA) && !defined(UI_MOTIF) @@ -54,6 +55,7 @@ UiList *srclist2; UiList *items; UiGeneric *web; + UiString *list_input; } MyDocument; MyDocument *doc1; @@ -168,9 +170,9 @@ ui_list_append(doc->list, "test2"); ui_list_append(doc->list, "test3"); doc->list2 = ui_list_new(docctx, "list2"); - ui_list_append(doc->list2, "test1"); - ui_list_append(doc->list2, "test2"); - ui_list_append(doc->list2, "test3"); + ui_list_append(doc->list2, strdup("test1")); + ui_list_append(doc->list2, strdup("test2")); + ui_list_append(doc->list2, strdup("test3")); doc->radio = ui_int_new(docctx, "radio"); doc->tabview = ui_int_new(docctx, "tabview"); doc->image = ui_generic_new(docctx, "image"); @@ -190,6 +192,8 @@ doc->web = ui_generic_new(docctx, NULL); + doc->list_input = ui_string_new(docctx, "list_input"); + //doc->text = ui_text_new(docctx, "text"); return doc; } @@ -348,6 +352,17 @@ printf("dropdown[%d]: %s\n", event->intval, event->eventdata); } +static void action_update_list(UiEvent *event, void *userdata) { + MyDocument *doc = event->document; + + char *newvalue = ui_get(doc->list_input); + CxList *list2 = doc->list2->data; + cxListRemove(list2, 1); + cxListInsert(list2, 1, strdup(newvalue)); + + doc->list2->update(doc->list2, 1); +} + void application_startup(UiEvent *event, void *data) { // global list UiContext *global = ui_global_context(); @@ -436,6 +451,10 @@ ui_table(obj, .model = model, .list = doc->list2, .colspan = 2, .fill = UI_ON, .contextmenu = menubuilder, .multiselection = TRUE, .onactivate = action_table_activate, .onactivatedata = "activate", .onselection = action_table_activate, .onselectiondata = "selection"); + ui_hbox(obj, .fill = UI_OFF) { + ui_textfield(obj, .value = doc->list_input); + ui_button(obj, .label = "Update List Item 1", .onclick = action_update_list); + } } ui_tab(obj, "Tab 2") { ui_button(obj, .label = "Button 1 Start Thread", .onclick=action_start_thread);
--- a/ui/common/types.c Tue Mar 18 17:47:40 2025 +0100 +++ b/ui/common/types.c Sun Mar 23 18:09:24 2025 +0100 @@ -162,7 +162,7 @@ UIEXPORT void ui_list_update(UiList *list) { if(list->update) { - list->update(list, 0); + list->update(list, -1); } }
--- a/ui/gtk/list.c Tue Mar 18 17:47:40 2025 +0100 +++ b/ui/gtk/list.c Sun Mar 23 18:09:24 2025 +0100 @@ -579,7 +579,16 @@ void ui_listview_update2(UiList *list, int i) { UiListView *view = list->obj; - ui_update_liststore(view->liststore, list); + if(i < 0) { + ui_update_liststore(view->liststore, list); + } else { + void *value = list->get(list, i); + if(value) { + ObjWrapper *obj = obj_wrapper_new(value); + g_list_store_remove(view->liststore, i); + g_list_store_insert(view->liststore, i, obj); + } + } } UiListSelection ui_listview_getselection2(UiList *list) { @@ -639,6 +648,86 @@ #else +static void update_list_row(GtkListStore *store, GtkTreeIter *iter, UiModel *model, void *elm) { + // set column values + int c = 0; + for(int i=0;i<model->columns;i++,c++) { + void *data = model->getvalue(elm, c); + + GValue value = G_VALUE_INIT; + switch(model->types[i]) { + case UI_STRING: + case UI_STRING_FREE: { + g_value_init(&value, G_TYPE_STRING); + g_value_set_string(&value, data); + if(model->types[i] == UI_STRING_FREE) { + free(data); + } + break; + } + case UI_INTEGER: { + g_value_init(&value, G_TYPE_INT); + intptr_t intptr = (intptr_t)data; + g_value_set_int(&value, (int)intptr); + break; + } + case UI_ICON: { + g_value_init(&value, G_TYPE_OBJECT); + UiIcon *icon = data; +#if GTK_MAJOR_VERSION >= 4 + g_value_set_object(&value, icon->info); // TODO: does this work? +#else + if(!icon->pixbuf && icon->info) { + GError *error = NULL; + GdkPixbuf *pixbuf = gtk_icon_info_load_icon(icon->info, &error); + icon->pixbuf = pixbuf; + } + + if(icon->pixbuf) { + g_value_set_object(&value, icon->pixbuf); + } +#endif + break; + } + case UI_ICON_TEXT: + case UI_ICON_TEXT_FREE: { + UiIcon *icon = data; +#if GTK_MAJOR_VERSION >= 4 + if(icon) { + GValue iconvalue = G_VALUE_INIT; + g_value_init(&iconvalue, G_TYPE_OBJECT); + g_value_set_object(&iconvalue, ui_icon_pixbuf(icon)); + gtk_list_store_set_value(store, &iter, c, &iconvalue); + } +#else + GValue pixbufvalue = G_VALUE_INIT; + if(icon) { + if(!icon->pixbuf && icon->info) { + GError *error = NULL; + GdkPixbuf *pixbuf = gtk_icon_info_load_icon(icon->info, &error); + icon->pixbuf = pixbuf; + } + g_value_init(&pixbufvalue, G_TYPE_OBJECT); + g_value_set_object(&pixbufvalue, icon->pixbuf); + gtk_list_store_set_value(store, iter, c, &pixbufvalue); + } +#endif + c++; + + char *str = model->getvalue(elm, c); + g_value_init(&value, G_TYPE_STRING); + g_value_set_string(&value, str); + if(model->types[i] == UI_ICON_TEXT_FREE) { + free(str); + } + break; + } + } + + gtk_list_store_set_value(store, iter, c, &value); + } +} + static GtkListStore* create_list_store(UiList *list, UiModel *model) { int columns = model->columns; GType types[2*columns]; @@ -666,83 +755,7 @@ GtkTreeIter iter; gtk_list_store_insert (store, &iter, -1); - // set column values - int c = 0; - for(int i=0;i<columns;i++,c++) { - void *data = model->getvalue(elm, c); - - GValue value = G_VALUE_INIT; - switch(model->types[i]) { - case UI_STRING: - case UI_STRING_FREE: { - g_value_init(&value, G_TYPE_STRING); - g_value_set_string(&value, data); - if(model->types[i] == UI_STRING_FREE) { - free(data); - } - break; - } - case UI_INTEGER: { - g_value_init(&value, G_TYPE_INT); - intptr_t intptr = (intptr_t)data; - g_value_set_int(&value, (int)intptr); - break; - } - case UI_ICON: { - g_value_init(&value, G_TYPE_OBJECT); - UiIcon *icon = data; -#if GTK_MAJOR_VERSION >= 4 - g_value_set_object(&value, icon->info); // TODO: does this work? -#else - if(!icon->pixbuf && icon->info) { - GError *error = NULL; - GdkPixbuf *pixbuf = gtk_icon_info_load_icon(icon->info, &error); - icon->pixbuf = pixbuf; - } - - if(icon->pixbuf) { - g_value_set_object(&value, icon->pixbuf); - } -#endif - break; - } - case UI_ICON_TEXT: - case UI_ICON_TEXT_FREE: { - UiIcon *icon = data; -#if GTK_MAJOR_VERSION >= 4 - if(icon) { - GValue iconvalue = G_VALUE_INIT; - g_value_init(&iconvalue, G_TYPE_OBJECT); - g_value_set_object(&iconvalue, ui_icon_pixbuf(icon)); - gtk_list_store_set_value(store, &iter, c, &iconvalue); - } -#else - GValue pixbufvalue = G_VALUE_INIT; - if(icon) { - if(!icon->pixbuf && icon->info) { - GError *error = NULL; - GdkPixbuf *pixbuf = gtk_icon_info_load_icon(icon->info, &error); - icon->pixbuf = pixbuf; - } - g_value_init(&pixbufvalue, G_TYPE_OBJECT); - g_value_set_object(&pixbufvalue, icon->pixbuf); - gtk_list_store_set_value(store, &iter, c, &pixbufvalue); - } -#endif - c++; - - char *str = model->getvalue(elm, c); - g_value_init(&value, G_TYPE_STRING); - g_value_set_string(&value, str); - if(model->types[i] == UI_ICON_TEXT_FREE) { - free(str); - } - break; - } - } - - gtk_list_store_set_value(store, &iter, c, &value); - } + update_list_row(store, &iter, model, elm); // next row elm = list->next(list); @@ -1039,9 +1052,18 @@ void ui_listview_update(UiList *list, int i) { UiListView *view = list->obj; - GtkListStore *store = create_list_store(list, view->model); - gtk_tree_view_set_model(GTK_TREE_VIEW(view->widget), GTK_TREE_MODEL(store)); - g_object_unref(G_OBJECT(store)); + if(i < 0) { + GtkListStore *store = create_list_store(list, view->model); + gtk_tree_view_set_model(GTK_TREE_VIEW(view->widget), GTK_TREE_MODEL(store)); + g_object_unref(G_OBJECT(store)); + } else { + void *elm = list->get(list, i); + GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(view->widget)); + GtkTreeIter iter; + if(gtk_tree_model_iter_nth_child(store, &iter, NULL, i)) { + update_list_row(GTK_LIST_STORE(store), &iter, view->model, elm); + } + } } UiListSelection ui_listview_getselection(UiList *list) {