NK_API int nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size) { int i; int max_height; struct nk_vec2 item_spacing; struct nk_vec2 window_padding; const char *item; NK_ASSERT(ctx); NK_ASSERT(item_getter); if (!ctx || !item_getter) return selected; /* calculate popup window */ 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); item_getter(userdata, selected, &item); if (nk_combo_begin_label(ctx, item, size)) { nk_layout_row_dynamic(ctx, (float)item_height, 1); for (i = 0; i < count; ++i) { item_getter(userdata, i, &item); if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT)) selected = i; } nk_combo_end(ctx); } return selected; }
NK_API int nk_combo(struct nk_context *ctx, const char **items, int count, 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; 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); if (nk_combo_begin_label(ctx, items[selected], size)) { nk_layout_row_dynamic(ctx, (float)item_height, 1); for (i = 0; i < count; ++i) { if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT)) selected = i; } nk_combo_end(ctx); } return selected; }
NK_API int nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size) { int i; int max_height; struct nk_vec2 item_spacing; struct nk_vec2 window_padding; const char *current_item; const char *iter; int length = 0; NK_ASSERT(ctx); NK_ASSERT(items_separated_by_separator); if (!ctx || !items_separated_by_separator) return selected; /* calculate popup window */ 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); /* find selected item */ current_item = items_separated_by_separator; for (i = 0; i < count; ++i) { iter = current_item; while (*iter && *iter != separator) iter++; length = (int)(iter - current_item); if (i == selected) break; current_item = iter + 1; } if (nk_combo_begin_text(ctx, current_item, length, size)) { current_item = items_separated_by_separator; nk_layout_row_dynamic(ctx, (float)item_height, 1); for (i = 0; i < count; ++i) { iter = current_item; while (*iter && *iter != separator) iter++; length = (int)(iter - current_item); if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT)) selected = i; current_item = current_item + length + 1; } nk_combo_end(ctx); } return selected; }
static void hat_widget(struct nk_context* nk, unsigned char state) { float radius; struct nk_rect area; struct nk_vec2 center; if (nk_widget(&area, nk) != NK_WIDGET_VALID) return; center = nk_vec2(area.x + area.w / 2.f, area.y + area.h / 2.f); radius = NK_MIN(area.w, area.h) / 2.f; nk_stroke_circle(nk_window_get_canvas(nk), nk_rect(center.x - radius, center.y - radius, radius * 2.f, radius * 2.f), 1.f, nk_rgb(175, 175, 175)); if (state) { const float angles[] = { 0.f, 0.f, NK_PI * 1.5f, NK_PI * 1.75f, NK_PI, 0.f, NK_PI * 1.25f, 0.f, NK_PI * 0.5f, NK_PI * 0.25f, 0.f, 0.f, NK_PI * 0.75f, 0.f, }; const float cosa = nk_cos(angles[state]); const float sina = nk_sin(angles[state]); const struct nk_vec2 p0 = nk_vec2(0.f, -radius); const struct nk_vec2 p1 = nk_vec2( radius / 2.f, -radius / 3.f); const struct nk_vec2 p2 = nk_vec2(-radius / 2.f, -radius / 3.f); nk_fill_triangle(nk_window_get_canvas(nk), center.x + cosa * p0.x + sina * p0.y, center.y + cosa * p0.y - sina * p0.x, center.x + cosa * p1.x + sina * p1.y, center.y + cosa * p1.y - sina * p1.x, center.x + cosa * p2.x + sina * p2.y, center.y + cosa * p2.y - sina * p2.x, nk_rgb(175, 175, 175)); } }
/* =============================================================== * * SCROLLBAR * * ===============================================================*/ NK_LIB float nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, int has_scrolling, const struct nk_rect *scroll, const struct nk_rect *cursor, const struct nk_rect *empty0, const struct nk_rect *empty1, float scroll_offset, float target, float scroll_step, enum nk_orientation o) { nk_flags ws = 0; int left_mouse_down; int left_mouse_clicked; int left_mouse_click_in_cursor; float scroll_delta; nk_widget_state_reset(state); if (!in) return scroll_offset; left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked; left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, *cursor, nk_true); if (nk_input_is_mouse_hovering_rect(in, *scroll)) *state = NK_WIDGET_STATE_HOVERED; scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x; if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) { /* update cursor by mouse dragging */ float pixel, delta; *state = NK_WIDGET_STATE_ACTIVE; if (o == NK_VERTICAL) { float cursor_y; pixel = in->mouse.delta.y; delta = (pixel / scroll->h) * target; scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h); cursor_y = scroll->y + ((scroll_offset/target) * scroll->h); in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f; } else { float cursor_x; pixel = in->mouse.delta.x; delta = (pixel / scroll->w) * target; scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w); cursor_x = scroll->x + ((scroll_offset/target) * scroll->w); in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f; } } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)|| nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) { /* scroll page up by click on empty space or shortcut */ if (o == NK_VERTICAL) scroll_offset = NK_MAX(0, scroll_offset - scroll->h); else scroll_offset = NK_MAX(0, scroll_offset - scroll->w); } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) || nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) { /* scroll page down by click on empty space or shortcut */ if (o == NK_VERTICAL) scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h); else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w); } else if (has_scrolling) { if ((scroll_delta < 0 || (scroll_delta > 0))) { /* update cursor by mouse scrolling */ scroll_offset = scroll_offset + scroll_step * (-scroll_delta); if (o == NK_VERTICAL) scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h); else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w); } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) { /* update cursor to the beginning */ if (o == NK_VERTICAL) scroll_offset = 0; } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) { /* update cursor to the end */ if (o == NK_VERTICAL) scroll_offset = target - scroll->h; } } if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll)) *state |= NK_WIDGET_STATE_ENTERED; else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll)) *state |= NK_WIDGET_STATE_LEFT; return scroll_offset; }
NK_LIB float nk_do_scrollbarh(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font) { struct nk_rect cursor; struct nk_rect empty_west; struct nk_rect empty_east; float scroll_step; float scroll_offset; float scroll_off; float scroll_ratio; NK_ASSERT(out); NK_ASSERT(style); if (!out || !style) return 0; /* scrollbar background */ scroll.h = NK_MAX(scroll.h, 1); scroll.w = NK_MAX(scroll.w, 2 * scroll.h); if (target <= scroll.w) return 0; /* optional scrollbar buttons */ if (style->show_buttons) { nk_flags ws; float scroll_w; struct nk_rect button; button.y = scroll.y; button.w = scroll.h; button.h = scroll.h; scroll_w = scroll.w - 2 * button.w; scroll_step = NK_MIN(step, button_pixel_inc); /* decrement button */ button.x = scroll.x; if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_REPEATER, &style->dec_button, in, font)) offset = offset - scroll_step; /* increment button */ button.x = scroll.x + scroll.w - button.w; if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_REPEATER, &style->inc_button, in, font)) offset = offset + scroll_step; scroll.x = scroll.x + button.w; scroll.w = scroll_w; } /* calculate scrollbar constants */ scroll_step = NK_MIN(step, scroll.w); scroll_offset = NK_CLAMP(0, offset, target - scroll.w); scroll_ratio = scroll.w / target; scroll_off = scroll_offset / target; /* calculate cursor bounds */ cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x); cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x; cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y); cursor.y = scroll.y + style->border + style->padding.y; /* calculate empty space around cursor */ empty_west.x = scroll.x; empty_west.y = scroll.y; empty_west.w = cursor.x - scroll.x; empty_west.h = scroll.h; empty_east.x = cursor.x + cursor.w; empty_east.y = scroll.y; empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w); empty_east.h = scroll.h; /* update scrollbar */ scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL); scroll_off = scroll_offset / target; cursor.x = scroll.x + (scroll_off * scroll.w); /* draw scrollbar */ if (style->draw_begin) style->draw_begin(out, style->userdata); nk_draw_scrollbar(out, *state, style, &scroll, &cursor); if (style->draw_end) style->draw_end(out, style->userdata); return scroll_offset; }