--- a/ui/motif/list.c Sun Dec 07 20:00:33 2025 +0100 +++ b/ui/motif/list.c Sat Dec 13 15:58:58 2025 +0100 @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> +#include <Xm/Xm.h> #include "container.h" @@ -62,6 +63,9 @@ } else { XtSetArg(xargs[n], XmNselectionPolicy, XmSINGLE_SELECT); n++; } + if(args->height > 0) { + XtSetArg(xargs[n], XmNheight, args->height); n++; + } char *name = args->name ? (char*)args->name : "listview"; Widget parent = ui_container_prepare(ctn, &layout, xargs, &n); @@ -91,6 +95,8 @@ listview->onselection = args->onselection; listview->onselectiondata = args->onselectiondata; + char **static_elements = args->static_elements; + size_t static_nelm = args->static_nelm; if(var) { UiList *list = var->value; list->obj = listview; @@ -98,6 +104,23 @@ list->getselection = ui_listview_getselection; list->setselection = ui_listview_setselection; ui_listview_update(list, 0); + } else if(static_elements && static_nelm > 0) { + XmStringTable items = calloc(static_nelm, sizeof(XmString)); + for(int i=0;i<static_nelm;i++) { + items[i] = XmStringCreateLocalized(static_elements[i]); + } + XtVaSetValues( + listview->widget, + XmNitems, items, + XmNitemCount, + static_nelm, + NULL); + for (int i=0;i<static_nelm;i++) { + XmStringFree(items[i]); + } + free(items); + listview->getvalue = getvalue_wrapper; + listview->getvaluedata = ui_strmodel_getvalue; } XtAddCallback( @@ -114,19 +137,36 @@ XtAddCallback( widget, XmNextendedSelectionCallback, - (XtCallbackProc)ui_listview_selection, + (XtCallbackProc)ui_listview_selection_changed, listview); XtAddCallback( widget, XmNsingleSelectionCallback, - (XtCallbackProc)ui_listview_selection, + (XtCallbackProc)ui_listview_selection_changed, listview); return widget; } +void ui_listview_select(UIWIDGET listview, int index) { + XmListDeselectAllItems(listview); + XmListSelectPos(listview, index+1, False); +} + +int ui_listview_selection(UIWIDGET listview) { + int *selpositions = NULL; + int numpos = 0; + XtVaGetValues(listview, XmNselectedPositions, &selpositions, XmNselectedPositionCount, &numpos, NULL); + return numpos > 0 ? selpositions[0] : -1; +} + void ui_listview_destroy(Widget w, UiListView *listview, XtPointer d) { - // TODO + ui_listselection_free(listview->current_selection); + if(listview->model) { + ui_model_remove_observer(listview->model, listview); + ui_model_unref(listview->model); + } + free(listview); } static void list_callback(UiObject *obj, UiListSelection sel, ui_callback callback, void *userdata) { @@ -144,8 +184,12 @@ UiListSelection sel = { cb->selected_item_count, NULL }; if(sel.count > 0) { sel.rows = calloc(sel.count, sizeof(int)); - for(int i=0;i<sel.count;i++) { - sel.rows[i] = cb->selected_item_positions[i]-1; + if(sel.count == 1) { + sel.rows[0] = cb->item_position-1; + } else if(cb->selected_item_positions) { + for(int i=0;i<sel.count;i++) { + sel.rows[i] = cb->selected_item_positions[i]-1; + } } } free(listview->current_selection.rows); @@ -159,7 +203,7 @@ } } -void ui_listview_selection(Widget w, UiListView *listview, XmListCallbackStruct *cb) { +void ui_listview_selection_changed(Widget w, UiListView *listview, XmListCallbackStruct *cb) { listview_save_selection(listview, cb); if(listview->onselection) { list_callback(listview->obj, listview->current_selection, listview->onselection, listview->onselectiondata); @@ -209,10 +253,18 @@ UiListSelection ui_listview_getselection(UiList *list) { UiListView *listview = list->obj; - UiListSelection sel = { listview->current_selection.count, NULL }; - if(sel.count > 0) { - sel.rows = calloc(sel.count, sizeof(int)); - memcpy(sel.rows, listview->current_selection.rows, sel.count*sizeof(int)); + UiListSelection sel = { 0, NULL }; + int *selpositions = NULL; + int numpos = 0; + XtVaGetValues(listview->widget, XmNselectedPositions, &selpositions, XmNselectedPositionCount, &numpos, NULL); + if(numpos > 0) { + sel.rows = calloc(numpos, sizeof(int)); + sel.count = numpos; + memcpy(sel.rows, selpositions, numpos*sizeof(int)); + // motif selected positions start at index 1 -> translate positions + for(int i=0;i<numpos;i++) { + sel.rows[i]--; + } } return sel; } @@ -233,7 +285,7 @@ /* ------------------------------- Drop Down ------------------------------- */ -static void ui_dropdown_selection( +static void ui_dropdown_selection_changed( Widget w, UiListView *listview, XmComboBoxCallbackStruct *cb) @@ -260,7 +312,7 @@ } } -UIWIDGET ui_combobox_create(UiObject* obj, UiListArgs *args) { +UIWIDGET ui_dropdown_create(UiObject* obj, UiListArgs *args) { Arg xargs[16]; int n = 0; @@ -295,13 +347,32 @@ listview->onselection = args->onselection; listview->onselectiondata = args->onselectiondata; + char **static_elements = args->static_elements; + size_t static_nelm = args->static_nelm; if(var) { UiList *list = var->value; list->obj = listview; list->update = ui_listview_update; - list->getselection = ui_listview_getselection; - list->setselection = ui_listview_setselection; + list->getselection = ui_dropdown_getselection; + list->setselection = ui_dropdown_setselection; ui_listview_update(list, 0); + } else if(static_elements && static_nelm > 0) { + XmStringTable items = calloc(static_nelm, sizeof(XmString)); + for(int i=0;i<static_nelm;i++) { + items[i] = XmStringCreateLocalized(static_elements[i]); + } + XtVaSetValues( + listview->widget, + XmNitems, items, + XmNitemCount, + static_nelm, + NULL); + for (int i=0;i<static_nelm;i++) { + XmStringFree(items[i]); + } + free(items); + listview->getvalue = getvalue_wrapper; + listview->getvaluedata = ui_strmodel_getvalue; } XtAddCallback( @@ -312,8 +383,39 @@ XtAddCallback( widget, XmNselectionCallback, - (XtCallbackProc)ui_dropdown_selection, + (XtCallbackProc)ui_dropdown_selection_changed, listview); return widget; } + +void ui_dropdown_setselection(UiList *list, UiListSelection selection) { + UiListView *listview = list->obj; + if(selection.count > 0) { + XtVaSetValues(listview->widget, XmNselectedPosition, selection.rows[0], NULL); + } else { + XtVaSetValues(listview->widget, XmNselectedPosition, 0, NULL); + } +} + +UiListSelection ui_dropdown_getselection(UiList *list) { + UiListView *listview = list->obj; + int pos = -1; + XtVaGetValues(listview->widget, XmNselectedPosition, &pos, NULL); + UiListSelection sel = { 0, NULL }; + if(pos >= 0) { + sel.rows = malloc(sizeof(int)); + sel.rows[0] = pos; + sel.count = 1; + } + return sel; +} + +void ui_dropdown_select(UIWIDGET dropdown, int index) { + XtVaSetValues(dropdown, XmNselectedPosition, index, NULL); +} + +int ui_dropdown_selection(UIWIDGET dropdown) { + int pos = -1; + XtVaGetValues(dropdown, XmNselectedPosition, &pos, NULL); +}