ui/motif/list.c

changeset 115
e57ca2747782
parent 112
c3f2f16fa4b8
--- 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);
+}

mercurial