--- 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; }