1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include <cx/array_list.h>
33
34 #include "list.h"
35 #include "container.h"
36
37
38
39 static W32WidgetClass listview_widget_class = {
40 .eventproc = ui_listview_eventproc,
41 .enable = w32_widget_default_enable,
42 .show = w32_widget_default_show,
43 .get_preferred_size = ui_listview_get_preferred_size,
44 .destroy = w32_widget_default_destroy
45 };
46
47 static void* strmodel_getvalue(UiList *list,
void *elm,
int row,
int col,
void *userdata, UiBool *freeResult) {
48 return col ==
0 ? elm :
NULL;
49 }
50
51 static void* getvalue_wrapper(UiList *list,
void *elm,
int row,
int col,
void *userdata, UiBool *freeResult) {
52 ui_getvaluefunc getvalue = (ui_getvaluefunc)userdata;
53 return getvalue(elm, col);
54 }
55
56 static void* null_getvalue(UiList *list,
void *elm,
int row,
int col,
void *userdata, UiBool *freeResult) {
57 return NULL;
58 }
59
60
61
62
63 static UiListView* create_listview_widget(UiObject *obj, W32WidgetClass *widget_class,
HWND hwnd, UiListArgs *args, UiBool table) {
64 UiListView *listview = w32_widget_create(widget_class, hwnd,
sizeof(UiListView));
65 listview->widget.hwnd = hwnd;
66 listview->obj = obj;
67 listview->preferred_width = args->width ? args->width :
300;
68 listview->preferred_height = args->height ? args->height :
300;
69 listview->onactivate = args->onactivate;
70 listview->onactivatedata = args->onactivatedata;
71 listview->onselection = args->onselection;
72 listview->onselectiondata = args->onselectiondata;
73 listview->ondragstart = args->ondragstart;
74 listview->ondragstartdata = args->ondragstartdata;
75 listview->ondragcomplete = args->ondragcomplete;
76 listview->ondragcompletedata = args->ondragcompletedata;
77 listview->ondrop = args->ondrop;
78 listview->ondropdata = args->ondropdata;
79 listview->istable = table;
80
81
82 ui_getvaluefunc2 getvalue = args->getvalue2;
83 void *getvaluedata = args->getvalue2data;
84 if(!getvalue) {
85 if(args->getvalue) {
86 getvalue = getvalue_wrapper;
87 getvaluedata = (
void*)args->getvalue;
88 }
else {
89 getvalue = table ? null_getvalue : strmodel_getvalue;
90 }
91 }
92 listview->getvalue = getvalue;
93 listview->getvaluedata = getvaluedata;
94
95 listview->var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname,
UI_VAR_LIST);
96
97 return listview;
98 }
99
100 static UIWIDGET listview_create(UiObject *obj, UiListArgs *args, UiBool table) {
101 HINSTANCE hInstance = GetModuleHandle(
NULL);
102 UiContainerPrivate *container = ui_obj_container(obj);
103 HWND parent = ui_container_get_parent(container);
104 UiLayout layout =
UI_ARGS2LAYOUT(args);
105
106 HWND hwnd = CreateWindowEx(
107 WS_EX_CLIENTEDGE,
108 WC_LISTVIEW,
109 "",
110 WS_CHILD |
WS_VISIBLE |
LVS_REPORT,
111 0,
0,
100,
100,
112 parent,
113 (
HMENU)
1337,
114 hInstance,
115 NULL);
116 ui_win32_set_ui_font(hwnd);
117 ListView_SetExtendedListViewStyle(
118 hwnd,
119 LVS_EX_FULLROWSELECT
120 );
121
122 UiListView *listview = create_listview_widget(obj, &listview_widget_class, hwnd, args, table);
123 ui_container_add(container, (W32Widget*)listview, &layout);
124
125
126
127 int numcolumns =
0;
128 if (table) {
129 if (args->model) {
130 listview->model = ui_model_copy(obj->ctx, args->model);
131 numcolumns = listview->model->columns;
132 }
else {
133 listview->model = ui_model_new(obj->ctx);
134 }
135 }
else {
136 UiModel *model = ui_model_new(obj->ctx);
137 ui_model_add_column(model,
UI_STRING,
"Test",
-1);
138 listview->model = model;
139 numcolumns =
1;
140 }
141
142
143 UiModel *model = listview->model;
144 for (
int i=
0;i<numcolumns;i++) {
145 LVCOLUMN col;
146 UiModelType type = model->types[i];
147 char *title = model->titles[i];
148 size_t titlelen = title ? strlen(title) :
0;
149 int size = model->columnsize[i];
150 switch (type) {
151 default: {
152 col.mask =
LVCF_TEXT |
LVCF_WIDTH;
153 col.pszText = title;
154 col.cx = size >
0 ? size : titlelen*
10+5;
155 break;
156 }
157 case UI_ICON: {
158 break;
159 }
160 }
161 ListView_InsertColumn(hwnd, i, &col);
162 }
163
164
165 if (listview->var) {
166 UiList *list = listview->var->value;
167 list->obj = listview;
168 list->update = ui_listview_update;
169 list->getselection = ui_listview_getselection;
170 list->setselection = ui_listview_setselection;
171
172 ui_listview_update(list,
-1);
173 }
174
175 return (W32Widget*)listview;
176 }
177
178 static UiListSelection listview_get_selection(UiListView *listview) {
179 UiListSelection sel = {
0,
NULL };
180 HWND hwnd = listview->widget.hwnd;
181
182 CX_ARRAY_DECLARE(
int, indices);
183 cx_array_initialize(indices,
8);
184
185 int index =
-1;
186 while ((index = ListView_GetNextItem(hwnd, index,
LVNI_SELECTED)) !=
-1) {
187 cx_array_simple_add(indices, index);
188 }
189
190 if (indices_size >
0) {
191 sel.rows = indices;
192 sel.count = indices_size;
193 }
194
195 return sel;
196 }
197
198
199 int ui_listview_eventproc(W32Widget *widget,
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam) {
200 UiListView *listview = (UiListView*)widget;
201 switch (uMsg) {
202 case WM_NOTIFY: {
203 LPNMHDR hdr = (
LPNMHDR)lParam;
204 switch (hdr->code) {
205 case LVN_ITEMCHANGED: {
206 LPNMLISTVIEW lv = (
LPNMLISTVIEW)lParam;
207 int row = lv->iItem;
208 if ((lv->uChanged &
LVIF_STATE) && (lv->uNewState &
LVIS_SELECTED) && listview->onselection) {
209 UiListSelection sel = listview_get_selection(listview);
210
211 UiEvent event;
212 event.obj = listview->obj;
213 event.window = listview->obj->window;
214 event.document = listview->obj->ctx->document;
215 event.eventdata = &sel;
216 event.eventdatatype =
UI_EVENT_DATA_LIST_SELECTION;
217 event.intval = row;
218 event.set = ui_get_setop();
219 listview->onselection(&event, listview->onselectiondata);
220
221 ui_listselection_free(sel);
222 }
223 break;
224 }
225 case LVN_ITEMACTIVATE: {
226 LPNMLISTVIEW lv = (
LPNMLISTVIEW)lParam;
227 int row = lv->iItem;
228 if (listview->onactivate) {
229 UiEvent event;
230 event.obj = listview->obj;
231 event.window = listview->obj->window;
232 event.document = listview->obj->ctx->document;
233 event.eventdata =
NULL;
234 event.eventdatatype =
UI_EVENT_DATA_LIST_ELM;
235 event.intval = row;
236 event.set = ui_get_setop();
237
238 if (listview->var) {
239 UiList *list = listview->var->value;
240 event.eventdata = list->get(list, row);
241 event.eventdatatype =
UI_EVENT_DATA_LIST_ELM;
242 }
243
244 listview->onactivate(&event, listview->onactivatedata);
245 }
246 break;
247 }
248 }
249 break;
250 }
251 }
252
253 return 0;
254 }
255
256 W32Size ui_listview_get_preferred_size(W32Widget *widget) {
257 UiListView *listview = (UiListView*)widget;
258 W32Size size;
259 size.width = listview->preferred_width;
260 size.height = listview->preferred_height;
261 return size;
262 }
263
264
265
266
267
268
269
270
271 static void insert_item(UiList *list,
int row,
void *elm) {
272 UiListView *listview = (UiListView*)list->obj;
273 HWND hwnd = listview->widget.hwnd;
274 UiModel *model = listview->model;
275
276 LVITEM item;
277 item.mask =
LVIF_TEXT;
278 item.iItem = row;
279 item.iSubItem =
0;
280 int idx =
-1;
281 for (
int col=
0;col<model->columns;col++) {
282 UiBool freeResult =
FALSE;
283
284
285 char *str = listview->getvalue(list, elm, row, col, listview->getvaluedata, &freeResult);
286 if (col ==
0) {
287 item.pszText = str;
288 idx = ListView_InsertItem(hwnd, &item);
289 }
else {
290 ListView_SetItemText(hwnd, idx, col, str);
291 }
292
293 if (freeResult) {
294 free(str);
295 }
296 }
297 }
298
299
300
301
302
303
304
305 void ui_listview_update(UiList *list,
int row) {
306 UiListView *listview = (UiListView*)list->obj;
307 HWND hwnd = listview->widget.hwnd;
308 UiModel *model = listview->model;
309 if (row <
0) {
310 ListView_DeleteAllItems(hwnd);
311 void *elm = list->first(list);
312 int row =
0;
313 while (elm) {
314 insert_item(list, row, elm);
315 elm = list->next(list);
316 row++;
317 }
318 }
else {
319 ListView_DeleteItem(hwnd, row);
320 void *elm = list->get(list, row);
321 insert_item(list, row, elm);
322 }
323
324
325 for (
int i=
0;i<model->columns;i++) {
326 ListView_SetColumnWidth(hwnd, i,
LVSCW_AUTOSIZE);
327 }
328 }
329
330 UiListSelection ui_listview_getselection(UiList *list) {
331 UiListView *listview = (UiListView*)list->obj;
332 return listview_get_selection(listview);
333 }
334
335 void ui_listview_setselection(UiList *list, UiListSelection selection) {
336
337 }
338
339
340 UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) {
341 return listview_create(obj, args,
FALSE);
342 }
343
344
345 UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
346 return listview_create(obj, args,
TRUE);
347 }
348
349
350
351
352 static W32WidgetClass dropdown_widget_class = {
353 .eventproc = ui_dropdown_eventproc,
354 .enable = w32_widget_default_enable,
355 .show = w32_widget_default_show,
356 .get_preferred_size = ui_dropdown_get_preferred_size,
357 .destroy = w32_widget_default_destroy
358 };
359
360 UIWIDGET ui_dropdown_create(UiObject *obj, UiListArgs *args) {
361 HINSTANCE hInstance = GetModuleHandle(
NULL);
362 UiContainerPrivate *container = ui_obj_container(obj);
363 HWND parent = ui_container_get_parent(container);
364 UiLayout layout =
UI_ARGS2LAYOUT(args);
365
366 HWND hwnd = CreateWindowEx(
367 WS_EX_CLIENTEDGE,
368 WC_COMBOBOX,
369 "",
370 WS_CHILD |
WS_VISIBLE |
WS_VSCROLL |
CBS_DROPDOWNLIST,
371 0,
0,
100,
100,
372 parent,
373 (
HMENU)
1337,
374 hInstance,
375 NULL);
376 ui_win32_set_ui_font(hwnd);
377
378 UiListView *dropdown = create_listview_widget(obj, &dropdown_widget_class, hwnd, args,
FALSE);
379 ui_container_add(container, (W32Widget*)dropdown, &layout);
380
381
382 if (dropdown->var) {
383 UiList *list = dropdown->var->value;
384 list->obj = dropdown;
385 list->update = ui_dropdown_update;
386 list->getselection = ui_dropdown_getselection;
387 list->setselection = ui_dropdown_setselection;
388
389 ui_dropdown_update(list,
-1);
390 }
391
392
393 return (W32Widget*)dropdown;
394 }
395
396 int ui_dropdown_eventproc(W32Widget *widget,
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam) {
397 return 0;
398 }
399
400 W32Size ui_dropdown_get_preferred_size(W32Widget *widget) {
401 W32Size size;
402 size.width =
200;
403 size.height =
30;
404 return size;
405 }
406
407 static void dropdown_insert_item(UiList *list,
int row,
void *elm) {
408 UiListView *listview = (UiListView*)list->obj;
409 HWND hwnd = listview->widget.hwnd;
410
411 UiBool freeResult =
FALSE;
412 char *str = listview->getvalue(list, elm, row,
0, listview->getvaluedata, &freeResult);
413 SendMessage(hwnd,
CB_ADDSTRING,
0, (
LPARAM)str);
414
415 if (freeResult) {
416 free(str);
417 }
418 }
419
420 void ui_dropdown_update(UiList *list,
int row) {
421 UiListView *listview = (UiListView*)list->obj;
422 HWND hwnd = listview->widget.hwnd;
423 if (row <
0) {
424 SendMessage(hwnd,
CB_RESETCONTENT,
0,
0);
425
426 void *elm = list->first(list);
427 int row =
0;
428 while (elm) {
429 dropdown_insert_item(list, row, elm);
430 elm = list->next(list);
431 row++;
432 }
433 }
else {
434 SendMessage(hwnd,
CB_DELETESTRING, row,
0);
435 void *elm = list->get(list, row);
436 dropdown_insert_item(list, row, elm);
437 }
438 }
439
440 UiListSelection ui_dropdown_getselection(UiList *list) {
441 UiListSelection sel = {
0,
NULL };
442 UiListView *listview = (UiListView*)list->obj;
443 int index = (
int)SendMessage(listview->widget.hwnd,
CB_GETCURSEL,
0,
0);
444 if (index >=
0) {
445 sel.rows = malloc(
sizeof(
int));
446 sel.rows[
0] = index;
447 sel.count =
1;
448 }
449 return sel;
450 }
451
452 void ui_dropdown_setselection(UiList *list, UiListSelection selection) {
453 UiListView *listview = (UiListView*)list->obj;
454 SendMessage(listview->widget.hwnd,
CB_SETCURSEL,
0,
0);
455 }
456