Wed, 01 Jan 2025 11:39:42 +0100
implement listview (Motif)
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2014 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <stdio.h> #include <stdlib.h> #include "container.h" #include "list.h" #include "../common/object.h" 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); if(args.multiselection) { XtSetArg(xargs[n], XmNselectionPolicy, XmEXTENDED_SELECT); n++; } else { XtSetArg(xargs[n], XmNselectionPolicy, XmSINGLE_SELECT); n++; } char *name = args.name ? (char*)args.name : "listview"; Widget parent = ctn->prepare(ctn, xargs, &n); Widget widget = XmCreateScrolledList(parent, name, xargs, n); XtManageChild(widget); UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.list, args.varname, UI_VAR_LIST); 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(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_listview_activate, listview); XtAddCallback( widget, XmNextendedSelectionCallback, (XtCallbackProc)ui_listview_selection, listview); XtAddCallback( widget, XmNsingleSelectionCallback, (XtCallbackProc)ui_listview_selection, listview); return widget; } 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); } 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; } } 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); } } 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++) { char *s = getvalue(data, 0); items[i] = XmStringCreateLocalized(s ? s : ""); data = list->next(list); } *count = num; return items; } void ui_listview_update(UiList *list, int i) { UiListView *listview = list->obj; int count; XmStringTable items = create_stringlist( list, listview->getvalue, &count); XtVaSetValues( listview->widget, XmNitems, count == 0 ? NULL : items, XmNitemCount, count, NULL); for (int i=0;i<count;i++) { XmStringFree(items[i]); } XtFree((char *)items); } 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; } 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); } } void* ui_strmodel_getvalue(void *elm, int column) { return column == 0 ? elm : NULL; }