nuklear_menu.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. #include "nuklear.h"
  2. #include "nuklear_internal.h"
  3. /* ===============================================================
  4. *
  5. * MENU
  6. *
  7. * ===============================================================*/
  8. NK_API void
  9. nk_menubar_begin(struct nk_context *ctx)
  10. {
  11. struct nk_panel *layout;
  12. NK_ASSERT(ctx);
  13. NK_ASSERT(ctx->current);
  14. NK_ASSERT(ctx->current->layout);
  15. if (!ctx || !ctx->current || !ctx->current->layout)
  16. return;
  17. layout = ctx->current->layout;
  18. NK_ASSERT(layout->at_y == layout->bounds.y);
  19. /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
  20. If you want a menubar the first nuklear function after `nk_begin` has to be a
  21. `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
  22. widgets (also supports multiple rows).
  23. Example:
  24. if (nk_begin(...)) {
  25. nk_menubar_begin(...);
  26. nk_layout_xxxx(...);
  27. nk_button(...);
  28. nk_layout_xxxx(...);
  29. nk_button(...);
  30. nk_menubar_end(...);
  31. }
  32. nk_end(...);
  33. */
  34. if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
  35. return;
  36. layout->menu.x = layout->at_x;
  37. layout->menu.y = layout->at_y + layout->row.height;
  38. layout->menu.w = layout->bounds.w;
  39. layout->menu.offset.x = *layout->offset_x;
  40. layout->menu.offset.y = *layout->offset_y;
  41. *layout->offset_y = 0;
  42. }
  43. NK_API void
  44. nk_menubar_end(struct nk_context *ctx)
  45. {
  46. struct nk_window *win;
  47. struct nk_panel *layout;
  48. struct nk_command_buffer *out;
  49. NK_ASSERT(ctx);
  50. NK_ASSERT(ctx->current);
  51. NK_ASSERT(ctx->current->layout);
  52. if (!ctx || !ctx->current || !ctx->current->layout)
  53. return;
  54. win = ctx->current;
  55. out = &win->buffer;
  56. layout = win->layout;
  57. if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
  58. return;
  59. layout->menu.h = layout->at_y - layout->menu.y;
  60. layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
  61. layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
  62. *layout->offset_x = layout->menu.offset.x;
  63. *layout->offset_y = layout->menu.offset.y;
  64. layout->at_y = layout->bounds.y - layout->row.height;
  65. layout->clip.y = layout->bounds.y;
  66. layout->clip.h = layout->bounds.h;
  67. nk_push_scissor(out, layout->clip);
  68. }
  69. NK_INTERN int
  70. nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
  71. const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
  72. {
  73. int is_open = 0;
  74. int is_active = 0;
  75. struct nk_rect body;
  76. struct nk_window *popup;
  77. nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
  78. NK_ASSERT(ctx);
  79. NK_ASSERT(ctx->current);
  80. NK_ASSERT(ctx->current->layout);
  81. if (!ctx || !ctx->current || !ctx->current->layout)
  82. return 0;
  83. body.x = header.x;
  84. body.w = size.x;
  85. body.y = header.y + header.h;
  86. body.h = size.y;
  87. popup = win->popup.win;
  88. is_open = popup ? nk_true : nk_false;
  89. is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
  90. if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
  91. (!is_open && !is_active && !is_clicked)) return 0;
  92. if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
  93. return 0;
  94. win->popup.type = NK_PANEL_MENU;
  95. win->popup.name = hash;
  96. return 1;
  97. }
  98. NK_API int
  99. nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
  100. nk_flags align, struct nk_vec2 size)
  101. {
  102. struct nk_window *win;
  103. const struct nk_input *in;
  104. struct nk_rect header;
  105. int is_clicked = nk_false;
  106. nk_flags state;
  107. NK_ASSERT(ctx);
  108. NK_ASSERT(ctx->current);
  109. NK_ASSERT(ctx->current->layout);
  110. if (!ctx || !ctx->current || !ctx->current->layout)
  111. return 0;
  112. win = ctx->current;
  113. state = nk_widget(&header, ctx);
  114. if (!state) return 0;
  115. in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  116. if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
  117. title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
  118. is_clicked = nk_true;
  119. return nk_menu_begin(ctx, win, title, is_clicked, header, size);
  120. }
  121. NK_API int nk_menu_begin_label(struct nk_context *ctx,
  122. const char *text, nk_flags align, struct nk_vec2 size)
  123. {
  124. return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);
  125. }
  126. NK_API int
  127. nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
  128. struct nk_vec2 size)
  129. {
  130. struct nk_window *win;
  131. struct nk_rect header;
  132. const struct nk_input *in;
  133. int is_clicked = nk_false;
  134. nk_flags state;
  135. NK_ASSERT(ctx);
  136. NK_ASSERT(ctx->current);
  137. NK_ASSERT(ctx->current->layout);
  138. if (!ctx || !ctx->current || !ctx->current->layout)
  139. return 0;
  140. win = ctx->current;
  141. state = nk_widget(&header, ctx);
  142. if (!state) return 0;
  143. in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  144. if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
  145. img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
  146. is_clicked = nk_true;
  147. return nk_menu_begin(ctx, win, id, is_clicked, header, size);
  148. }
  149. NK_API int
  150. nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
  151. enum nk_symbol_type sym, struct nk_vec2 size)
  152. {
  153. struct nk_window *win;
  154. const struct nk_input *in;
  155. struct nk_rect header;
  156. int is_clicked = nk_false;
  157. nk_flags state;
  158. NK_ASSERT(ctx);
  159. NK_ASSERT(ctx->current);
  160. NK_ASSERT(ctx->current->layout);
  161. if (!ctx || !ctx->current || !ctx->current->layout)
  162. return 0;
  163. win = ctx->current;
  164. state = nk_widget(&header, ctx);
  165. if (!state) return 0;
  166. in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  167. if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header,
  168. sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
  169. is_clicked = nk_true;
  170. return nk_menu_begin(ctx, win, id, is_clicked, header, size);
  171. }
  172. NK_API int
  173. nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
  174. nk_flags align, struct nk_image img, struct nk_vec2 size)
  175. {
  176. struct nk_window *win;
  177. struct nk_rect header;
  178. const struct nk_input *in;
  179. int is_clicked = nk_false;
  180. nk_flags state;
  181. NK_ASSERT(ctx);
  182. NK_ASSERT(ctx->current);
  183. NK_ASSERT(ctx->current->layout);
  184. if (!ctx || !ctx->current || !ctx->current->layout)
  185. return 0;
  186. win = ctx->current;
  187. state = nk_widget(&header, ctx);
  188. if (!state) return 0;
  189. in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  190. if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
  191. header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
  192. ctx->style.font, in))
  193. is_clicked = nk_true;
  194. return nk_menu_begin(ctx, win, title, is_clicked, header, size);
  195. }
  196. NK_API int
  197. nk_menu_begin_image_label(struct nk_context *ctx,
  198. const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
  199. {
  200. return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);
  201. }
  202. NK_API int
  203. nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
  204. nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
  205. {
  206. struct nk_window *win;
  207. struct nk_rect header;
  208. const struct nk_input *in;
  209. int is_clicked = nk_false;
  210. nk_flags state;
  211. NK_ASSERT(ctx);
  212. NK_ASSERT(ctx->current);
  213. NK_ASSERT(ctx->current->layout);
  214. if (!ctx || !ctx->current || !ctx->current->layout)
  215. return 0;
  216. win = ctx->current;
  217. state = nk_widget(&header, ctx);
  218. if (!state) return 0;
  219. in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  220. if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
  221. header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
  222. ctx->style.font, in)) is_clicked = nk_true;
  223. return nk_menu_begin(ctx, win, title, is_clicked, header, size);
  224. }
  225. NK_API int
  226. nk_menu_begin_symbol_label(struct nk_context *ctx,
  227. const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
  228. {
  229. return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);
  230. }
  231. NK_API int
  232. nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
  233. {
  234. return nk_contextual_item_text(ctx, title, len, align);
  235. }
  236. NK_API int
  237. nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
  238. {
  239. return nk_contextual_item_label(ctx, label, align);
  240. }
  241. NK_API int
  242. nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
  243. const char *label, nk_flags align)
  244. {
  245. return nk_contextual_item_image_label(ctx, img, label, align);
  246. }
  247. NK_API int
  248. nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
  249. const char *text, int len, nk_flags align)
  250. {
  251. return nk_contextual_item_image_text(ctx, img, text, len, align);
  252. }
  253. NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
  254. const char *text, int len, nk_flags align)
  255. {
  256. return nk_contextual_item_symbol_text(ctx, sym, text, len, align);
  257. }
  258. NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
  259. const char *label, nk_flags align)
  260. {
  261. return nk_contextual_item_symbol_label(ctx, sym, label, align);
  262. }
  263. NK_API void nk_menu_close(struct nk_context *ctx)
  264. {
  265. nk_contextual_close(ctx);
  266. }
  267. NK_API void
  268. nk_menu_end(struct nk_context *ctx)
  269. {
  270. nk_contextual_end(ctx);
  271. }