diff -r 7d3dd5aacfda -r d9018dcd4e2d ui/win32/list.c --- a/ui/win32/list.c Wed Nov 19 12:17:59 2025 +0100 +++ b/ui/win32/list.c Wed Nov 19 13:02:55 2025 +0100 @@ -26,6 +26,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include +#include + +#include + #include "list.h" #include "container.h" @@ -52,11 +57,14 @@ return NULL; } - +/* + * Creates an UiListView widget object and initializes it from the UiListArgs + */ static UiListView* create_listview_widget(UiObject *obj, HWND hwnd, UiListArgs *args, UiBool table) { UiListView *listview = w32_widget_create(&listview_widget_class, hwnd, sizeof(UiListView)); listview->widget.hwnd = hwnd; - listview->preferred_width = args->width ? args->width : 300; + listview->obj = obj; + listview->preferred_width = args->width ? args->width : 300; // 300: default width/height listview->preferred_height = args->height ? args->height : 300; listview->onactivate = args->onactivate; listview->onactivatedata = args->onactivatedata; @@ -70,6 +78,7 @@ listview->ondropdata = args->ondropdata; listview->istable = table; + // convert ui_getvaluefunc into ui_getvaluefunc2 if necessary ui_getvaluefunc2 getvalue = args->getvalue2; void *getvaluedata = args->getvalue2data; if(!getvalue) { @@ -105,7 +114,6 @@ hInstance, NULL); ui_win32_set_ui_font(hwnd); - ListView_SetExtendedListViewStyle( hwnd, LVS_EX_FULLROWSELECT //| LVS_EX_GRIDLINES @@ -114,7 +122,8 @@ UiListView *listview = create_listview_widget(obj, hwnd, args, table); ui_container_add(container, (W32Widget*)listview, &layout); - // model + // init list model + // always initialize listview->model int numcolumns = 0; if (table) { if (args->model) { @@ -130,6 +139,7 @@ numcolumns = 1; } + // create columns UiModel *model = listview->model; for (int i=0;ivar) { UiList *list = listview->var->value; list->obj = listview; @@ -164,8 +175,80 @@ return (W32Widget*)listview; } +static UiListSelection listview_get_selection(UiListView *listview) { + UiListSelection sel = { 0, NULL }; + HWND hwnd = listview->widget.hwnd; + + CX_ARRAY_DECLARE(int, indices); + cx_array_initialize(indices, 8); + + int index = -1; + while ((index = ListView_GetNextItem(hwnd, index, LVNI_SELECTED)) != -1) { + cx_array_simple_add(indices, index); + } + + if (indices_size > 0) { + sel.rows = indices; + sel.count = indices_size; + } + + return sel; +} + +// listview class event proc void ui_listview_eventproc(W32Widget *widget, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + UiListView *listview = (UiListView*)widget; + switch (uMsg) { + case WM_NOTIFY: { + LPNMHDR hdr = (LPNMHDR)lParam; + switch (hdr->code) { + case LVN_ITEMCHANGED: { + LPNMLISTVIEW lv = (LPNMLISTVIEW)lParam; + int row = lv->iItem; + if ((lv->uChanged & LVIF_STATE) && (lv->uNewState & LVIS_SELECTED) && listview->onselection) { + UiListSelection sel = listview_get_selection(listview); + UiEvent event; + event.obj = listview->obj; + event.window = listview->obj->window; + event.document = listview->obj->ctx->document; + event.eventdata = &sel; + event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION; + event.intval = row; + event.set = ui_get_setop(); + listview->onselection(&event, listview->onselectiondata); + + ui_listselection_free(sel); + } + break; + } + case LVN_ITEMACTIVATE: { + LPNMLISTVIEW lv = (LPNMLISTVIEW)lParam; + int row = lv->iItem; + if (listview->onactivate) { + UiEvent event; + event.obj = listview->obj; + event.window = listview->obj->window; + event.document = listview->obj->ctx->document; + event.eventdata = NULL; + event.eventdatatype = UI_EVENT_DATA_LIST_ELM; + event.intval = row; + event.set = ui_get_setop(); + + if (listview->var) { + UiList *list = listview->var->value; + event.eventdata = list->get(list, row); + event.eventdatatype = UI_EVENT_DATA_LIST_ELM; + } + + listview->onactivate(&event, listview->onactivatedata); + } + break; + } + } + break; + } + } } W32Size ui_listview_get_preferred_size(W32Widget *widget) { @@ -176,6 +259,13 @@ return size; } +/* + * Creates and inserts an LVITEM + * + * list: An UiList bound to an UiListView + * row: row index + * elm: list element (same as list->get(list, row)) + */ static void insert_item(UiList *list, int row, void *elm) { UiListView *listview = (UiListView*)list->obj; HWND hwnd = listview->widget.hwnd; @@ -188,6 +278,8 @@ int idx = -1; for (int col=0;colcolumns;col++) { UiBool freeResult = FALSE; + // convert the list element to a value, that can be displayed in the list view + // TODO: handle all model types char *str = listview->getvalue(list, elm, row, col, listview->getvaluedata, &freeResult); if (col == 0) { item.pszText = str; @@ -202,6 +294,12 @@ } } +/* + * UiList->update function + * + * Updates one or all rows + * row: list index or -1 for updating all rows + */ void ui_listview_update(UiList *list, int row) { UiListView *listview = (UiListView*)list->obj; HWND hwnd = listview->widget.hwnd; @@ -221,24 +319,27 @@ insert_item(list, row, elm); } + // re-adjust all columns for (int i=0;icolumns;i++) { ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE); } } UiListSelection ui_listview_getselection(UiList *list) { - UiListSelection sel = { 0, NULL }; - return sel; + UiListView *listview = (UiListView*)list->obj; + return listview_get_selection(listview); } void ui_listview_setselection(UiList *list, UiListSelection selection) { } +// public API UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) { return listview_create(obj, args, FALSE); } +// public API UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) { return listview_create(obj, args, TRUE); }