| 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; |