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