nuklear_group.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include "nuklear.h"
  2. #include "nuklear_internal.h"
  3. /* ===============================================================
  4. *
  5. * GROUP
  6. *
  7. * ===============================================================*/
  8. NK_API nk_bool
  9. nk_group_scrolled_offset_begin(struct nk_context *ctx,
  10. nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
  11. {
  12. struct nk_rect bounds;
  13. struct nk_window panel;
  14. struct nk_window *win;
  15. win = ctx->current;
  16. nk_panel_alloc_space(&bounds, ctx);
  17. {const struct nk_rect *c = &win->layout->clip;
  18. if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
  19. !(flags & NK_WINDOW_MOVABLE)) {
  20. return 0;
  21. }}
  22. if (win->flags & NK_WINDOW_ROM)
  23. flags |= NK_WINDOW_ROM;
  24. /* initialize a fake window to create the panel from */
  25. nk_zero(&panel, sizeof(panel));
  26. panel.bounds = bounds;
  27. panel.flags = flags;
  28. panel.scrollbar.x = *x_offset;
  29. panel.scrollbar.y = *y_offset;
  30. panel.buffer = win->buffer;
  31. panel.layout = (struct nk_panel*)nk_create_panel(ctx);
  32. ctx->current = &panel;
  33. nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
  34. win->buffer = panel.buffer;
  35. win->buffer.clip = panel.layout->clip;
  36. panel.layout->offset_x = x_offset;
  37. panel.layout->offset_y = y_offset;
  38. panel.layout->parent = win->layout;
  39. win->layout = panel.layout;
  40. ctx->current = win;
  41. if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
  42. (panel.layout->flags & NK_WINDOW_MINIMIZED))
  43. {
  44. nk_flags f = panel.layout->flags;
  45. nk_group_scrolled_end(ctx);
  46. if (f & NK_WINDOW_CLOSED)
  47. return NK_WINDOW_CLOSED;
  48. if (f & NK_WINDOW_MINIMIZED)
  49. return NK_WINDOW_MINIMIZED;
  50. }
  51. return 1;
  52. }
  53. NK_API void
  54. nk_group_scrolled_end(struct nk_context *ctx)
  55. {
  56. struct nk_window *win;
  57. struct nk_panel *parent;
  58. struct nk_panel *g;
  59. struct nk_rect clip;
  60. struct nk_window pan;
  61. struct nk_vec2 panel_padding;
  62. NK_ASSERT(ctx);
  63. NK_ASSERT(ctx->current);
  64. if (!ctx || !ctx->current)
  65. return;
  66. /* make sure nk_group_begin was called correctly */
  67. NK_ASSERT(ctx->current);
  68. win = ctx->current;
  69. NK_ASSERT(win->layout);
  70. g = win->layout;
  71. NK_ASSERT(g->parent);
  72. parent = g->parent;
  73. /* dummy window */
  74. nk_zero_struct(pan);
  75. panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
  76. pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
  77. pan.bounds.x = g->bounds.x - panel_padding.x;
  78. pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
  79. pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
  80. if (g->flags & NK_WINDOW_BORDER) {
  81. pan.bounds.x -= g->border;
  82. pan.bounds.y -= g->border;
  83. pan.bounds.w += 2*g->border;
  84. pan.bounds.h += 2*g->border;
  85. }
  86. if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
  87. pan.bounds.w += ctx->style.window.scrollbar_size.x;
  88. pan.bounds.h += ctx->style.window.scrollbar_size.y;
  89. }
  90. pan.scrollbar.x = *g->offset_x;
  91. pan.scrollbar.y = *g->offset_y;
  92. pan.flags = g->flags;
  93. pan.buffer = win->buffer;
  94. pan.layout = g;
  95. pan.parent = win;
  96. ctx->current = &pan;
  97. /* make sure group has correct clipping rectangle */
  98. nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
  99. pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
  100. nk_push_scissor(&pan.buffer, clip);
  101. nk_end(ctx);
  102. win->buffer = pan.buffer;
  103. nk_push_scissor(&win->buffer, parent->clip);
  104. ctx->current = win;
  105. win->layout = parent;
  106. g->bounds = pan.bounds;
  107. return;
  108. }
  109. NK_API nk_bool
  110. nk_group_scrolled_begin(struct nk_context *ctx,
  111. struct nk_scroll *scroll, const char *title, nk_flags flags)
  112. {
  113. return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);
  114. }
  115. NK_API nk_bool
  116. nk_group_begin_titled(struct nk_context *ctx, const char *id,
  117. const char *title, nk_flags flags)
  118. {
  119. int id_len;
  120. nk_hash id_hash;
  121. struct nk_window *win;
  122. nk_uint *x_offset;
  123. nk_uint *y_offset;
  124. NK_ASSERT(ctx);
  125. NK_ASSERT(id);
  126. NK_ASSERT(ctx->current);
  127. NK_ASSERT(ctx->current->layout);
  128. if (!ctx || !ctx->current || !ctx->current->layout || !id)
  129. return 0;
  130. /* find persistent group scrollbar value */
  131. win = ctx->current;
  132. id_len = (int)nk_strlen(id);
  133. id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
  134. x_offset = nk_find_value(win, id_hash);
  135. if (!x_offset) {
  136. x_offset = nk_add_value(ctx, win, id_hash, 0);
  137. y_offset = nk_add_value(ctx, win, id_hash+1, 0);
  138. NK_ASSERT(x_offset);
  139. NK_ASSERT(y_offset);
  140. if (!x_offset || !y_offset) return 0;
  141. *x_offset = *y_offset = 0;
  142. } else y_offset = nk_find_value(win, id_hash+1);
  143. return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
  144. }
  145. NK_API nk_bool
  146. nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
  147. {
  148. return nk_group_begin_titled(ctx, title, title, flags);
  149. }
  150. NK_API void
  151. nk_group_end(struct nk_context *ctx)
  152. {
  153. nk_group_scrolled_end(ctx);
  154. }
  155. NK_API void
  156. nk_group_get_scroll(struct nk_context *ctx, const char *id, nk_uint *x_offset, nk_uint *y_offset)
  157. {
  158. int id_len;
  159. nk_hash id_hash;
  160. struct nk_window *win;
  161. nk_uint *x_offset_ptr;
  162. nk_uint *y_offset_ptr;
  163. NK_ASSERT(ctx);
  164. NK_ASSERT(id);
  165. NK_ASSERT(ctx->current);
  166. NK_ASSERT(ctx->current->layout);
  167. if (!ctx || !ctx->current || !ctx->current->layout || !id)
  168. return;
  169. /* find persistent group scrollbar value */
  170. win = ctx->current;
  171. id_len = (int)nk_strlen(id);
  172. id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
  173. x_offset_ptr = nk_find_value(win, id_hash);
  174. if (!x_offset_ptr) {
  175. x_offset_ptr = nk_add_value(ctx, win, id_hash, 0);
  176. y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0);
  177. NK_ASSERT(x_offset_ptr);
  178. NK_ASSERT(y_offset_ptr);
  179. if (!x_offset_ptr || !y_offset_ptr) return;
  180. *x_offset_ptr = *y_offset_ptr = 0;
  181. } else y_offset_ptr = nk_find_value(win, id_hash+1);
  182. if (x_offset)
  183. *x_offset = *x_offset_ptr;
  184. if (y_offset)
  185. *y_offset = *y_offset_ptr;
  186. }
  187. NK_API void
  188. nk_group_set_scroll(struct nk_context *ctx, const char *id, nk_uint x_offset, nk_uint y_offset)
  189. {
  190. int id_len;
  191. nk_hash id_hash;
  192. struct nk_window *win;
  193. nk_uint *x_offset_ptr;
  194. nk_uint *y_offset_ptr;
  195. NK_ASSERT(ctx);
  196. NK_ASSERT(id);
  197. NK_ASSERT(ctx->current);
  198. NK_ASSERT(ctx->current->layout);
  199. if (!ctx || !ctx->current || !ctx->current->layout || !id)
  200. return;
  201. /* find persistent group scrollbar value */
  202. win = ctx->current;
  203. id_len = (int)nk_strlen(id);
  204. id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
  205. x_offset_ptr = nk_find_value(win, id_hash);
  206. if (!x_offset_ptr) {
  207. x_offset_ptr = nk_add_value(ctx, win, id_hash, 0);
  208. y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0);
  209. NK_ASSERT(x_offset_ptr);
  210. NK_ASSERT(y_offset_ptr);
  211. if (!x_offset_ptr || !y_offset_ptr) return;
  212. *x_offset_ptr = *y_offset_ptr = 0;
  213. } else y_offset_ptr = nk_find_value(win, id_hash+1);
  214. *x_offset_ptr = x_offset;
  215. *y_offset_ptr = y_offset;
  216. }