Sun, 20 Jul 2025 22:04:39 +0200
update toolkit, adjust UI code
/* * 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" static void* getvalue_wrapper(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) { ui_getvaluefunc getvalue = (ui_getvaluefunc)userdata; return getvalue(elm, col); } /* static void* model_getvalue(UiModel *model, UiList *list, void *elm, int row, int col, UiBool *freeResult) { if(model->getvalue2) { return model->getvalue2(list, elm, row, col, model->getvalue2data, freeResult); } else if(model->getvalue) { return model->getvalue(elm, col); } return NULL; } */ 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; if(args->getvalue2) { listview->getvalue = args->getvalue2; listview->getvaluedata = args->getvalue2data; } else if(args->getvalue) { listview->getvalue = getvalue_wrapper; listview->getvaluedata = args->getvalue; } else { listview->getvalue = getvalue_wrapper; listview->getvaluedata = 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.eventdatatype = UI_EVENT_DATA_LIST_SELECTION; 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_getvaluefunc2 getvalue, void *getvaluedata, 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++) { UiBool freevalue = FALSE; char *s = getvalue(list, data, i, 0, getvaluedata, &freevalue); items[i] = XmStringCreateLocalized(s ? s : ""); if(freevalue) { free(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, listview->getvaluedata, &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) { ui_setop_enable(TRUE); UiListView *listview = list->obj; XmListDeselectAllItems(listview->widget); for(int i=0;i<selection.count;i++) { XmListSelectPos(listview->widget, selection.rows[i]+1, False); } ui_setop_enable(FALSE); } void* ui_strmodel_getvalue(void *elm, int column) { return column == 0 ? elm : NULL; } /* ------------------------------- Drop Down ------------------------------- */ static void ui_dropdown_selection( Widget w, UiListView *listview, XmComboBoxCallbackStruct *cb) { int index = cb->item_position; void *elm = NULL; if(listview->var) { UiList *list = listview->var->value; elm = ui_list_get(list, index); } UiEvent event; event.obj = listview->obj; event.window = event.obj->window; event.document = event.obj->ctx->document; event.eventdata = elm; event.eventdatatype = UI_EVENT_DATA_LIST_ELM; event.intval = index; if(listview->onactivate) { listview->onactivate(&event, listview->onactivatedata); } if(listview->onselection) { listview->onselection(&event, listview->onselectiondata); } } UIWIDGET ui_combobox_create(UiObject* obj, UiListArgs *args) { Arg xargs[16]; int n = 0; UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); char *name = args->name ? (char*)args->name : "dropdown"; Widget parent = ctn->prepare(ctn, xargs, &n); Widget widget = XmCreateDropDownList(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; if(args->getvalue2) { listview->getvalue = args->getvalue2; listview->getvaluedata = args->getvalue2data; } else if(args->getvalue) { listview->getvalue = getvalue_wrapper; listview->getvaluedata = args->getvalue; } else { listview->getvalue = getvalue_wrapper; listview->getvaluedata = 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, XmNselectionCallback, (XtCallbackProc)ui_dropdown_selection, listview); return widget; }