ui/gtk/list.c

changeset 853
380ec881faa2
parent 824
a0ea8f3aa6e8
child 855
37f8a9fa8251
equal deleted inserted replaced
852:a04cb4398034 853:380ec881faa2
2087 } 2087 }
2088 2088
2089 if(sublist->separator) { 2089 if(sublist->separator) {
2090 GtkWidget *separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); 2090 GtkWidget *separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
2091 gtk_list_box_row_set_header(row, separator); 2091 gtk_list_box_row_set_header(row, separator);
2092 } else if(sublist->header) { 2092 } else if(sublist->header && !listbox->header_is_item) {
2093 GtkWidget *header = gtk_label_new(sublist->header); 2093 GtkWidget *header = gtk_label_new(sublist->header);
2094 gtk_widget_set_halign(header, GTK_ALIGN_START); 2094 gtk_widget_set_halign(header, GTK_ALIGN_START);
2095 if(row == listbox->first_row) { 2095 if(row == listbox->first_row) {
2096 WIDGET_ADD_CSS_CLASS(header, "ui-listbox-header-first"); 2096 WIDGET_ADD_CSS_CLASS(header, "ui-listbox-header-first");
2097 } else { 2097 } else {
2175 ct->add(ct, scroll_area, &layout); 2175 ct->add(ct, scroll_area, &layout);
2176 2176
2177 UiListBox *uilistbox = malloc(sizeof(UiListBox)); 2177 UiListBox *uilistbox = malloc(sizeof(UiListBox));
2178 uilistbox->obj = obj; 2178 uilistbox->obj = obj;
2179 uilistbox->listbox = GTK_LIST_BOX(listbox); 2179 uilistbox->listbox = GTK_LIST_BOX(listbox);
2180 uilistbox->header_is_item = args->header_is_item;
2180 uilistbox->getvalue = args->getvalue; 2181 uilistbox->getvalue = args->getvalue;
2181 uilistbox->getvaluedata = args->getvaluedata; 2182 uilistbox->getvaluedata = args->getvaluedata;
2182 uilistbox->onactivate = args->onactivate; 2183 uilistbox->onactivate = args->onactivate;
2183 uilistbox->onactivatedata = args->onactivatedata; 2184 uilistbox->onactivatedata = args->onactivatedata;
2184 uilistbox->onbuttonclick = args->onbuttonclick; 2185 uilistbox->onbuttonclick = args->onbuttonclick;
2324 data->callback2(&event, data->userdata2); 2325 data->callback2(&event, data->userdata2);
2325 } 2326 }
2326 } 2327 }
2327 2328
2328 static void listbox_fill_row(UiListBox *listbox, GtkWidget *row, UiListBoxSubList *sublist, UiSubListItem *item, int index) { 2329 static void listbox_fill_row(UiListBox *listbox, GtkWidget *row, UiListBoxSubList *sublist, UiSubListItem *item, int index) {
2330 UiBool is_header = index < 0;
2331
2329 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); 2332 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
2330 if(item->icon) { 2333 if(item->icon) {
2331 GtkWidget *icon = ICON_IMAGE(item->icon); 2334 GtkWidget *icon = ICON_IMAGE(item->icon);
2332 BOX_ADD(hbox, icon); 2335 BOX_ADD(hbox, icon);
2333 } 2336 }
2334 GtkWidget *label = gtk_label_new(item->label); 2337 GtkWidget *label = gtk_label_new(item->label);
2338 if(is_header) {
2339 WIDGET_ADD_CSS_CLASS(label, "ui-listbox-header-row");
2340 }
2335 gtk_widget_set_halign(label, GTK_ALIGN_START); 2341 gtk_widget_set_halign(label, GTK_ALIGN_START);
2336 BOX_ADD_EXPAND(hbox, label); 2342 BOX_ADD_EXPAND(hbox, label);
2337 if(item->badge) { 2343 if(item->badge) {
2338 2344
2339 } 2345 }
2349 event->callback = listbox->onactivate; 2355 event->callback = listbox->onactivate;
2350 event->userdata = listbox->onactivatedata; 2356 event->userdata = listbox->onactivatedata;
2351 event->callback2 = listbox->onbuttonclick; 2357 event->callback2 = listbox->onbuttonclick;
2352 event->userdata2 = listbox->onbuttonclickdata; 2358 event->userdata2 = listbox->onbuttonclickdata;
2353 event->value0 = index; 2359 event->value0 = index;
2360
2361 // TODO: semi-memory leak when listbox_fill_row is called again for the same row
2362 // each row update will create a new UiEventDataExt object and a separate destroy handler
2354 2363
2355 g_signal_connect( 2364 g_signal_connect(
2356 row, 2365 row,
2357 "destroy", 2366 "destroy",
2358 G_CALLBACK(ui_destroy_userdata), 2367 G_CALLBACK(ui_destroy_userdata),
2388 ); 2397 );
2389 } 2398 }
2390 } 2399 }
2391 2400
2392 static void update_sublist_item(UiListBox *listbox, UiListBoxSubList *sublist, int index) { 2401 static void update_sublist_item(UiListBox *listbox, UiListBoxSubList *sublist, int index) {
2393 GtkListBoxRow *row = gtk_list_box_get_row_at_index(listbox->listbox, sublist->startpos + index); 2402 int header_row = listbox->header_is_item && sublist->header ? 1 : 0;
2403 GtkListBoxRow *row = gtk_list_box_get_row_at_index(listbox->listbox, sublist->startpos + index + header_row);
2394 if(!row) { 2404 if(!row) {
2395 return; 2405 return;
2396 } 2406 }
2397 UiList *list = sublist->var->value; 2407 UiList *list = sublist->var->value;
2398 if(!list) { 2408 if(!list) {
2436 UiList *list = sublist->var->value; 2446 UiList *list = sublist->var->value;
2437 if(!list) { 2447 if(!list) {
2438 return; 2448 return;
2439 } 2449 }
2440 2450
2441 size_t index = 0; 2451 int index = 0;
2442 void *elm = list->first(list); 2452 void *elm = list->first(list);
2443 2453 void *first = elm;
2444 if(!elm && sublist->header) { 2454
2455 if(sublist->header && !listbox->header_is_item && !elm) {
2445 // empty row for header 2456 // empty row for header
2446 GtkWidget *row = gtk_list_box_row_new(); 2457 GtkWidget *row = gtk_list_box_row_new();
2447 cxListAdd(sublist->widgets, row); 2458 cxListAdd(sublist->widgets, row);
2448 g_object_set_data(G_OBJECT(row), "ui_listbox", listbox); 2459 g_object_set_data(G_OBJECT(row), "ui_listbox", listbox);
2449 g_object_set_data(G_OBJECT(row), "ui_listbox_sublist", sublist); 2460 g_object_set_data(G_OBJECT(row), "ui_listbox_sublist", sublist);
2450 intptr_t rowindex = listbox_insert_index + index; 2461 intptr_t rowindex = listbox_insert_index + index;
2451 g_object_set_data(G_OBJECT(row), "ui_listbox_row_index", (gpointer)rowindex); 2462 //g_object_set_data(G_OBJECT(row), "ui_listbox_row_index", (gpointer)rowindex);
2452 gtk_list_box_insert(listbox->listbox, row, listbox_insert_index + index); 2463 gtk_list_box_insert(listbox->listbox, row, listbox_insert_index + index);
2453 sublist->numitems = 1; 2464 sublist->numitems = 1;
2454 return; 2465 return;
2466 }
2467
2468 int first_index = 0;
2469 int header_row = 0;
2470 if(listbox->header_is_item && sublist->header) {
2471 index = -1;
2472 first_index = -1;
2473 header_row = 1;
2474 elm = sublist->header;
2455 } 2475 }
2456 2476
2457 while(elm) { 2477 while(elm) {
2458 UiSubListItem item = { NULL, NULL, NULL, NULL, NULL, NULL }; 2478 UiSubListItem item = { NULL, NULL, NULL, NULL, NULL, NULL };
2459 if(listbox->getvalue) { 2479 if(listbox->getvalue) {
2462 item.label = strdup(elm); 2482 item.label = strdup(elm);
2463 } 2483 }
2464 2484
2465 // create listbox item 2485 // create listbox item
2466 GtkWidget *row = gtk_list_box_row_new(); 2486 GtkWidget *row = gtk_list_box_row_new();
2467 listbox_fill_row(listbox, row, sublist, &item, (int)index); 2487 listbox_fill_row(listbox, row, sublist, &item, index);
2468 if(index == 0) { 2488 if(index == first_index) {
2469 // first row in the sublist, set ui_listbox data to the row 2489 // first row in the sublist, set ui_listbox data to the row
2470 // which is then used by the headerfunc 2490 // which is then used by the headerfunc
2471 g_object_set_data(G_OBJECT(row), "ui_listbox", listbox); 2491 g_object_set_data(G_OBJECT(row), "ui_listbox", listbox);
2472 g_object_set_data(G_OBJECT(row), "ui_listbox_sublist", sublist); 2492 g_object_set_data(G_OBJECT(row), "ui_listbox_sublist", sublist);
2473 2493
2475 // first row in the GtkListBox 2495 // first row in the GtkListBox
2476 listbox->first_row = GTK_LIST_BOX_ROW(row); 2496 listbox->first_row = GTK_LIST_BOX_ROW(row);
2477 } 2497 }
2478 } 2498 }
2479 intptr_t rowindex = listbox_insert_index + index; 2499 intptr_t rowindex = listbox_insert_index + index;
2480 g_object_set_data(G_OBJECT(row), "ui_listbox_row_index", (gpointer)rowindex); 2500 //g_object_set_data(G_OBJECT(row), "ui_listbox_row_index", (gpointer)rowindex);
2481 gtk_list_box_insert(listbox->listbox, row, listbox_insert_index + index); 2501 gtk_list_box_insert(listbox->listbox, row, listbox_insert_index + index + header_row);
2482 cxListAdd(sublist->widgets, row); 2502 cxListAdd(sublist->widgets, row);
2483 2503
2484 // cleanup 2504 // cleanup
2485 free(item.label); 2505 free(item.label);
2486 free(item.icon); 2506 free(item.icon);
2487 free(item.button_label); 2507 free(item.button_label);
2488 free(item.button_icon); 2508 free(item.button_icon);
2489 free(item.badge); 2509 free(item.badge);
2490 2510
2491 // next row 2511 // next row
2492 elm = list->next(list); 2512 elm = index >= 0 ? list->next(list) : first;
2493 index++; 2513 index++;
2494 } 2514 }
2495 2515
2496 sublist->numitems = cxListSize(sublist->widgets); 2516 sublist->numitems = cxListSize(sublist->widgets);
2497 } 2517 }
2521 UiSubListEventData eventdata; 2541 UiSubListEventData eventdata;
2522 eventdata.list = sublist->var->value; 2542 eventdata.list = sublist->var->value;
2523 eventdata.sublist_index = sublist->index; 2543 eventdata.sublist_index = sublist->index;
2524 eventdata.row_index = data->value0; 2544 eventdata.row_index = data->value0;
2525 eventdata.sublist_userdata = sublist->userdata; 2545 eventdata.sublist_userdata = sublist->userdata;
2526 eventdata.row_data = eventdata.list->get(eventdata.list, eventdata.row_index); 2546 eventdata.row_data = eventdata.row_index >= 0 ? eventdata.list->get(eventdata.list, eventdata.row_index) : NULL;
2527 eventdata.event_data = data->customdata2; 2547 eventdata.event_data = data->customdata2;
2528 2548
2529 UiEvent event; 2549 UiEvent event;
2530 event.obj = data->obj; 2550 event.obj = data->obj;
2531 event.window = event.obj->window; 2551 event.window = event.obj->window;

mercurial