浏览代码

Added addition `nk_group` and new `nk_list_view`

Added additional `nk_group` version which uses an external scrollbar
offset instead of internally managing the memory. In addition
`nk_list_view` is introduced which allows drawing huge lists inside a
`nk_group`(#269).
vurtun 9 年之前
父节点
当前提交
42efd8214f
共有 2 个文件被更改,包括 157 次插入46 次删除
  1. 7 0
      CHANGELOG.md
  2. 150 46
      nuklear.h

+ 7 - 0
CHANGELOG.md

@@ -1,4 +1,11 @@
 # Changelog
 # Changelog
+- 2016/11/09 (1.180)- Added additional `nk_group` version to support external scrollbar
+                        offset storage. Main advantage is that you can externalize
+                        the memory management for the offset. It could also be helpful
+                        if you have a hash collision in `nk_group_begin` but really
+                        want the name. In addition I added `nk_list_view` which allows
+                        to draw big lists inside a group without actually having to
+                        commit the whole list to nuklear (issue #269).
 - 2016/10/30 (1.171)- Fixed clipping rectangle bug inside `nk_draw_list`
 - 2016/10/30 (1.171)- Fixed clipping rectangle bug inside `nk_draw_list`
 - 2016/10/29 (1.170)- Pulled `nk_panel` memory management into nuklear and out of
 - 2016/10/29 (1.170)- Pulled `nk_panel` memory management into nuklear and out of
                         the hands of the user. From now on users don't have to care
                         the hands of the user. From now on users don't have to care

+ 150 - 46
nuklear.h

@@ -305,6 +305,10 @@ extern "C" {
 #endif
 #endif
 #endif
 #endif
 
 
+#define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
+#define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
+#define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
+
 /*
 /*
  * ===============================================================
  * ===============================================================
  *
  *
@@ -438,8 +442,8 @@ typedef union {void *ptr; int id;} nk_handle;
 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
 struct nk_scroll {unsigned short x, y;};
 struct nk_scroll {unsigned short x, y;};
-enum nk_heading {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT};
 
 
+enum nk_heading {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT};
 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER};
 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER};
 enum nk_modify          {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true};
 enum nk_modify          {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true};
 enum nk_orientation     {NK_VERTICAL, NK_HORIZONTAL};
 enum nk_orientation     {NK_VERTICAL, NK_HORIZONTAL};
@@ -482,6 +486,16 @@ struct nk_convert_config {
     nk_size vertex_alignment; /* vertex alignment: Can be optained by NK_ALIGNOF */
     nk_size vertex_alignment; /* vertex alignment: Can be optained by NK_ALIGNOF */
 };
 };
 
 
+struct nk_list_view {
+/* public: */
+    int begin, end, count;
+/* private: */
+    int total_height;
+    struct nk_context *ctx;
+    nk_ushort *scroll_pointer;
+    nk_ushort scroll_value;
+};
+
 enum nk_symbol_type {
 enum nk_symbol_type {
     NK_SYMBOL_NONE,
     NK_SYMBOL_NONE,
     NK_SYMBOL_X,
     NK_SYMBOL_X,
@@ -737,6 +751,12 @@ NK_API float                    nk_layout_ratio_from_pixel(struct nk_context*, f
 NK_API int                      nk_group_begin(struct nk_context*, const char *title, nk_flags);
 NK_API int                      nk_group_begin(struct nk_context*, const char *title, nk_flags);
 NK_API void                     nk_group_end(struct nk_context*);
 NK_API void                     nk_group_end(struct nk_context*);
 
 
+NK_API int                      nk_group_scrolled_begin(struct nk_context*, struct nk_scroll*, const char *title, nk_flags);
+NK_API void                     nk_group_scrolled_end(struct nk_context*);
+
+NK_API int                      nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
+NK_API void                     nk_list_view_end(struct nk_list_view*);
+
 /* Layout: Tree */
 /* Layout: Tree */
 #define                         nk_tree_push(ctx, type, title, state) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
 #define                         nk_tree_push(ctx, type, title, state) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
 #define                         nk_tree_push_id(ctx, type, title, state, id) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
 #define                         nk_tree_push_id(ctx, type, title, state, id) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
@@ -2754,7 +2774,7 @@ struct nk_window {
  *
  *
  * Nuklear has a stack for style_items, float properties, vector properties, 
  * Nuklear has a stack for style_items, float properties, vector properties, 
  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
- * which can be changed in compile time.
+ * which can be changed at compile time.
  */
  */
 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
@@ -2825,7 +2845,8 @@ struct nk_configuration_stacks {
 /*==============================================================
 /*==============================================================
  *                          CONTEXT
  *                          CONTEXT
  * =============================================================*/
  * =============================================================*/
-#define NK_VALUE_PAGE_CAPACITY ((sizeof(struct nk_window) / sizeof(nk_uint)) / 2)
+#define NK_VALUE_PAGE_CAPACITY \
+    ((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint)) / 2)
 
 
 struct nk_table {
 struct nk_table {
     unsigned int seq;
     unsigned int seq;
@@ -2847,7 +2868,7 @@ struct nk_page_element {
 };
 };
 
 
 struct nk_page {
 struct nk_page {
-    unsigned size;
+    unsigned int size;
     struct nk_page *next;
     struct nk_page *next;
     struct nk_page_element win[1];
     struct nk_page_element win[1];
 };
 };
@@ -2884,7 +2905,7 @@ struct nk_context {
     nk_handle userdata;
     nk_handle userdata;
 #endif
 #endif
     /* text editor objects are quite big because of an internal
     /* text editor objects are quite big because of an internal
-     * undo/redo stack. Therefore does not make sense to have one for
+     * undo/redo stack. Therefore it does not make sense to have one for
      * each window for temporary use cases, so I only provide *one* instance
      * each window for temporary use cases, so I only provide *one* instance
      * for all windows. This works because the content is cleared anyway */
      * for all windows. This works because the content is cleared anyway */
     struct nk_text_edit text_edit;
     struct nk_text_edit text_edit;
@@ -2907,10 +2928,6 @@ struct nk_context {
 /* ==============================================================
 /* ==============================================================
  *                          MATH
  *                          MATH
  * =============================================================== */
  * =============================================================== */
-#define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
-#define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
-#define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
-
 #define NK_PI 3.141592654f
 #define NK_PI 3.141592654f
 #define NK_UTF_INVALID 0xFFFD
 #define NK_UTF_INVALID 0xFFFD
 #define NK_MAX_FLOAT_PRECISION 2
 #define NK_MAX_FLOAT_PRECISION 2
@@ -16968,10 +16985,10 @@ nk_add_value(struct nk_context *ctx, struct nk_window *win,
 NK_INTERN nk_uint*
 NK_INTERN nk_uint*
 nk_find_value(struct nk_window *win, nk_hash name)
 nk_find_value(struct nk_window *win, nk_hash name)
 {
 {
-    unsigned short size = win->table_size;
+    nk_ushort size = win->table_size;
     struct nk_table *iter = win->tables;
     struct nk_table *iter = win->tables;
     while (iter) {
     while (iter) {
-        unsigned short i = 0;
+        nk_ushort i = 0;
         for (i = 0; i < size; ++i) {
         for (i = 0; i < size; ++i) {
             if (iter->keys[i] == name) {
             if (iter->keys[i] == name) {
                 iter->seq = win->seq;
                 iter->seq = win->seq;
@@ -19241,6 +19258,7 @@ nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
     NK_ASSERT(text);
     NK_ASSERT(text);
     NK_ASSERT(flags);
     NK_ASSERT(flags);
     if (!ctx || !text || !flags) return 0;
     if (!ctx || !text || !flags) return 0;
+
     active = (int)((*flags & value) & value);
     active = (int)((*flags & value) & value);
     if (nk_checkbox_text(ctx, text, len, &active)) {
     if (nk_checkbox_text(ctx, text, len, &active)) {
         if (active) *flags |= value;
         if (active) *flags |= value;
@@ -19498,8 +19516,8 @@ nk_edit_string(struct nk_context *ctx, nk_flags flags,
         win->edit.sel_start = edit->select_start;
         win->edit.sel_start = edit->select_start;
         win->edit.sel_end = edit->select_end;
         win->edit.sel_end = edit->select_end;
         win->edit.mode = edit->mode;
         win->edit.mode = edit->mode;
-        win->edit.scrollbar.x = (unsigned short)edit->scrollbar.x;
-        win->edit.scrollbar.y = (unsigned short)edit->scrollbar.y;
+        win->edit.scrollbar.x = (nk_ushort)edit->scrollbar.x;
+        win->edit.scrollbar.y = (nk_ushort)edit->scrollbar.y;
     }
     }
     return state;
     return state;
 }
 }
@@ -19964,8 +19982,7 @@ nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
 
 
         bounds.x = g->slots[slot].last.x - 2;
         bounds.x = g->slots[slot].last.x - 2;
         bounds.y = g->slots[slot].last.y - 2;
         bounds.y = g->slots[slot].last.y - 2;
-        bounds.w = 4;
-        bounds.h = 4;
+        bounds.w = bounds.h = 4;
 
 
         color = g->slots[slot].color;
         color = g->slots[slot].color;
         if (!(layout->flags & NK_WINDOW_ROM) &&
         if (!(layout->flags & NK_WINDOW_ROM) &&
@@ -19988,8 +20005,7 @@ nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
 
 
     bounds.x = cur.x - 3;
     bounds.x = cur.x - 3;
     bounds.y = cur.y - 3;
     bounds.y = cur.y - 3;
-    bounds.w = 6;
-    bounds.h = 6;
+    bounds.w = bounds.h = 6;
 
 
     /* user selection of current data point */
     /* user selection of current data point */
     if (!(layout->flags & NK_WINDOW_ROM)) {
     if (!(layout->flags & NK_WINDOW_ROM)) {
@@ -20158,40 +20174,21 @@ nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata
  *
  *
  * --------------------------------------------------------------*/
  * --------------------------------------------------------------*/
 NK_API int
 NK_API int
-nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
+nk_group_scrolled_begin(struct nk_context *ctx,
+    struct nk_scroll *scroll, const char *title, nk_flags flags)
 {
 {
-    struct nk_window *win;
-    const struct nk_rect *c;
-    union {struct nk_scroll *s; nk_uint *i;} value;
-    struct nk_window panel;
     struct nk_rect bounds;
     struct nk_rect bounds;
-    nk_hash title_hash;
-    int title_len;
-
-    NK_ASSERT(ctx);
-    NK_ASSERT(title);
-    NK_ASSERT(ctx->current);
-    NK_ASSERT(ctx->current->layout);
-    if (!ctx || !ctx->current || !ctx->current->layout || !title)
-        return 0;
+    struct nk_window panel;
+    struct nk_window *win;
 
 
-    /* allocate space for the group panel inside the panel */
     win = ctx->current;
     win = ctx->current;
-    c = &win->layout->clip;
     nk_panel_alloc_space(&bounds, ctx);
     nk_panel_alloc_space(&bounds, ctx);
 
 
-    /* find persistent group scrollbar value */
-    title_len = (int)nk_strlen(title);
-    title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
-    value.i = nk_find_value(win, title_hash);
-    if (!value.i) {
-        value.i = nk_add_value(ctx, win, title_hash, 0);
-        *value.i = 0;
-    }
+    {const struct nk_rect *c = &win->layout->clip;
     if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
     if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
         !(flags & NK_WINDOW_MOVABLE)) {
         !(flags & NK_WINDOW_MOVABLE)) {
         return 0;
         return 0;
-    }
+    }}
     if (win->flags & NK_WINDOW_ROM)
     if (win->flags & NK_WINDOW_ROM)
         flags |= NK_WINDOW_ROM;
         flags |= NK_WINDOW_ROM;
 
 
@@ -20199,8 +20196,8 @@ nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
     nk_zero(&panel, sizeof(panel));
     nk_zero(&panel, sizeof(panel));
     panel.bounds = bounds;
     panel.bounds = bounds;
     panel.flags = flags;
     panel.flags = flags;
-    panel.scrollbar.x = (unsigned short)value.s->x;
-    panel.scrollbar.y = (unsigned short)value.s->y;
+    panel.scrollbar.x = scroll->x;
+    panel.scrollbar.y = scroll->y;
     panel.buffer = win->buffer;
     panel.buffer = win->buffer;
     panel.layout = (struct nk_panel*)nk_create_panel(ctx);
     panel.layout = (struct nk_panel*)nk_create_panel(ctx);
     ctx->current = &panel;
     ctx->current = &panel;
@@ -20208,15 +20205,16 @@ nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
 
 
     win->buffer = panel.buffer;
     win->buffer = panel.buffer;
     win->buffer.clip = panel.layout->clip;
     win->buffer.clip = panel.layout->clip;
-    panel.layout->offset = value.s;
+    panel.layout->offset = scroll;
     panel.layout->parent = win->layout;
     panel.layout->parent = win->layout;
     win->layout = panel.layout;
     win->layout = panel.layout;
     ctx->current = win;
     ctx->current = win;
     return 1;
     return 1;
+
 }
 }
 
 
 NK_API void
 NK_API void
-nk_group_end(struct nk_context *ctx)
+nk_group_scrolled_end(struct nk_context *ctx)
 {
 {
     struct nk_window *win;
     struct nk_window *win;
     struct nk_panel *parent;
     struct nk_panel *parent;
@@ -20278,6 +20276,112 @@ nk_group_end(struct nk_context *ctx)
     return;
     return;
 }
 }
 
 
+NK_API int
+nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
+{
+    int title_len;
+    nk_hash title_hash;
+    union {struct nk_scroll *s; nk_uint *i;} value;
+    struct nk_window *win;
+
+    NK_ASSERT(ctx);
+    NK_ASSERT(title);
+    NK_ASSERT(ctx->current);
+    NK_ASSERT(ctx->current->layout);
+    if (!ctx || !ctx->current || !ctx->current->layout || !title)
+        return 0;
+
+    /* find persistent group scrollbar value */
+    win = ctx->current;
+    title_len = (int)nk_strlen(title);
+    title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
+    value.i = nk_find_value(win, title_hash);
+    if (!value.i) {
+        value.i = nk_add_value(ctx, win, title_hash, 0);
+        NK_ASSERT(value.i);
+        if (!value.i) return 0;
+        *value.i = 0;
+    }
+    return nk_group_scrolled_begin(ctx, value.s, title, flags);
+}
+
+NK_API void
+nk_group_end(struct nk_context *ctx)
+{
+    nk_group_scrolled_end(ctx);
+}
+
+NK_API int
+nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
+    const char *title, nk_flags flags, int row_height, int row_count)
+{
+    int title_len;
+    nk_hash title_hash;
+    union {struct nk_scroll *s; nk_uint *i;} value;
+
+    int result;
+    struct nk_window *win;
+    struct nk_panel *layout;
+    const struct nk_style *style;
+    struct nk_vec2 item_spacing;
+
+    NK_ASSERT(ctx);
+    NK_ASSERT(view);
+    NK_ASSERT(title);
+    if (!ctx || !view || !title) return 0;
+
+    win = ctx->current;
+    layout = win->layout;
+    style = &ctx->style;
+    item_spacing = style->window.spacing;
+    row_height += NK_MAX(0, (int)item_spacing.y);
+
+    /* find persistent group scrollbar offset */
+    title_len = (int)nk_strlen(title);
+    title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
+    value.i = nk_find_value(win, title_hash);
+    if (!value.i) {
+        value.i = nk_add_value(ctx, win, title_hash, 0);
+        NK_ASSERT(value.i);
+        if (!value.i) return 0;
+        *value.i = 0;
+    }
+    view->scroll_value = value.s->y;
+    view->scroll_pointer = &value.s->y;
+
+    value.s->y = 0;
+    result = nk_group_scrolled_begin(ctx, value.s, title, flags);
+    win = ctx->current;
+    layout = win->layout;
+ 
+    view->total_height = row_height * NK_MAX(row_count,1);
+    view->begin = (int)NK_MAX((view->scroll_value / (float)row_height), 0.0f);
+    view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height), 0);
+    view->end = view->begin + view->count;
+    view->ctx = ctx;
+    return result;
+}
+
+NK_API void
+nk_list_view_end(struct nk_list_view *view)
+{
+    struct nk_context *ctx;
+    struct nk_window *win;
+    struct nk_panel *layout;
+
+    NK_ASSERT(view);
+    NK_ASSERT(view->ctx);
+    NK_ASSERT(view->scroll_pointer);
+    if (!view || !view->ctx) return;
+
+    ctx = view->ctx;
+    win = ctx->current;
+    layout = win->layout;
+    layout->at_y = layout->bounds.y + view->total_height;
+    *view->scroll_pointer += view->scroll_value;
+    nk_group_end(view->ctx);
+}
+
 /* --------------------------------------------------------------
 /* --------------------------------------------------------------
  *
  *
  *                          POPUP
  *                          POPUP