ui/motif/list.c

changeset 431
bb7da585debc
parent 427
7ead63398a50
--- a/ui/motif/list.c	Sun May 23 09:44:43 2021 +0200
+++ b/ui/motif/list.c	Sat Jan 04 16:38:48 2025 +0100
@@ -34,87 +34,118 @@
 #include "list.h"
 #include "../common/object.h"
 
-
-void* ui_strmodel_getvalue(void *elm, int column) {
-    return column == 0 ? elm : NULL;
-}
-
-
-UIWIDGET ui_listview_str(UiObject *obj, UiList *list, ui_callback f, void *udata) {
-    return ui_listview(obj, list, ui_strmodel_getvalue, f, udata);
-}
-
-UIWIDGET ui_listview_var(UiObject *obj, UiVar *var, ui_getvaluefunc getvalue, ui_callback f, void *udata) {
-    int count;
-    XmStringTable items = ui_create_stringlist(var->value, getvalue, &count);
+UIWIDGET ui_listview_create(UiObject* obj, UiListArgs args) {
+    Arg xargs[16];
+    int n = 0;
+    
+    UiContainerPrivate *ctn = ui_obj_container(obj);
+    UI_APPLY_LAYOUT(ctn->layout, args);
     
-    Arg args[8];
-    int n = 0;
-    XtSetArg(args[n], XmNitemCount, count);
-    n++;
-    XtSetArg(args[n], XmNitems, count == 0 ? NULL : items);
-    n++;
+    if(args.multiselection) {
+        XtSetArg(xargs[n], XmNselectionPolicy, XmEXTENDED_SELECT); n++;
+    } else {
+        XtSetArg(xargs[n], XmNselectionPolicy, XmSINGLE_SELECT); n++;
+    }
     
-    UiContainer *ct = uic_get_current_container(obj);
-    Widget parent = ct->prepare(ct, args, &n, TRUE);
-    Widget widget = XmCreateScrolledList(parent, "listview", args, n);
-    ct->add(ct, XtParent(widget));
+    char *name = args.name ? (char*)args.name : "listview";
+    Widget parent = ctn->prepare(ctn, xargs, &n);
+    Widget widget = XmCreateScrolledList(parent, name, xargs, n);
     XtManageChild(widget);
     
-    UiListView *listview = ucx_mempool_malloc(obj->ctx->mempool, sizeof(UiListView));
-    listview->widget = widget;
-    listview->list = var;
-    listview->getvalue = getvalue;
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.list, args.varname, UI_VAR_LIST);
     
-    for (int i=0;i<count;i++) {
-        XmStringFree(items[i]);
-    }
-    XtFree((char *)items);
+    UiListView *listview = malloc(sizeof(UiListView));
+    memset(listview, 0, sizeof(UiListView));
+    listview->obj = obj;
+    listview->widget = widget;
+    listview->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
+    listview->var = var;
+    listview->onactivate = args.onactivate;
+    listview->onactivatedata = args.onactivatedata;
+    listview->onselection = args.onselection;
+    listview->onselectiondata = args.onselectiondata;
     
-    if(f) {
-        UiListViewEventData *event = ucx_mempool_malloc(
-                obj->ctx->mempool,
-                sizeof(UiListViewEventData));
-        event->event.obj = obj;
-        event->event.userdata = udata;
-        event->event.callback = f;
-        event->event.value = 0;
-        event->var = var;
-        XtAddCallback(
+    if(var) {
+        UiList *list = var->value;
+        list->obj = listview;
+        list->update = ui_listview_update;
+        list->getselection = ui_listview_getselection;
+        list->setselection = ui_listview_setselection;
+        ui_listview_update(list, 0);
+    }
+    
+    XtAddCallback(
+                widget,
+                XmNdestroyCallback,
+                (XtCallbackProc)ui_listview_destroy,
+                listview);
+    
+    XtAddCallback(
                 widget,
                 XmNdefaultActionCallback,
-                (XtCallbackProc)ui_list_selection_callback,
-                event);
-    }
+                (XtCallbackProc)ui_listview_activate,
+                listview);
+    XtAddCallback(
+                widget,
+                XmNextendedSelectionCallback,
+                (XtCallbackProc)ui_listview_selection,
+                listview);
+    XtAddCallback(
+                widget,
+                XmNsingleSelectionCallback,
+                (XtCallbackProc)ui_listview_selection,
+                listview);
     
     return widget;
 }
 
-UIWIDGET ui_listview(UiObject *obj, UiList *list, ui_getvaluefunc getvalue, ui_callback f, void *udata) {
-    UiVar *var = malloc(sizeof(UiVar));
-    var->value = list;
-    var->type = UI_VAR_SPECIAL;
-    return ui_listview_var(obj, var, getvalue, f, udata);
+void ui_listview_destroy(Widget w, UiListView *listview, XtPointer d) {
+    // TODO
+}
+
+static void list_callback(UiObject *obj, UiListSelection sel, ui_callback callback, void *userdata) {
+    UiEvent event;
+    event.obj = obj;
+    event.window = obj->window;
+    event.document = obj->ctx->document;
+    event.eventdata = &sel;
+    event.intval = sel.count > 0 ? sel.rows[0] : -1;
+    callback(&event, userdata);
 }
 
-UIWIDGET ui_listview_nv(UiObject *obj, char *varname, ui_getvaluefunc getvalue, ui_callback f, void *udata) {
-    UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_LIST);
-    if(var) {
-        UiListVar *value = var->value;
-        return ui_listview_var(obj, var, getvalue, f, udata);
-    } else {
-        // TODO: error
+static void listview_save_selection(UiListView *listview, XmListCallbackStruct *cb) {
+    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;
+        }
     }
-    return NULL;
+    free(listview->current_selection.rows);
+    listview->current_selection = sel;
 }
 
+void ui_listview_activate(Widget w, UiListView *listview, XmListCallbackStruct *cb) {
+    listview_save_selection(listview, cb);
+    if(listview->onactivate) {
+        list_callback(listview->obj, listview->current_selection, listview->onactivate, listview->onactivatedata);
+    }
+}
 
-XmStringTable ui_create_stringlist(UiList *list, ui_getvaluefunc getvalue, int *count) { 
+void ui_listview_selection(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);
+    }
+}
+
+static XmStringTable create_stringlist(UiList *list, ui_getvaluefunc getvalue, int *count) { 
     int num = list->count(list);
     XmStringTable items = (XmStringTable)XtMalloc(num * sizeof(XmString));
     void *data = list->first(list);
     for(int i=0;i<num;i++) {
-        items[i] = XmStringCreateLocalized(getvalue(data, 0));
+        char *s = getvalue(data, 0);
+        items[i] = XmStringCreateLocalized(s ? s : "");
         data = list->next(list);
     }
     
@@ -122,16 +153,17 @@
     return items;
 }
 
-
-void ui_listview_update(UiEvent *event, UiListView *view) {
+void ui_listview_update(UiList *list, int i) {
+    UiListView *listview = list->obj;
+    
     int count;
-    XmStringTable items = ui_create_stringlist(
-            view->list->value,
-            view->getvalue,
+    XmStringTable items = create_stringlist(
+            list,
+            listview->getvalue,
             &count);
     
     XtVaSetValues(
-            view->widget,
+            listview->widget,
             XmNitems, count == 0 ? NULL : items,
             XmNitemCount,
             count,
@@ -143,65 +175,24 @@
     XtFree((char *)items);
 }
 
-void ui_list_selection_callback (Widget widget, UiListViewEventData *event, XtPointer data) {
-    XmListCallbackStruct *cbs = (XmListCallbackStruct *)data;
-    
-    UiEvent e;
-    e.obj = event->event.obj;
-    e.window = event->event.obj->window;
-    e.document = event->event.obj->ctx->document;
-    UiList *list = event->var->value;
-    e.eventdata = list->get(list, cbs->item_position - 1);
-    e.intval = cbs->item_position - 1;
-    event->event.callback(&e, event->event.userdata);
-}
-
-
-/* --------------------------- ComboBox ---------------------------  */
-
-UIWIDGET ui_combobox_str(UiObject *obj, UiList *list, ui_callback f, void *udata) {
-    return ui_combobox(obj, list, ui_strmodel_getvalue, f, udata);
-}
-
-UIWIDGET ui_combobox(UiObject *obj, UiList *list, ui_getvaluefunc getvalue, ui_callback f, void *udata) {
-    UiVar *var = malloc(sizeof(UiVar));
-    var->value = list;
-    var->type = UI_VAR_SPECIAL;
-    return ui_combobox_var(obj, var, getvalue, f, udata);
+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));
+    }
+    return sel;
 }
 
-UIWIDGET ui_combobox_nv(UiObject *obj, char *varname, ui_getvaluefunc getvalue, ui_callback f, void *udata) {
-    UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_LIST);
-    if(var) {
-        UiListVar *value = var->value;
-        return ui_combobox_var(obj, var, getvalue, f, udata);
-    } else {
-        // TODO: error
+void ui_listview_setselection(UiList *list, UiListSelection selection) {
+    UiListView *listview = list->obj;
+    XmListDeselectAllItems(listview->widget);
+    for(int i=0;i<selection.count;i++) {
+        XmListSelectPos(listview->widget, selection.rows[i]+1, False);
     }
-    return NULL;
 }
 
-UIWIDGET ui_combobox_var(UiObject *obj, UiVar *var, ui_getvaluefunc getvalue, ui_callback f, void *udata) {
-    UiListView *listview = ucx_mempool_malloc(
-                obj->ctx->mempool,
-                sizeof(UiListView));
-    
-    UiContainer *ct = uic_get_current_container(obj);
-    Arg args[16];
-    int n = 0;
-    XtSetArg(args[n], XmNindicatorOn, XmINDICATOR_NONE);
-    n++;
-    XtSetArg(args[n], XmNtraversalOn, FALSE);
-    n++;
-    XtSetArg(args[n], XmNwidth, 160);
-    n++;
-    Widget parent = ct->prepare(ct, args, &n, FALSE);
-    Widget combobox = XmCreateDropDownList(parent, "combobox", args, n);
-    XtManageChild(combobox);
-    listview->widget = combobox;
-    listview->list = var;
-    listview->getvalue = getvalue;
-    
-    ui_listview_update(NULL, listview);
-    
+void* ui_strmodel_getvalue(void *elm, int column) {
+    return column == 0 ? elm : NULL;
 }

mercurial