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_impl;
170 list->setselection = ui_listview_setselection_impl;
171
172 ui_listview_update(list,
-1);
173 }
else if (!table && args->static_elements && args->static_nelm >
0) {
174 char **static_elements = args->static_elements;
175 size_t static_nelm = args->static_nelm;
176 LVITEM item;
177 item.mask =
LVIF_TEXT;
178 item.iSubItem =
0;
179 for (
int i=
0;i<static_nelm;i++) {
180 item.iItem = i;
181 item.pszText = static_elements[i];
182 ListView_InsertItem(hwnd, &item);
183 }
184 listview->getvalue = strmodel_getvalue;
185 listview->getvaluedata =
NULL;
186 }
187
188 return (W32Widget*)listview;
189 }
190
191 static UiListSelection listview_get_selection2(
HWND hwnd) {
192 UiListSelection sel = {
0,
NULL };
193
194 CX_ARRAY_DECLARE(
int, indices);
195 cx_array_initialize(indices,
8);
196
197 int index =
-1;
198 while ((index = ListView_GetNextItem(hwnd, index,
LVNI_SELECTED)) !=
-1) {
199 cx_array_simple_add(indices, index);
200 }
201
202 if (indices_size >
0) {
203 sel.rows = indices;
204 sel.count = indices_size;
205 }
206
207 return sel;
208 }
209
210 static UiListSelection listview_get_selection(UiListView *listview) {
211 HWND hwnd = listview->widget.hwnd;
212 return listview_get_selection2(hwnd);
213 }
214
215
216 int ui_listview_eventproc(W32Widget *widget,
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam) {
217 UiListView *listview = (UiListView*)widget;
218 switch (uMsg) {
219 case WM_NOTIFY: {
220 LPNMHDR hdr = (
LPNMHDR)lParam;
221 switch (hdr->code) {
222 case LVN_ITEMCHANGED: {
223 LPNMLISTVIEW lv = (
LPNMLISTVIEW)lParam;
224 int row = lv->iItem;
225 if ((lv->uChanged &
LVIF_STATE) && (lv->uNewState &
LVIS_SELECTED) && listview->onselection) {
226 UiListSelection sel = listview_get_selection(listview);
227
228 UiEvent event;
229 event.obj = listview->obj;
230 event.window = listview->obj->window;
231 event.document = listview->obj->ctx->document;
232 event.eventdata = &sel;
233 event.eventdatatype =
UI_EVENT_DATA_LIST_SELECTION;
234 event.intval = row;
235 event.set = ui_get_setop();
236 listview->onselection(&event, listview->onselectiondata);
237
238 ui_listselection_free(sel);
239 }
240 break;
241 }
242 case LVN_ITEMACTIVATE: {
243 LPNMLISTVIEW lv = (
LPNMLISTVIEW)lParam;
244 int row = lv->iItem;
245 if (listview->onactivate) {
246 UiEvent event;
247 event.obj = listview->obj;
248 event.window = listview->obj->window;
249 event.document = listview->obj->ctx->document;
250 event.eventdata =
NULL;
251 event.eventdatatype =
UI_EVENT_DATA_LIST_ELM;
252 event.intval = row;
253 event.set = ui_get_setop();
254
255 if (listview->var) {
256 UiList *list = listview->var->value;
257 event.eventdata = list->get(list, row);
258 event.eventdatatype =
UI_EVENT_DATA_LIST_ELM;
259 }
260
261 listview->onactivate(&event, listview->onactivatedata);
262 }
263 break;
264 }
265 }
266 break;
267 }
268 }
269
270 return 0;
271 }
272
273 W32Size ui_listview_get_preferred_size(W32Widget *widget) {
274 UiListView *listview = (UiListView*)widget;
275 W32Size size;
276 size.width = listview->preferred_width;
277 size.height = listview->preferred_height;
278 return size;
279 }
280
281
282
283
284
285
286
287
288 static void insert_item(UiList *list,
int row,
void *elm) {
289 UiListView *listview = (UiListView*)list->obj;
290 HWND hwnd = listview->widget.hwnd;
291 UiModel *model = listview->model;
292
293 LVITEM item;
294 item.mask =
LVIF_TEXT;
295 item.iItem = row;
296 item.iSubItem =
0;
297 int idx =
-1;
298 for (
int col=
0;col<model->columns;col++) {
299 UiBool freeResult =
FALSE;
300
301
302 char *str = listview->getvalue(list, elm, row, col, listview->getvaluedata, &freeResult);
303 if (col ==
0) {
304 item.pszText = str;
305 idx = ListView_InsertItem(hwnd, &item);
306 }
else {
307 ListView_SetItemText(hwnd, idx, col, str);
308 }
309
310 if (freeResult) {
311 free(str);
312 }
313 }
314 }
315
316
317
318
319
320
321
322 void ui_listview_update(UiList *list,
int row) {
323 UiListView *listview = (UiListView*)list->obj;
324 HWND hwnd = listview->widget.hwnd;
325 UiModel *model = listview->model;
326 if (row <
0) {
327 ListView_DeleteAllItems(hwnd);
328 void *elm = list->first(list);
329 int row =
0;
330 while (elm) {
331 insert_item(list, row, elm);
332 elm = list->next(list);
333 row++;
334 }
335 }
else {
336 ListView_DeleteItem(hwnd, row);
337 void *elm = list->get(list, row);
338 insert_item(list, row, elm);
339 }
340
341
342 for (
int i=
0;i<model->columns;i++) {
343 ListView_SetColumnWidth(hwnd, i,
LVSCW_AUTOSIZE);
344 }
345 }
346
347 UiListSelection ui_listview_getselection_impl(UiList *list) {
348 UiListView *listview = (UiListView*)list->obj;
349 return listview_get_selection(listview);
350 }
351
352 void ui_listview_setselection_impl(UiList *list, UiListSelection selection) {
353
354 }
355
356
357 UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) {
358 return listview_create(obj, args,
FALSE);
359 }
360
361
362 UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
363 return listview_create(obj, args,
TRUE);
364 }
365
366 void ui_listview_select(
UIWIDGET listview,
int index) {
367
368 }
369
370 int ui_listview_selection(
UIWIDGET listview) {
371 W32Widget *w = (W32Widget*)listview;
372 UiListSelection sel = listview_get_selection2(w->hwnd);
373 int index =
-1;
374 if (sel.count >
0) {
375 index = sel.rows[
0];
376 }
377 free(sel.rows);
378 return index;
379 }
380
381
382
383 static W32WidgetClass dropdown_widget_class = {
384 .eventproc = ui_dropdown_eventproc,
385 .enable = w32_widget_default_enable,
386 .show = w32_widget_default_show,
387 .get_preferred_size = ui_dropdown_get_preferred_size,
388 .destroy = w32_widget_default_destroy
389 };
390
391 UIWIDGET ui_dropdown_create(UiObject *obj, UiListArgs *args) {
392 HINSTANCE hInstance = GetModuleHandle(
NULL);
393 UiContainerPrivate *container = ui_obj_container(obj);
394 HWND parent = ui_container_get_parent(container);
395 UiLayout layout =
UI_ARGS2LAYOUT(args);
396
397 HWND hwnd = CreateWindowEx(
398 WS_EX_CLIENTEDGE,
399 WC_COMBOBOX,
400 "",
401 WS_CHILD |
WS_VISIBLE |
WS_VSCROLL |
CBS_DROPDOWNLIST,
402 0,
0,
100,
100,
403 parent,
404 (
HMENU)
1337,
405 hInstance,
406 NULL);
407 ui_win32_set_ui_font(hwnd);
408
409 UiListView *dropdown = create_listview_widget(obj, &dropdown_widget_class, hwnd, args,
FALSE);
410 ui_container_add(container, (W32Widget*)dropdown, &layout);
411
412
413 if (dropdown->var) {
414 UiList *list = dropdown->var->value;
415 list->obj = dropdown;
416 list->update = ui_dropdown_update;
417 list->getselection = ui_dropdown_getselection_impl;
418 list->setselection = ui_dropdown_setselection_impl;
419
420 ui_dropdown_update(list,
-1);
421 }
else if (args->static_elements && args->static_nelm >
0) {
422 char **static_elements = args->static_elements;
423 size_t static_nelm = args->static_nelm;
424 for (
int i=
0;i<static_nelm;i++) {
425 SendMessage(hwnd,
CB_ADDSTRING,
0, (
LPARAM)static_elements[i]);
426 }
427 dropdown->getvalue = strmodel_getvalue;
428 dropdown->getvaluedata =
NULL;
429 }
430
431 return (W32Widget*)dropdown;
432 }
433
434 int ui_dropdown_eventproc(W32Widget *widget,
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam) {
435 return 0;
436 }
437
438 W32Size ui_dropdown_get_preferred_size(W32Widget *widget) {
439 W32Size size;
440 size.width =
200;
441 size.height =
30;
442 return size;
443 }
444
445 static void dropdown_insert_item(UiList *list,
int row,
void *elm) {
446 UiListView *listview = (UiListView*)list->obj;
447 HWND hwnd = listview->widget.hwnd;
448
449 UiBool freeResult =
FALSE;
450 char *str = listview->getvalue(list, elm, row,
0, listview->getvaluedata, &freeResult);
451 SendMessage(hwnd,
CB_ADDSTRING,
0, (
LPARAM)str);
452
453 if (freeResult) {
454 free(str);
455 }
456 }
457
458 void ui_dropdown_update(UiList *list,
int row) {
459 UiListView *listview = (UiListView*)list->obj;
460 HWND hwnd = listview->widget.hwnd;
461 if (row <
0) {
462 SendMessage(hwnd,
CB_RESETCONTENT,
0,
0);
463
464 void *elm = list->first(list);
465 int row =
0;
466 while (elm) {
467 dropdown_insert_item(list, row, elm);
468 elm = list->next(list);
469 row++;
470 }
471 }
else {
472 SendMessage(hwnd,
CB_DELETESTRING, row,
0);
473 void *elm = list->get(list, row);
474 dropdown_insert_item(list, row, elm);
475 }
476 }
477
478 UiListSelection ui_dropdown_getselection_impl(UiList *list) {
479 UiListSelection sel = {
0,
NULL };
480 UiListView *listview = (UiListView*)list->obj;
481 int index = (
int)SendMessage(listview->widget.hwnd,
CB_GETCURSEL,
0,
0);
482 if (index >=
0) {
483 sel.rows = malloc(
sizeof(
int));
484 sel.rows[
0] = index;
485 sel.count =
1;
486 }
487 return sel;
488 }
489
490 void ui_dropdown_setselection_impl(UiList *list, UiListSelection selection) {
491 UiListView *listview = (UiListView*)list->obj;
492 SendMessage(listview->widget.hwnd,
CB_SETCURSEL,
0,
0);
493 }
494
495 void ui_dropdown_select(
UIWIDGET dropdown,
int index) {
496 SendMessage(dropdown->hwnd,
CB_SETCURSEL,
0,
0);
497 }
498
499 int ui_dropdown_selection(
UIWIDGET dropdown) {
500 return SendMessage(dropdown->hwnd,
CB_GETCURSEL,
0,
0);
501 }
502