ui/win32/list.c

changeset 917
ca3918f9c96b
child 918
7d3dd5aacfda
equal deleted inserted replaced
916:6fdcf1cbbec9 917:ca3918f9c96b
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2025 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "list.h"
30 #include "container.h"
31
32
33
34 static W32WidgetClass listview_widget_class = {
35 .eventproc = ui_listview_eventproc,
36 .enable = w32_widget_default_enable,
37 .show = w32_widget_default_show,
38 .get_preferred_size = ui_listview_get_preferred_size,
39 .destroy = w32_widget_default_destroy
40 };
41
42 static void* strmodel_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
43 return col == 0 ? elm : NULL;
44 }
45
46 static void* getvalue_wrapper(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
47 ui_getvaluefunc getvalue = (ui_getvaluefunc)userdata;
48 return getvalue(elm, col);
49 }
50
51 static void* null_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
52 return NULL;
53 }
54
55
56 static UiListView* create_listview_widget(UiObject *obj, HWND hwnd, UiListArgs *args, UiBool table) {
57 UiListView *listview = w32_widget_create(&listview_widget_class, hwnd, sizeof(UiWidget));
58 listview->widget.hwnd = hwnd;
59 listview->preferred_width = args->width ? args->width : 300;
60 listview->preferred_height = args->height ? args->height : 300;
61 listview->onactivate = args->onactivate;
62 listview->onactivatedata = args->onactivatedata;
63 listview->onselection = args->onselection;
64 listview->onselectiondata = args->onselectiondata;
65 listview->ondragstart = args->ondragstart;
66 listview->ondragstartdata = args->ondragstartdata;
67 listview->ondragcomplete = args->ondragcomplete;
68 listview->ondragcompletedata = args->ondragcompletedata;
69 listview->ondrop = args->ondrop;
70 listview->ondropdata = args->ondropdata;
71 listview->istable = table;
72
73 ui_getvaluefunc2 getvalue = args->getvalue2;
74 void *getvaluedata = args->getvalue2data;
75 if(!getvalue) {
76 if(args->getvalue) {
77 getvalue = getvalue_wrapper;
78 getvaluedata = (void*)args->getvalue;
79 } else {
80 getvalue = table ? null_getvalue : strmodel_getvalue;
81 }
82 }
83 listview->getvalue = getvalue;
84 listview->getvaluedata = getvaluedata;
85
86 listview->var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST);
87
88 return listview;
89 }
90
91 static UIWIDGET listview_create(UiObject *obj, UiListArgs *args, UiBool table) {
92 HINSTANCE hInstance = GetModuleHandle(NULL);
93 UiContainerPrivate *container = ui_obj_container(obj);
94 HWND parent = ui_container_get_parent(container);
95 UiLayout layout = UI_ARGS2LAYOUT(args);
96
97 int type = table ? LVS_REPORT : LVS_LIST;
98 HWND hwnd = CreateWindowEx(
99 WS_EX_CLIENTEDGE,
100 WC_LISTVIEW,
101 "",
102 WS_CHILD | WS_VISIBLE | LVS_REPORT,
103 0, 0, 100, 100,
104 parent,
105 (HMENU)1,
106 hInstance,
107 NULL);
108 ui_win32_set_ui_font(hwnd);
109
110 ListView_SetExtendedListViewStyle(
111 hwnd,
112 LVS_EX_FULLROWSELECT //| LVS_EX_GRIDLINES
113 );
114
115 UiListView *listview = create_listview_widget(obj, hwnd, args, table);
116 ui_container_add(container, (W32Widget*)listview, &layout);
117
118 // model
119 int numcolumns = 0;
120 if (table) {
121 if (args->model) {
122 listview->model = ui_model_copy(obj->ctx, args->model);
123 numcolumns = listview->model->columns;
124 } else {
125 listview->model = ui_model_new(obj->ctx);
126 }
127 } else {
128 UiModel *model = ui_model_new(obj->ctx);
129 ui_model_add_column(obj->ctx, model, UI_STRING, "Test", -1);
130 listview->model = model;
131 numcolumns = 1;
132 }
133
134 ///*
135 UiModel *model = listview->model;
136 for (int i=0;i<numcolumns;i++) {
137 LVCOLUMN col;
138 UiModelType type = model->types[i];
139 char *title = model->titles[i];
140 size_t titlelen = title ? strlen(title) : 0;
141 int size = model->columnsize[i];
142 switch (type) {
143 default: {
144 col.mask = LVCF_TEXT | LVCF_WIDTH;
145 col.pszText = title;
146 col.cx = size > 0 ? size : titlelen*10+5;
147 break;
148 }
149 case UI_ICON: {
150 break; // TODO
151 }
152 }
153 ListView_InsertColumn(hwnd, i, &col);
154 }
155
156 if (listview->var) {
157 UiList *list = listview->var->value;
158 list->obj = listview;
159 list->update = ui_listview_update;
160 list->getselection = ui_listview_getselection;
161 list->setselection = ui_listview_setselection;
162
163 ui_listview_update(list, -1);
164 }
165
166 return (W32Widget*)listview;
167 }
168
169 void ui_listview_eventproc(W32Widget *widget, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
170
171 }
172
173 W32Size ui_listview_get_preferred_size(W32Widget *widget) {
174 UiListView *listview = (UiListView*)widget;
175 W32Size size;
176 size.width = listview->preferred_width;
177 size.height = listview->preferred_height;
178 return size;
179 }
180
181 void ui_listview_update(UiList *list, int row) {
182 UiListView *listview = (UiListView*)list->obj;
183 HWND hwnd = listview->widget.hwnd;
184 UiModel *model = listview->model;
185 if (row < 0) {
186 ListView_DeleteAllItems(hwnd);
187 void *elm = list->first(list);
188 int row = 0;
189 while (elm) {
190 LVITEM item;
191 item.mask = LVIF_TEXT;
192 item.iItem = row;
193 item.iSubItem = 0;
194 int idx = -1;
195 for (int col=0;col<model->columns;col++) {
196 UiBool freeResult = FALSE;
197 char *str = listview->getvalue(list, elm, row, col, listview->getvaluedata, &freeResult);
198 if (col == 0) {
199 item.pszText = str;
200 idx = ListView_InsertItem(hwnd, &item);
201 } else {
202 ListView_SetItemText(hwnd, idx, col, str);
203 }
204
205 if (freeResult) {
206 free(str);
207 }
208 }
209
210 elm = list->next(list);
211 row++;
212 }
213
214 for (int i=0;i<model->columns;i++) {
215 ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE);
216 }
217 } else {
218 // TODO
219 }
220 }
221
222 UiListSelection ui_listview_getselection(UiList *list) {
223 UiListSelection sel = { 0, NULL };
224 return sel;
225 }
226
227 void ui_listview_setselection(UiList *list, UiListSelection selection) {
228
229 }
230
231 UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) {
232 return listview_create(obj, args, FALSE);
233 }
234
235 UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
236 return listview_create(obj, args, TRUE);
237 }

mercurial