diff --git a/demo/common/overview.c b/demo/common/overview.c index 45458543..279fe188 100644 --- a/demo/common/overview.c +++ b/demo/common/overview.c @@ -18,7 +18,7 @@ overview(struct nk_context *ctx) #ifdef INCLUDE_STYLE /* styles */ - static const char* themes[] = {"Black", "White", "Red", "Blue", "Dark", "Dracula", + static const char* themes[] = {"Black", "White", "Red", "Blue", "Dark", "Dracula", "Catppucin Latte", "Catppucin Frappe", "Catppucin Macchiato", "Catppucin Mocha"}; static int current_theme = 0; #endif @@ -584,6 +584,50 @@ overview(struct nk_context *ctx) nk_combo_end(ctx); } } + { + /* Combobox from array of struct */ + static int sel=0; + struct student { + int id; + char* name; + int age; + char* major; + }; + + static struct student students[3] = { + { + .id = 1, + .name = "Mike", + .age = 20, + .major = "CS" + }, + { + .id = 2, + .name = "Jim", + .age = 19, + .major = "Maths" + }, + { + .id = 3, + .name = "Julia", + .age = 20, + .major = "Biology" + } + }; + sel = nk_combo_from_struct_array(ctx, &students, 3, + sizeof(struct student), + offsetof(struct student, name), + sel, 15, nk_vec2(200,200)); + if(sel>0){ + nk_layout_row_static(ctx, 30,300, 2); + nk_labelf(ctx, NK_TEXT_LEFT, "id:%d | name:%s | age:%d | major:%s", + students[sel].id, + students[sel].name, + students[sel].age, + students[sel].major + ); + } + } nk_tree_pop(ctx); } diff --git a/nuklear.h b/nuklear.h index 8c3fea99..72ff9158 100644 --- a/nuklear.h +++ b/nuklear.h @@ -3765,7 +3765,8 @@ NK_API int nk_combo(struct nk_context*, const char *const *items, int count, int NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size); NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size); NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size); -NK_API void nk_combobox(struct nk_context*, const char *const *items, int count, int *selected, int item_height, struct nk_vec2 size); +NK_API int nk_combo_from_struct_array(struct nk_context *ctx, const void *items, int count, int item_sz, int stride, int selected, int item_height, struct nk_vec2 size); +NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size); NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size); NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int *selected, int count, int item_height, struct nk_vec2 size); NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size); @@ -30504,6 +30505,41 @@ nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const c nk_combo_end(ctx); } return selected; } + + +NK_API int nk_combo_from_struct_array(struct nk_context *ctx, const void *items, int count, int item_sz, int stride, int selected, int item_height, struct nk_vec2 size) +{ + int i = 0; + int max_height; + struct nk_vec2 item_spacing; + struct nk_vec2 window_padding; + char* sel; + char* name; + NK_ASSERT(ctx); + NK_ASSERT(items); + NK_ASSERT(ctx->current); + if (!ctx || !items ||!count) + return selected; + + item_spacing = ctx->style.window.spacing; + window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); + max_height = count * item_height + count * (int)item_spacing.y; + max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; + size.y = NK_MIN(size.y, (float)max_height); + sel = *(char**)((char*)items + (item_sz*selected) + stride); + if (nk_combo_begin_label(ctx, sel, size)) { + nk_layout_row_dynamic(ctx, (float)item_height, 1); + for (i = 0; i < count; ++i) { + name = *(char**)((char*)items + stride); + if (nk_combo_item_label(ctx, name, NK_TEXT_LEFT)) + selected = i; + items = (char*)items + item_sz; + } + nk_combo_end(ctx); + } + return selected; +} + NK_API void nk_combobox(struct nk_context *ctx, const char *const *items, int count, int *selected, int item_height, struct nk_vec2 size) diff --git a/src/nuklear.h b/src/nuklear.h index a76d384c..eac73c93 100644 --- a/src/nuklear.h +++ b/src/nuklear.h @@ -3543,7 +3543,28 @@ NK_API int nk_combo(struct nk_context*, const char *const *items, int count, int NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size); NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size); NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size); -NK_API void nk_combobox(struct nk_context*, const char *const *items, int count, int *selected, int item_height, struct nk_vec2 size); +/* + * \brief create a combobox from an array of strct containing a `char*` member that we use as a name + * this avoids the need to have two arrays (one being for the array of structs, and one for the names) + * + * \details + * ```c + * int nk_combo_from_struct_array(struct nk_context *ctx, const void *items, int count, int item_sz, int stride, int selected, int item_height, struct nk_vec2 size); + * ``` + * + * \param[in] ctx | Must point to an previously initialized `nk_context` struct after calling a layouting function + * \param[in] items | `void` pointer to a list of structures + * \param[in] count | Number of elements in the array of structs + * \param[in] items_sz | Size of an individual structure. + * \param[in] stride | Stride to a char* member inside the structure + * \param[in] selected | the index of the current selected item + * \param[in] item_height | Height of the element + * \param[in] size | Size of the element listing, must point to a `nk_vec2` structure + * + * \returns the index of the newly selected item. + */ +NK_API int nk_combo_from_struct_array(struct nk_context *ctx, const void *items, int count, int item_sz, int stride, int selected, int item_height, struct nk_vec2 size); +NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size); NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size); NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int *selected, int count, int item_height, struct nk_vec2 size); NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size); diff --git a/src/nuklear_combo.c b/src/nuklear_combo.c index 8cfc6da3..d24ddfcb 100644 --- a/src/nuklear_combo.c +++ b/src/nuklear_combo.c @@ -819,6 +819,43 @@ nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const c nk_combo_end(ctx); } return selected; } + + +NK_API int nk_combo_from_struct_array(struct nk_context *ctx, const void *items, int count, int item_sz, int stride, int selected, int item_height, struct nk_vec2 size) +{ + int i = 0; + int max_height; + struct nk_vec2 item_spacing; + struct nk_vec2 window_padding; + char* sel; + char* name; + NK_ASSERT(ctx); + NK_ASSERT(items); + NK_ASSERT(ctx->current); + if (!ctx || !items ||!count) + return selected; + + item_spacing = ctx->style.window.spacing; + window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); + max_height = count * item_height + count * (int)item_spacing.y; + max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; + size.y = NK_MIN(size.y, (float)max_height); + sel = *(char**)((char*)items + (item_sz*selected) + stride); + if (nk_combo_begin_label(ctx, sel, size)) { + nk_layout_row_dynamic(ctx, (float)item_height, 1); + for (i = 0; i < count; ++i) { + name = *(char**)((char*)items + stride); + if(!name) + name = ""; + if (nk_combo_item_label(ctx, name, NK_TEXT_LEFT)) + selected = i; + items = (char*)items + item_sz; + } + nk_combo_end(ctx); + } + return selected; +} + NK_API void nk_combobox(struct nk_context *ctx, const char *const *items, int count, int *selected, int item_height, struct nk_vec2 size)