1 #include "nuklear.h"
2 #include "nuklear_internal.h"
3 
4 /* ==============================================================
5  *
6  *                          COMBO
7  *
8  * ===============================================================*/
9 NK_INTERN int
nk_combo_begin(struct nk_context * ctx,struct nk_window * win,struct nk_vec2 size,int is_clicked,struct nk_rect header)10 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
11     struct nk_vec2 size, int is_clicked, struct nk_rect header)
12 {
13     struct nk_window *popup;
14     int is_open = 0;
15     int is_active = 0;
16     struct nk_rect body;
17     nk_hash hash;
18 
19     NK_ASSERT(ctx);
20     NK_ASSERT(ctx->current);
21     NK_ASSERT(ctx->current->layout);
22     if (!ctx || !ctx->current || !ctx->current->layout)
23         return 0;
24 
25     popup = win->popup.win;
26     body.x = header.x;
27     body.w = size.x;
28     body.y = header.y + header.h-ctx->style.window.combo_border;
29     body.h = size.y;
30 
31     hash = win->popup.combo_count++;
32     is_open = (popup) ? nk_true:nk_false;
33     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
34     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
35         (!is_open && !is_active && !is_clicked)) return 0;
36     if (!nk_nonblock_begin(ctx, 0, body,
37         (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
38 
39     win->popup.type = NK_PANEL_COMBO;
40     win->popup.name = hash;
41     return 1;
42 }
43 NK_API int
nk_combo_begin_text(struct nk_context * ctx,const char * selected,int len,struct nk_vec2 size)44 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
45     struct nk_vec2 size)
46 {
47     const struct nk_input *in;
48     struct nk_window *win;
49     struct nk_style *style;
50 
51     enum nk_widget_layout_states s;
52     int is_clicked = nk_false;
53     struct nk_rect header;
54     const struct nk_style_item *background;
55     struct nk_text text;
56 
57     NK_ASSERT(ctx);
58     NK_ASSERT(selected);
59     NK_ASSERT(ctx->current);
60     NK_ASSERT(ctx->current->layout);
61     if (!ctx || !ctx->current || !ctx->current->layout || !selected)
62         return 0;
63 
64     win = ctx->current;
65     style = &ctx->style;
66     s = nk_widget(&header, ctx);
67     if (s == NK_WIDGET_INVALID)
68         return 0;
69 
70     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
71     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
72         is_clicked = nk_true;
73 
74     /* draw combo box header background and border */
75     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
76         background = &style->combo.active;
77         text.text = style->combo.label_active;
78     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
79         background = &style->combo.hover;
80         text.text = style->combo.label_hover;
81     } else {
82         background = &style->combo.normal;
83         text.text = style->combo.label_normal;
84     }
85     if (background->type == NK_STYLE_ITEM_IMAGE) {
86         text.background = nk_rgba(0,0,0,0);
87         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
88     } else {
89         text.background = background->data.color;
90         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
91         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
92     }
93     {
94         /* print currently selected text item */
95         struct nk_rect label;
96         struct nk_rect button;
97         struct nk_rect content;
98 
99         enum nk_symbol_type sym;
100         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
101             sym = style->combo.sym_hover;
102         else if (is_clicked)
103             sym = style->combo.sym_active;
104         else sym = style->combo.sym_normal;
105 
106         /* calculate button */
107         button.w = header.h - 2 * style->combo.button_padding.y;
108         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
109         button.y = header.y + style->combo.button_padding.y;
110         button.h = button.w;
111 
112         content.x = button.x + style->combo.button.padding.x;
113         content.y = button.y + style->combo.button.padding.y;
114         content.w = button.w - 2 * style->combo.button.padding.x;
115         content.h = button.h - 2 * style->combo.button.padding.y;
116 
117         /* draw selected label */
118         text.padding = nk_vec2(0,0);
119         label.x = header.x + style->combo.content_padding.x;
120         label.y = header.y + style->combo.content_padding.y;
121         label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
122         label.h = header.h - 2 * style->combo.content_padding.y;
123         nk_widget_text(&win->buffer, label, selected, len, &text,
124             NK_TEXT_LEFT, ctx->style.font);
125 
126         /* draw open/close button */
127         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
128             &ctx->style.combo.button, sym, style->font);
129     }
130     return nk_combo_begin(ctx, win, size, is_clicked, header);
131 }
132 NK_API int
nk_combo_begin_label(struct nk_context * ctx,const char * selected,struct nk_vec2 size)133 nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
134 {
135     return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);
136 }
137 NK_API int
nk_combo_begin_color(struct nk_context * ctx,struct nk_color color,struct nk_vec2 size)138 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
139 {
140     struct nk_window *win;
141     struct nk_style *style;
142     const struct nk_input *in;
143 
144     struct nk_rect header;
145     int is_clicked = nk_false;
146     enum nk_widget_layout_states s;
147     const struct nk_style_item *background;
148 
149     NK_ASSERT(ctx);
150     NK_ASSERT(ctx->current);
151     NK_ASSERT(ctx->current->layout);
152     if (!ctx || !ctx->current || !ctx->current->layout)
153         return 0;
154 
155     win = ctx->current;
156     style = &ctx->style;
157     s = nk_widget(&header, ctx);
158     if (s == NK_WIDGET_INVALID)
159         return 0;
160 
161     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
162     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
163         is_clicked = nk_true;
164 
165     /* draw combo box header background and border */
166     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
167         background = &style->combo.active;
168     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
169         background = &style->combo.hover;
170     else background = &style->combo.normal;
171 
172     if (background->type == NK_STYLE_ITEM_IMAGE) {
173         nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
174     } else {
175         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
176         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
177     }
178     {
179         struct nk_rect content;
180         struct nk_rect button;
181         struct nk_rect bounds;
182 
183         enum nk_symbol_type sym;
184         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
185             sym = style->combo.sym_hover;
186         else if (is_clicked)
187             sym = style->combo.sym_active;
188         else sym = style->combo.sym_normal;
189 
190         /* calculate button */
191         button.w = header.h - 2 * style->combo.button_padding.y;
192         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
193         button.y = header.y + style->combo.button_padding.y;
194         button.h = button.w;
195 
196         content.x = button.x + style->combo.button.padding.x;
197         content.y = button.y + style->combo.button.padding.y;
198         content.w = button.w - 2 * style->combo.button.padding.x;
199         content.h = button.h - 2 * style->combo.button.padding.y;
200 
201         /* draw color */
202         bounds.h = header.h - 4 * style->combo.content_padding.y;
203         bounds.y = header.y + 2 * style->combo.content_padding.y;
204         bounds.x = header.x + 2 * style->combo.content_padding.x;
205         bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
206         nk_fill_rect(&win->buffer, bounds, 0, color);
207 
208         /* draw open/close button */
209         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
210             &ctx->style.combo.button, sym, style->font);
211     }
212     return nk_combo_begin(ctx, win, size, is_clicked, header);
213 }
214 NK_API int
nk_combo_begin_symbol(struct nk_context * ctx,enum nk_symbol_type symbol,struct nk_vec2 size)215 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
216 {
217     struct nk_window *win;
218     struct nk_style *style;
219     const struct nk_input *in;
220 
221     struct nk_rect header;
222     int is_clicked = nk_false;
223     enum nk_widget_layout_states s;
224     const struct nk_style_item *background;
225     struct nk_color sym_background;
226     struct nk_color symbol_color;
227 
228     NK_ASSERT(ctx);
229     NK_ASSERT(ctx->current);
230     NK_ASSERT(ctx->current->layout);
231     if (!ctx || !ctx->current || !ctx->current->layout)
232         return 0;
233 
234     win = ctx->current;
235     style = &ctx->style;
236     s = nk_widget(&header, ctx);
237     if (s == NK_WIDGET_INVALID)
238         return 0;
239 
240     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
241     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
242         is_clicked = nk_true;
243 
244     /* draw combo box header background and border */
245     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
246         background = &style->combo.active;
247         symbol_color = style->combo.symbol_active;
248     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
249         background = &style->combo.hover;
250         symbol_color = style->combo.symbol_hover;
251     } else {
252         background = &style->combo.normal;
253         symbol_color = style->combo.symbol_hover;
254     }
255 
256     if (background->type == NK_STYLE_ITEM_IMAGE) {
257         sym_background = nk_rgba(0,0,0,0);
258         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
259     } else {
260         sym_background = background->data.color;
261         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
262         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
263     }
264     {
265         struct nk_rect bounds = {0,0,0,0};
266         struct nk_rect content;
267         struct nk_rect button;
268 
269         enum nk_symbol_type sym;
270         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
271             sym = style->combo.sym_hover;
272         else if (is_clicked)
273             sym = style->combo.sym_active;
274         else sym = style->combo.sym_normal;
275 
276         /* calculate button */
277         button.w = header.h - 2 * style->combo.button_padding.y;
278         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
279         button.y = header.y + style->combo.button_padding.y;
280         button.h = button.w;
281 
282         content.x = button.x + style->combo.button.padding.x;
283         content.y = button.y + style->combo.button.padding.y;
284         content.w = button.w - 2 * style->combo.button.padding.x;
285         content.h = button.h - 2 * style->combo.button.padding.y;
286 
287         /* draw symbol */
288         bounds.h = header.h - 2 * style->combo.content_padding.y;
289         bounds.y = header.y + style->combo.content_padding.y;
290         bounds.x = header.x + style->combo.content_padding.x;
291         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
292         nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
293             1.0f, style->font);
294 
295         /* draw open/close button */
296         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
297             &ctx->style.combo.button, sym, style->font);
298     }
299     return nk_combo_begin(ctx, win, size, is_clicked, header);
300 }
301 NK_API int
nk_combo_begin_symbol_text(struct nk_context * ctx,const char * selected,int len,enum nk_symbol_type symbol,struct nk_vec2 size)302 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
303     enum nk_symbol_type symbol, struct nk_vec2 size)
304 {
305     struct nk_window *win;
306     struct nk_style *style;
307     struct nk_input *in;
308 
309     struct nk_rect header;
310     int is_clicked = nk_false;
311     enum nk_widget_layout_states s;
312     const struct nk_style_item *background;
313     struct nk_color symbol_color;
314     struct nk_text text;
315 
316     NK_ASSERT(ctx);
317     NK_ASSERT(ctx->current);
318     NK_ASSERT(ctx->current->layout);
319     if (!ctx || !ctx->current || !ctx->current->layout)
320         return 0;
321 
322     win = ctx->current;
323     style = &ctx->style;
324     s = nk_widget(&header, ctx);
325     if (!s) return 0;
326 
327     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
328     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
329         is_clicked = nk_true;
330 
331     /* draw combo box header background and border */
332     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
333         background = &style->combo.active;
334         symbol_color = style->combo.symbol_active;
335         text.text = style->combo.label_active;
336     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
337         background = &style->combo.hover;
338         symbol_color = style->combo.symbol_hover;
339         text.text = style->combo.label_hover;
340     } else {
341         background = &style->combo.normal;
342         symbol_color = style->combo.symbol_normal;
343         text.text = style->combo.label_normal;
344     }
345     if (background->type == NK_STYLE_ITEM_IMAGE) {
346         text.background = nk_rgba(0,0,0,0);
347         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
348     } else {
349         text.background = background->data.color;
350         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
351         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
352     }
353     {
354         struct nk_rect content;
355         struct nk_rect button;
356         struct nk_rect label;
357         struct nk_rect image;
358 
359         enum nk_symbol_type sym;
360         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
361             sym = style->combo.sym_hover;
362         else if (is_clicked)
363             sym = style->combo.sym_active;
364         else sym = style->combo.sym_normal;
365 
366         /* calculate button */
367         button.w = header.h - 2 * style->combo.button_padding.y;
368         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
369         button.y = header.y + style->combo.button_padding.y;
370         button.h = button.w;
371 
372         content.x = button.x + style->combo.button.padding.x;
373         content.y = button.y + style->combo.button.padding.y;
374         content.w = button.w - 2 * style->combo.button.padding.x;
375         content.h = button.h - 2 * style->combo.button.padding.y;
376         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
377             &ctx->style.combo.button, sym, style->font);
378 
379         /* draw symbol */
380         image.x = header.x + style->combo.content_padding.x;
381         image.y = header.y + style->combo.content_padding.y;
382         image.h = header.h - 2 * style->combo.content_padding.y;
383         image.w = image.h;
384         nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
385             1.0f, style->font);
386 
387         /* draw label */
388         text.padding = nk_vec2(0,0);
389         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
390         label.y = header.y + style->combo.content_padding.y;
391         label.w = (button.x - style->combo.content_padding.x) - label.x;
392         label.h = header.h - 2 * style->combo.content_padding.y;
393         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
394     }
395     return nk_combo_begin(ctx, win, size, is_clicked, header);
396 }
397 NK_API int
nk_combo_begin_image(struct nk_context * ctx,struct nk_image img,struct nk_vec2 size)398 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
399 {
400     struct nk_window *win;
401     struct nk_style *style;
402     const struct nk_input *in;
403 
404     struct nk_rect header;
405     int is_clicked = nk_false;
406     enum nk_widget_layout_states s;
407     const struct nk_style_item *background;
408 
409     NK_ASSERT(ctx);
410     NK_ASSERT(ctx->current);
411     NK_ASSERT(ctx->current->layout);
412     if (!ctx || !ctx->current || !ctx->current->layout)
413         return 0;
414 
415     win = ctx->current;
416     style = &ctx->style;
417     s = nk_widget(&header, ctx);
418     if (s == NK_WIDGET_INVALID)
419         return 0;
420 
421     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
422     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
423         is_clicked = nk_true;
424 
425     /* draw combo box header background and border */
426     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
427         background = &style->combo.active;
428     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
429         background = &style->combo.hover;
430     else background = &style->combo.normal;
431 
432     if (background->type == NK_STYLE_ITEM_IMAGE) {
433         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
434     } else {
435         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
436         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
437     }
438     {
439         struct nk_rect bounds = {0,0,0,0};
440         struct nk_rect content;
441         struct nk_rect button;
442 
443         enum nk_symbol_type sym;
444         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
445             sym = style->combo.sym_hover;
446         else if (is_clicked)
447             sym = style->combo.sym_active;
448         else sym = style->combo.sym_normal;
449 
450         /* calculate button */
451         button.w = header.h - 2 * style->combo.button_padding.y;
452         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
453         button.y = header.y + style->combo.button_padding.y;
454         button.h = button.w;
455 
456         content.x = button.x + style->combo.button.padding.x;
457         content.y = button.y + style->combo.button.padding.y;
458         content.w = button.w - 2 * style->combo.button.padding.x;
459         content.h = button.h - 2 * style->combo.button.padding.y;
460 
461         /* draw image */
462         bounds.h = header.h - 2 * style->combo.content_padding.y;
463         bounds.y = header.y + style->combo.content_padding.y;
464         bounds.x = header.x + style->combo.content_padding.x;
465         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
466         nk_draw_image(&win->buffer, bounds, &img, nk_white);
467 
468         /* draw open/close button */
469         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
470             &ctx->style.combo.button, sym, style->font);
471     }
472     return nk_combo_begin(ctx, win, size, is_clicked, header);
473 }
474 NK_API int
nk_combo_begin_image_text(struct nk_context * ctx,const char * selected,int len,struct nk_image img,struct nk_vec2 size)475 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
476     struct nk_image img, struct nk_vec2 size)
477 {
478     struct nk_window *win;
479     struct nk_style *style;
480     struct nk_input *in;
481 
482     struct nk_rect header;
483     int is_clicked = nk_false;
484     enum nk_widget_layout_states s;
485     const struct nk_style_item *background;
486     struct nk_text text;
487 
488     NK_ASSERT(ctx);
489     NK_ASSERT(ctx->current);
490     NK_ASSERT(ctx->current->layout);
491     if (!ctx || !ctx->current || !ctx->current->layout)
492         return 0;
493 
494     win = ctx->current;
495     style = &ctx->style;
496     s = nk_widget(&header, ctx);
497     if (!s) return 0;
498 
499     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
500     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
501         is_clicked = nk_true;
502 
503     /* draw combo box header background and border */
504     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
505         background = &style->combo.active;
506         text.text = style->combo.label_active;
507     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
508         background = &style->combo.hover;
509         text.text = style->combo.label_hover;
510     } else {
511         background = &style->combo.normal;
512         text.text = style->combo.label_normal;
513     }
514     if (background->type == NK_STYLE_ITEM_IMAGE) {
515         text.background = nk_rgba(0,0,0,0);
516         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
517     } else {
518         text.background = background->data.color;
519         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
520         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
521     }
522     {
523         struct nk_rect content;
524         struct nk_rect button;
525         struct nk_rect label;
526         struct nk_rect image;
527 
528         enum nk_symbol_type sym;
529         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
530             sym = style->combo.sym_hover;
531         else if (is_clicked)
532             sym = style->combo.sym_active;
533         else sym = style->combo.sym_normal;
534 
535         /* calculate button */
536         button.w = header.h - 2 * style->combo.button_padding.y;
537         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
538         button.y = header.y + style->combo.button_padding.y;
539         button.h = button.w;
540 
541         content.x = button.x + style->combo.button.padding.x;
542         content.y = button.y + style->combo.button.padding.y;
543         content.w = button.w - 2 * style->combo.button.padding.x;
544         content.h = button.h - 2 * style->combo.button.padding.y;
545         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
546             &ctx->style.combo.button, sym, style->font);
547 
548         /* draw image */
549         image.x = header.x + style->combo.content_padding.x;
550         image.y = header.y + style->combo.content_padding.y;
551         image.h = header.h - 2 * style->combo.content_padding.y;
552         image.w = image.h;
553         nk_draw_image(&win->buffer, image, &img, nk_white);
554 
555         /* draw label */
556         text.padding = nk_vec2(0,0);
557         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
558         label.y = header.y + style->combo.content_padding.y;
559         label.w = (button.x - style->combo.content_padding.x) - label.x;
560         label.h = header.h - 2 * style->combo.content_padding.y;
561         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
562     }
563     return nk_combo_begin(ctx, win, size, is_clicked, header);
564 }
565 NK_API int
nk_combo_begin_symbol_label(struct nk_context * ctx,const char * selected,enum nk_symbol_type type,struct nk_vec2 size)566 nk_combo_begin_symbol_label(struct nk_context *ctx,
567     const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
568 {
569     return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);
570 }
571 NK_API int
nk_combo_begin_image_label(struct nk_context * ctx,const char * selected,struct nk_image img,struct nk_vec2 size)572 nk_combo_begin_image_label(struct nk_context *ctx,
573     const char *selected, struct nk_image img, struct nk_vec2 size)
574 {
575     return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);
576 }
577 NK_API int
nk_combo_item_text(struct nk_context * ctx,const char * text,int len,nk_flags align)578 nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
579 {
580     return nk_contextual_item_text(ctx, text, len, align);
581 }
582 NK_API int
nk_combo_item_label(struct nk_context * ctx,const char * label,nk_flags align)583 nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
584 {
585     return nk_contextual_item_label(ctx, label, align);
586 }
587 NK_API int
nk_combo_item_image_text(struct nk_context * ctx,struct nk_image img,const char * text,int len,nk_flags alignment)588 nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
589     int len, nk_flags alignment)
590 {
591     return nk_contextual_item_image_text(ctx, img, text, len, alignment);
592 }
593 NK_API int
nk_combo_item_image_label(struct nk_context * ctx,struct nk_image img,const char * text,nk_flags alignment)594 nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
595     const char *text, nk_flags alignment)
596 {
597     return nk_contextual_item_image_label(ctx, img, text, alignment);
598 }
599 NK_API int
nk_combo_item_symbol_text(struct nk_context * ctx,enum nk_symbol_type sym,const char * text,int len,nk_flags alignment)600 nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
601     const char *text, int len, nk_flags alignment)
602 {
603     return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);
604 }
605 NK_API int
nk_combo_item_symbol_label(struct nk_context * ctx,enum nk_symbol_type sym,const char * label,nk_flags alignment)606 nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
607     const char *label, nk_flags alignment)
608 {
609     return nk_contextual_item_symbol_label(ctx, sym, label, alignment);
610 }
nk_combo_end(struct nk_context * ctx)611 NK_API void nk_combo_end(struct nk_context *ctx)
612 {
613     nk_contextual_end(ctx);
614 }
nk_combo_close(struct nk_context * ctx)615 NK_API void nk_combo_close(struct nk_context *ctx)
616 {
617     nk_contextual_close(ctx);
618 }
619 NK_API int
nk_combo(struct nk_context * ctx,const char ** items,int count,int selected,int item_height,struct nk_vec2 size)620 nk_combo(struct nk_context *ctx, const char **items, int count,
621     int selected, int item_height, struct nk_vec2 size)
622 {
623     int i = 0;
624     int max_height;
625     struct nk_vec2 item_spacing;
626     struct nk_vec2 window_padding;
627 
628     NK_ASSERT(ctx);
629     NK_ASSERT(items);
630     NK_ASSERT(ctx->current);
631     if (!ctx || !items ||!count)
632         return selected;
633 
634     item_spacing = ctx->style.window.spacing;
635     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
636     max_height = count * item_height + count * (int)item_spacing.y;
637     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
638     size.y = NK_MIN(size.y, (float)max_height);
639     if (nk_combo_begin_label(ctx, items[selected], size)) {
640         nk_layout_row_dynamic(ctx, (float)item_height, 1);
641         for (i = 0; i < count; ++i) {
642             if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
643                 selected = i;
644         }
645         nk_combo_end(ctx);
646     }
647     return selected;
648 }
649 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)650 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
651     int separator, int selected, int count, int item_height, struct nk_vec2 size)
652 {
653     int i;
654     int max_height;
655     struct nk_vec2 item_spacing;
656     struct nk_vec2 window_padding;
657     const char *current_item;
658     const char *iter;
659     int length = 0;
660 
661     NK_ASSERT(ctx);
662     NK_ASSERT(items_separated_by_separator);
663     if (!ctx || !items_separated_by_separator)
664         return selected;
665 
666     /* calculate popup window */
667     item_spacing = ctx->style.window.spacing;
668     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
669     max_height = count * item_height + count * (int)item_spacing.y;
670     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
671     size.y = NK_MIN(size.y, (float)max_height);
672 
673     /* find selected item */
674     current_item = items_separated_by_separator;
675     for (i = 0; i < count; ++i) {
676         iter = current_item;
677         while (*iter && *iter != separator) iter++;
678         length = (int)(iter - current_item);
679         if (i == selected) break;
680         current_item = iter + 1;
681     }
682 
683     if (nk_combo_begin_text(ctx, current_item, length, size)) {
684         current_item = items_separated_by_separator;
685         nk_layout_row_dynamic(ctx, (float)item_height, 1);
686         for (i = 0; i < count; ++i) {
687             iter = current_item;
688             while (*iter && *iter != separator) iter++;
689             length = (int)(iter - current_item);
690             if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
691                 selected = i;
692             current_item = current_item + length + 1;
693         }
694         nk_combo_end(ctx);
695     }
696     return selected;
697 }
698 NK_API int
nk_combo_string(struct nk_context * ctx,const char * items_separated_by_zeros,int selected,int count,int item_height,struct nk_vec2 size)699 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
700     int selected, int count, int item_height, struct nk_vec2 size)
701 {
702     return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);
703 }
704 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)705 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
706     void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
707 {
708     int i;
709     int max_height;
710     struct nk_vec2 item_spacing;
711     struct nk_vec2 window_padding;
712     const char *item;
713 
714     NK_ASSERT(ctx);
715     NK_ASSERT(item_getter);
716     if (!ctx || !item_getter)
717         return selected;
718 
719     /* calculate popup window */
720     item_spacing = ctx->style.window.spacing;
721     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
722     max_height = count * item_height + count * (int)item_spacing.y;
723     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
724     size.y = NK_MIN(size.y, (float)max_height);
725 
726     item_getter(userdata, selected, &item);
727     if (nk_combo_begin_label(ctx, item, size)) {
728         nk_layout_row_dynamic(ctx, (float)item_height, 1);
729         for (i = 0; i < count; ++i) {
730             item_getter(userdata, i, &item);
731             if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
732                 selected = i;
733         }
734         nk_combo_end(ctx);
735     } return selected;
736 }
737 NK_API void
nk_combobox(struct nk_context * ctx,const char ** items,int count,int * selected,int item_height,struct nk_vec2 size)738 nk_combobox(struct nk_context *ctx, const char **items, int count,
739     int *selected, int item_height, struct nk_vec2 size)
740 {
741     *selected = nk_combo(ctx, items, count, *selected, item_height, size);
742 }
743 NK_API void
nk_combobox_string(struct nk_context * ctx,const char * items_separated_by_zeros,int * selected,int count,int item_height,struct nk_vec2 size)744 nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
745     int *selected, int count, int item_height, struct nk_vec2 size)
746 {
747     *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);
748 }
749 NK_API void
nk_combobox_separator(struct nk_context * ctx,const char * items_separated_by_separator,int separator,int * selected,int count,int item_height,struct nk_vec2 size)750 nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
751     int separator,int *selected, int count, int item_height, struct nk_vec2 size)
752 {
753     *selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
754                                     *selected, count, item_height, size);
755 }
756 NK_API void
nk_combobox_callback(struct nk_context * ctx,void (* item_getter)(void * data,int id,const char ** out_text),void * userdata,int * selected,int count,int item_height,struct nk_vec2 size)757 nk_combobox_callback(struct nk_context *ctx,
758     void(*item_getter)(void* data, int id, const char **out_text),
759     void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
760 {
761     *selected = nk_combo_callback(ctx, item_getter, userdata,  *selected, count, item_height, size);
762 }
763 
764