--- a/ui/win32/list.c Tue Nov 25 12:10:04 2025 +0100 +++ b/ui/win32/list.c Tue Nov 25 12:58:28 2025 +0100 @@ -60,8 +60,8 @@ /* * 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)); +static UiListView* create_listview_widget(UiObject *obj, W32WidgetClass *widget_class, HWND hwnd, UiListArgs *args, UiBool table) { + UiListView *listview = w32_widget_create(widget_class, hwnd, sizeof(UiListView)); listview->widget.hwnd = hwnd; listview->obj = obj; listview->preferred_width = args->width ? args->width : 300; // 300: default width/height @@ -119,7 +119,7 @@ LVS_EX_FULLROWSELECT //| LVS_EX_GRIDLINES ); - UiListView *listview = create_listview_widget(obj, hwnd, args, table); + UiListView *listview = create_listview_widget(obj, &listview_widget_class, hwnd, args, table); ui_container_add(container, (W32Widget*)listview, &layout); // init list model @@ -343,3 +343,111 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) { return listview_create(obj, args, TRUE); } + + +/* ------------------------------------ DropDown ------------------------------------*/ + +static W32WidgetClass dropdown_widget_class = { + .eventproc = ui_dropdown_eventproc, + .enable = w32_widget_default_enable, + .show = w32_widget_default_show, + .get_preferred_size = ui_dropdown_get_preferred_size, + .destroy = w32_widget_default_destroy +}; + +UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs *args) { + HINSTANCE hInstance = GetModuleHandle(NULL); + UiContainerPrivate *container = ui_obj_container(obj); + HWND parent = ui_container_get_parent(container); + UiLayout layout = UI_ARGS2LAYOUT(args); + + HWND hwnd = CreateWindowEx( + WS_EX_CLIENTEDGE, + WC_COMBOBOX, + "", + WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST, + 0, 0, 100, 100, + parent, + (HMENU)1337, + hInstance, + NULL); + ui_win32_set_ui_font(hwnd); + + UiListView *dropdown = create_listview_widget(obj, &dropdown_widget_class, hwnd, args, FALSE); + ui_container_add(container, (W32Widget*)dropdown, &layout); + + // bind the dropdown to the provided UiList + if (dropdown->var) { + UiList *list = dropdown->var->value; + list->obj = dropdown; + list->update = ui_dropdown_update; + list->getselection = ui_dropdown_getselection; + list->setselection = ui_dropdown_setselection; + + ui_dropdown_update(list, -1); + } + + + return (W32Widget*)dropdown; +} + +void ui_dropdown_eventproc(W32Widget *widget, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + +} + +W32Size ui_dropdown_get_preferred_size(W32Widget *widget) { + W32Size size; + size.width = 200; + size.height = 30; + return size; +} + +static void dropdown_insert_item(UiList *list, int row, void *elm) { + UiListView *listview = (UiListView*)list->obj; + HWND hwnd = listview->widget.hwnd; + + UiBool freeResult = FALSE; + char *str = listview->getvalue(list, elm, row, 0, listview->getvaluedata, &freeResult); + SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)str); + + if (freeResult) { + free(str); + } +} + +void ui_dropdown_update(UiList *list, int row) { + UiListView *listview = (UiListView*)list->obj; + HWND hwnd = listview->widget.hwnd; + if (row < 0) { + SendMessage(hwnd, CB_RESETCONTENT, 0, 0); + + void *elm = list->first(list); + int row = 0; + while (elm) { + dropdown_insert_item(list, row, elm); + elm = list->next(list); + row++; + } + } else { + SendMessage(hwnd, CB_DELETESTRING, row, 0); + void *elm = list->get(list, row); + dropdown_insert_item(list, row, elm); + } +} + +UiListSelection ui_dropdown_getselection(UiList *list) { + UiListSelection sel = { 0, NULL }; + UiListView *listview = (UiListView*)list->obj; + int index = (int)SendMessage(listview->widget.hwnd, CB_GETCURSEL, 0, 0); + if (index >= 0) { + sel.rows = malloc(sizeof(int)); + sel.rows[0] = index; + sel.count = 1; + } + return sel; +} + +void ui_dropdown_setselection(UiList *list, UiListSelection selection) { + UiListView *listview = (UiListView*)list->obj; + SendMessage(listview->widget.hwnd, CB_SETCURSEL, 0, 0); +}