3 weeks ago
add support for dynamic sublists (GTK)
ui/gtk/list.c | file | annotate | diff | comparison | revisions | |
ui/gtk/list.h | file | annotate | diff | comparison | revisions | |
ui/ui/tree.h | file | annotate | diff | comparison | revisions |
--- a/ui/gtk/list.c Sun Feb 16 21:15:17 2025 +0100 +++ b/ui/gtk/list.c Sun Feb 16 22:49:09 2025 +0100 @@ -1566,6 +1566,34 @@ } #endif + +static void add_sublist(UiListBox *uilistbox, CxList *sublists, UiSubList *sublist) { + UiListBoxSubList uisublist; + uisublist.var = uic_widget_var( + uilistbox->obj->ctx, + uilistbox->obj->ctx, + sublist->value, + sublist->varname, + UI_VAR_LIST); + uisublist.numitems = 0; + uisublist.header = sublist->header ? strdup(sublist->header) : NULL; + uisublist.separator = sublist->separator; + uisublist.widgets = cxLinkedListCreateSimple(CX_STORE_POINTERS); + uisublist.listbox = uilistbox; + uisublist.userdata = sublist->userdata; + uisublist.index = cxListSize(sublists); + + // bind UiList + UiListBoxSubList *sublist_ptr = cxListAt(uilistbox->sublists, cxListSize(sublists)-1); + UiList *list = uisublist.var->value; + if(list) { + list->obj = sublist_ptr; + list->update = ui_listbox_list_update; + } + + cxListAdd(sublists, &uisublist); +} + UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs args) { UiObject* current = uic_current_obj(obj); @@ -1603,42 +1631,32 @@ uilistbox->sublists->collection.destructor_data = obj; uilistbox->first_row = NULL; - if(args.numsublists == 0 && args.sublists) { - args.numsublists = INT_MAX; - } - for(int i=0;i<args.numsublists;i++) { - UiSubList sublist = args.sublists[i]; - if(!sublist.varname && !sublist.value) { - break; + if(args.sublists) { + // static sublist initalization + if(args.numsublists == 0 && args.sublists) { + args.numsublists = INT_MAX; + } + for(int i=0;i<args.numsublists;i++) { + UiSubList sublist = args.sublists[i]; + if(!sublist.varname && !sublist.value) { + break; + } + + add_sublist(uilistbox, uilistbox->sublists, &sublist); } - UiListBoxSubList uisublist; - uisublist.var = uic_widget_var( - obj->ctx, - current->ctx, - sublist.value, - sublist.varname, - UI_VAR_LIST); - uisublist.numitems = 0; - uisublist.header = sublist.header ? strdup(sublist.header) : NULL; - uisublist.separator = sublist.separator; - uisublist.widgets = cxLinkedListCreateSimple(CX_STORE_POINTERS); - uisublist.listbox = uilistbox; - uisublist.userdata = sublist.userdata; - uisublist.index = i; - - cxListAdd(uilistbox->sublists, &uisublist); - - // bind UiList - UiListBoxSubList *sublist_ptr = cxListAt(uilistbox->sublists, cxListSize(uilistbox->sublists)-1); - UiList *list = uisublist.var->value; - if(list) { - list->obj = sublist_ptr; - list->update = ui_listbox_list_update; + // fill items + ui_listbox_update(uilistbox, 0, cxListSize(uilistbox->sublists)); + } else { + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.dynamic_sublist, args.varname, UI_VAR_LIST); + if(var) { + UiList *list = var->value; + list->obj = uilistbox; + list->update = ui_listbox_dynamic_update; + + ui_listbox_dynamic_update(list, 0); } } - // fill items - ui_listbox_update(uilistbox, 0, cxListSize(uilistbox->sublists)); // register uilistbox for both widgets, so it doesn't matter which // widget is used later @@ -1663,6 +1681,35 @@ return scroll_area; } +void ui_listbox_dynamic_update(UiList *list, int x) { + UiListBox *uilistbox = list->obj; + + // unbind/free previous list vars + CxIterator i = cxListIterator(uilistbox->sublists); + cx_foreach(UiListBoxSubList *, s, i) { + if(s->var) { + UiList *sl = s->var->value; + sl->obj = NULL; + sl->update = NULL; + if(s->var->type == UI_VAR_SPECIAL) { + ui_free(s->var->from_ctx, s->var); + } + } + } + + cxListFree(uilistbox->sublists); + CxList *new_sublists = cxArrayListCreateSimple(sizeof(UiListBoxSubList), list->count(list)); + uilistbox->sublists = new_sublists; + + UiSubList *sublist = list->first(list); + while(sublist) { + add_sublist(uilistbox, new_sublists, sublist); + sublist = list->next(list); + } + + ui_listbox_update(uilistbox, 0, cxListSize(uilistbox->sublists)); +} + void ui_listbox_update(UiListBox *listbox, int from, int to) { CxIterator i = cxListIterator(listbox->sublists); size_t pos = 0;
--- a/ui/gtk/list.h Sun Feb 16 21:15:17 2025 +0100 +++ b/ui/gtk/list.h Sun Feb 16 22:49:09 2025 +0100 @@ -161,6 +161,7 @@ UiListSelection ui_combobox_getselection(UiList *list); void ui_combobox_setselection(UiList *list, UiListSelection selection); +void ui_listbox_dynamic_update(UiList *list, int i); void ui_listbox_update(UiListBox *listbox, int from, int to); void ui_listbox_update_sublist(UiListBox *listbox, UiListBoxSubList *sublist, size_t listbox_insert_index); void ui_listbox_list_update(UiList *list, int i);
--- a/ui/ui/tree.h Sun Feb 16 21:15:17 2025 +0100 +++ b/ui/ui/tree.h Sun Feb 16 22:49:09 2025 +0100 @@ -183,11 +183,14 @@ const int *groups; /* - * list of sublists + * static list of sublists * a sublist must have a varname or a value * * the last entry in the list must contain all NULL values or numsublists * must contain the number of sublists + * + * sublists can be NULL, in which case sublists are dynamically loaded + * from dynamic_sublist/varname */ UiSubList *sublists; /* @@ -198,6 +201,17 @@ size_t numsublists; /* + * list value, that contains UiSubList* elements + */ + UiList *dynamic_sublist; + + /* + * load sublists dynamically from a variable with the specified name + */ + const char *varname; + + + /* * callback for each list item, that should fill all necessary * UiSubListItem fields */