ui/win32/list.c

changeset 919
d9018dcd4e2d
parent 918
7d3dd5aacfda
child 936
d40a72210be8
equal deleted inserted replaced
918:7d3dd5aacfda 919:d9018dcd4e2d
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include <cx/array_list.h>
33
29 #include "list.h" 34 #include "list.h"
30 #include "container.h" 35 #include "container.h"
31 36
32 37
33 38
50 55
51 static void* null_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) { 56 static void* null_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
52 return NULL; 57 return NULL;
53 } 58 }
54 59
55 60 /*
61 * Creates an UiListView widget object and initializes it from the UiListArgs
62 */
56 static UiListView* create_listview_widget(UiObject *obj, HWND hwnd, UiListArgs *args, UiBool table) { 63 static UiListView* create_listview_widget(UiObject *obj, HWND hwnd, UiListArgs *args, UiBool table) {
57 UiListView *listview = w32_widget_create(&listview_widget_class, hwnd, sizeof(UiListView)); 64 UiListView *listview = w32_widget_create(&listview_widget_class, hwnd, sizeof(UiListView));
58 listview->widget.hwnd = hwnd; 65 listview->widget.hwnd = hwnd;
59 listview->preferred_width = args->width ? args->width : 300; 66 listview->obj = obj;
67 listview->preferred_width = args->width ? args->width : 300; // 300: default width/height
60 listview->preferred_height = args->height ? args->height : 300; 68 listview->preferred_height = args->height ? args->height : 300;
61 listview->onactivate = args->onactivate; 69 listview->onactivate = args->onactivate;
62 listview->onactivatedata = args->onactivatedata; 70 listview->onactivatedata = args->onactivatedata;
63 listview->onselection = args->onselection; 71 listview->onselection = args->onselection;
64 listview->onselectiondata = args->onselectiondata; 72 listview->onselectiondata = args->onselectiondata;
68 listview->ondragcompletedata = args->ondragcompletedata; 76 listview->ondragcompletedata = args->ondragcompletedata;
69 listview->ondrop = args->ondrop; 77 listview->ondrop = args->ondrop;
70 listview->ondropdata = args->ondropdata; 78 listview->ondropdata = args->ondropdata;
71 listview->istable = table; 79 listview->istable = table;
72 80
81 // convert ui_getvaluefunc into ui_getvaluefunc2 if necessary
73 ui_getvaluefunc2 getvalue = args->getvalue2; 82 ui_getvaluefunc2 getvalue = args->getvalue2;
74 void *getvaluedata = args->getvalue2data; 83 void *getvaluedata = args->getvalue2data;
75 if(!getvalue) { 84 if(!getvalue) {
76 if(args->getvalue) { 85 if(args->getvalue) {
77 getvalue = getvalue_wrapper; 86 getvalue = getvalue_wrapper;
103 parent, 112 parent,
104 (HMENU)1337, 113 (HMENU)1337,
105 hInstance, 114 hInstance,
106 NULL); 115 NULL);
107 ui_win32_set_ui_font(hwnd); 116 ui_win32_set_ui_font(hwnd);
108
109 ListView_SetExtendedListViewStyle( 117 ListView_SetExtendedListViewStyle(
110 hwnd, 118 hwnd,
111 LVS_EX_FULLROWSELECT //| LVS_EX_GRIDLINES 119 LVS_EX_FULLROWSELECT //| LVS_EX_GRIDLINES
112 ); 120 );
113 121
114 UiListView *listview = create_listview_widget(obj, hwnd, args, table); 122 UiListView *listview = create_listview_widget(obj, hwnd, args, table);
115 ui_container_add(container, (W32Widget*)listview, &layout); 123 ui_container_add(container, (W32Widget*)listview, &layout);
116 124
117 // model 125 // init list model
126 // always initialize listview->model
118 int numcolumns = 0; 127 int numcolumns = 0;
119 if (table) { 128 if (table) {
120 if (args->model) { 129 if (args->model) {
121 listview->model = ui_model_copy(obj->ctx, args->model); 130 listview->model = ui_model_copy(obj->ctx, args->model);
122 numcolumns = listview->model->columns; 131 numcolumns = listview->model->columns;
128 ui_model_add_column(obj->ctx, model, UI_STRING, "Test", -1); 137 ui_model_add_column(obj->ctx, model, UI_STRING, "Test", -1);
129 listview->model = model; 138 listview->model = model;
130 numcolumns = 1; 139 numcolumns = 1;
131 } 140 }
132 141
142 // create columns
133 UiModel *model = listview->model; 143 UiModel *model = listview->model;
134 for (int i=0;i<numcolumns;i++) { 144 for (int i=0;i<numcolumns;i++) {
135 LVCOLUMN col; 145 LVCOLUMN col;
136 UiModelType type = model->types[i]; 146 UiModelType type = model->types[i];
137 char *title = model->titles[i]; 147 char *title = model->titles[i];
149 } 159 }
150 } 160 }
151 ListView_InsertColumn(hwnd, i, &col); 161 ListView_InsertColumn(hwnd, i, &col);
152 } 162 }
153 163
164 // bind the listview to the provided UiList
154 if (listview->var) { 165 if (listview->var) {
155 UiList *list = listview->var->value; 166 UiList *list = listview->var->value;
156 list->obj = listview; 167 list->obj = listview;
157 list->update = ui_listview_update; 168 list->update = ui_listview_update;
158 list->getselection = ui_listview_getselection; 169 list->getselection = ui_listview_getselection;
162 } 173 }
163 174
164 return (W32Widget*)listview; 175 return (W32Widget*)listview;
165 } 176 }
166 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 // listview class event proc
167 void ui_listview_eventproc(W32Widget *widget, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 199 void ui_listview_eventproc(W32Widget *widget, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
168 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 }
169 } 252 }
170 253
171 W32Size ui_listview_get_preferred_size(W32Widget *widget) { 254 W32Size ui_listview_get_preferred_size(W32Widget *widget) {
172 UiListView *listview = (UiListView*)widget; 255 UiListView *listview = (UiListView*)widget;
173 W32Size size; 256 W32Size size;
174 size.width = listview->preferred_width; 257 size.width = listview->preferred_width;
175 size.height = listview->preferred_height; 258 size.height = listview->preferred_height;
176 return size; 259 return size;
177 } 260 }
178 261
262 /*
263 * Creates and inserts an LVITEM
264 *
265 * list: An UiList bound to an UiListView
266 * row: row index
267 * elm: list element (same as list->get(list, row))
268 */
179 static void insert_item(UiList *list, int row, void *elm) { 269 static void insert_item(UiList *list, int row, void *elm) {
180 UiListView *listview = (UiListView*)list->obj; 270 UiListView *listview = (UiListView*)list->obj;
181 HWND hwnd = listview->widget.hwnd; 271 HWND hwnd = listview->widget.hwnd;
182 UiModel *model = listview->model; 272 UiModel *model = listview->model;
183 273
186 item.iItem = row; 276 item.iItem = row;
187 item.iSubItem = 0; 277 item.iSubItem = 0;
188 int idx = -1; 278 int idx = -1;
189 for (int col=0;col<model->columns;col++) { 279 for (int col=0;col<model->columns;col++) {
190 UiBool freeResult = FALSE; 280 UiBool freeResult = FALSE;
281 // convert the list element to a value, that can be displayed in the list view
282 // TODO: handle all model types
191 char *str = listview->getvalue(list, elm, row, col, listview->getvaluedata, &freeResult); 283 char *str = listview->getvalue(list, elm, row, col, listview->getvaluedata, &freeResult);
192 if (col == 0) { 284 if (col == 0) {
193 item.pszText = str; 285 item.pszText = str;
194 idx = ListView_InsertItem(hwnd, &item); 286 idx = ListView_InsertItem(hwnd, &item);
195 } else { 287 } else {
200 free(str); 292 free(str);
201 } 293 }
202 } 294 }
203 } 295 }
204 296
297 /*
298 * UiList->update function
299 *
300 * Updates one or all rows
301 * row: list index or -1 for updating all rows
302 */
205 void ui_listview_update(UiList *list, int row) { 303 void ui_listview_update(UiList *list, int row) {
206 UiListView *listview = (UiListView*)list->obj; 304 UiListView *listview = (UiListView*)list->obj;
207 HWND hwnd = listview->widget.hwnd; 305 HWND hwnd = listview->widget.hwnd;
208 UiModel *model = listview->model; 306 UiModel *model = listview->model;
209 if (row < 0) { 307 if (row < 0) {
219 ListView_DeleteItem(hwnd, row); 317 ListView_DeleteItem(hwnd, row);
220 void *elm = list->get(list, row); 318 void *elm = list->get(list, row);
221 insert_item(list, row, elm); 319 insert_item(list, row, elm);
222 } 320 }
223 321
322 // re-adjust all columns
224 for (int i=0;i<model->columns;i++) { 323 for (int i=0;i<model->columns;i++) {
225 ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE); 324 ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE);
226 } 325 }
227 } 326 }
228 327
229 UiListSelection ui_listview_getselection(UiList *list) { 328 UiListSelection ui_listview_getselection(UiList *list) {
230 UiListSelection sel = { 0, NULL }; 329 UiListView *listview = (UiListView*)list->obj;
231 return sel; 330 return listview_get_selection(listview);
232 } 331 }
233 332
234 void ui_listview_setselection(UiList *list, UiListSelection selection) { 333 void ui_listview_setselection(UiList *list, UiListSelection selection) {
235 334
236 } 335 }
237 336
337 // public API
238 UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) { 338 UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) {
239 return listview_create(obj, args, FALSE); 339 return listview_create(obj, args, FALSE);
240 } 340 }
241 341
342 // public API
242 UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) { 343 UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
243 return listview_create(obj, args, TRUE); 344 return listview_create(obj, args, TRUE);
244 } 345 }

mercurial