diff --git a/demo/x11/main.c b/demo/x11/main.c index df39b1a..182e9db 100644 --- a/demo/x11/main.c +++ b/demo/x11/main.c @@ -124,7 +124,7 @@ main(void) /* GUI */ {struct nk_panel layout; - if (nk_begin(ctx, &layout, "Demo", nk_rect(50, 50, 200, 300), + if (nk_begin(ctx, &layout, "Demo", nk_rect(50, 50, 200, 200), NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) { diff --git a/example/Makefile b/example/Makefile index 01f7285..e1b0419 100644 --- a/example/Makefile +++ b/example/Makefile @@ -32,3 +32,8 @@ extended: rm -f bin/extended $(OBJS) $(CC) $(CFLAGS) -o bin/extended extended.c $(LIBS) +calculator: + @mkdir -p bin + rm -f bin/calculator $(OBJS) + $(CC) $(CFLAGS) -o bin/calculator calculator.c $(LIBS) + diff --git a/example/calculator.c b/example/calculator.c new file mode 100644 index 0000000..551252e --- /dev/null +++ b/example/calculator.c @@ -0,0 +1,427 @@ +/* nuklear - v1.00 - public domain */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define NK_INCLUDE_FIXED_TYPES +#define NK_INCLUDE_STANDARD_IO +#define NK_INCLUDE_DEFAULT_ALLOCATOR +#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT +#define NK_INCLUDE_FONT_BAKING +#define NK_INCLUDE_DEFAULT_FONT +#define NK_IMPLEMENTATION +#include "../nuklear.h" + +/* macros */ +#define WINDOW_WIDTH 800 +#define WINDOW_HEIGHT 600 + +#define MAX_VERTEX_MEMORY 512 * 1024 +#define MAX_ELEMENT_MEMORY 128 * 1024 +#define UNUSED(a) (void)a + +/* =============================================================== + * + * DEVICE + * + * ===============================================================*/ +struct device { + struct nk_buffer cmds; + struct nk_draw_null_texture null; + GLuint vbo, vao, ebo; + GLuint prog; + GLuint vert_shdr; + GLuint frag_shdr; + GLint attrib_pos; + GLint attrib_uv; + GLint attrib_col; + GLint uniform_tex; + GLint uniform_proj; + GLuint font_tex; +}; + +static void +device_init(struct device *dev) +{ + GLint status; + static const GLchar *vertex_shader = + "#version 300 es\n" + "uniform mat4 ProjMtx;\n" + "in vec2 Position;\n" + "in vec2 TexCoord;\n" + "in vec4 Color;\n" + "out vec2 Frag_UV;\n" + "out vec4 Frag_Color;\n" + "void main() {\n" + " Frag_UV = TexCoord;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" + "}\n"; + static const GLchar *fragment_shader = + "#version 300 es\n" + "precision mediump float;\n" + "uniform sampler2D Texture;\n" + "in vec2 Frag_UV;\n" + "in vec4 Frag_Color;\n" + "out vec4 Out_Color;\n" + "void main(){\n" + " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" + "}\n"; + + nk_buffer_init_default(&dev->cmds); + dev->prog = glCreateProgram(); + dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); + dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); + glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); + glCompileShader(dev->vert_shdr); + glCompileShader(dev->frag_shdr); + glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); + assert(status == GL_TRUE); + glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); + assert(status == GL_TRUE); + glAttachShader(dev->prog, dev->vert_shdr); + glAttachShader(dev->prog, dev->frag_shdr); + glLinkProgram(dev->prog); + glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); + assert(status == GL_TRUE); + + dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); + dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); + dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); + dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); + dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); + + { + /* buffer setup */ + GLsizei vs = sizeof(struct nk_draw_vertex); + size_t vp = offsetof(struct nk_draw_vertex, position); + size_t vt = offsetof(struct nk_draw_vertex, uv); + size_t vc = offsetof(struct nk_draw_vertex, col); + + glGenBuffers(1, &dev->vbo); + glGenBuffers(1, &dev->ebo); + glGenVertexArrays(1, &dev->vao); + + glBindVertexArray(dev->vao); + glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); + + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); + } + + glBindTexture(GL_TEXTURE_2D, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +static void +device_upload_atlas(struct device *dev, const void *image, int width, int height) +{ + glGenTextures(1, &dev->font_tex); + glBindTexture(GL_TEXTURE_2D, dev->font_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image); +} + +static void +device_shutdown(struct device *dev) +{ + glDetachShader(dev->prog, dev->vert_shdr); + glDetachShader(dev->prog, dev->frag_shdr); + glDeleteShader(dev->vert_shdr); + glDeleteShader(dev->frag_shdr); + glDeleteProgram(dev->prog); + glDeleteTextures(1, &dev->font_tex); + glDeleteBuffers(1, &dev->vbo); + glDeleteBuffers(1, &dev->ebo); + nk_buffer_free(&dev->cmds); +} + +static void +device_draw(struct device *dev, struct nk_context *ctx, int width, int height, + enum nk_anti_aliasing AA) +{ + GLint last_prog, last_tex; + GLint last_ebo, last_vbo, last_vao; + GLfloat ortho[4][4] = { + {2.0f, 0.0f, 0.0f, 0.0f}, + {0.0f,-2.0f, 0.0f, 0.0f}, + {0.0f, 0.0f,-1.0f, 0.0f}, + {-1.0f,1.0f, 0.0f, 1.0f}, + }; + ortho[0][0] /= (GLfloat)width; + ortho[1][1] /= (GLfloat)height; + + /* save previous opengl state */ + glGetIntegerv(GL_CURRENT_PROGRAM, &last_prog); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_tex); + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_vao); + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_ebo); + glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vbo); + + /* setup global state */ + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + /* setup program */ + glUseProgram(dev->prog); + glUniform1i(dev->uniform_tex, 0); + glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); + { + /* convert from command queue into draw list and draw to screen */ + const struct nk_draw_command *cmd; + void *vertices, *elements; + const nk_draw_index *offset = NULL; + + /* allocate vertex and element buffer */ + glBindVertexArray(dev->vao); + glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + + glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW); + + /* load draw vertices & elements directly into vertex + element buffer */ + vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + { + /* fill converting configuration */ + struct nk_convert_config config; + memset(&config, 0, sizeof(config)); + config.global_alpha = 1.0f; + config.shape_AA = AA; + config.line_AA = AA; + config.circle_segment_count = 22; + config.curve_segment_count = 22; + config.arc_segment_count = 22; + config.null = dev->null; + + /* setup buffers to load vertices and elements */ + {struct nk_buffer vbuf, ebuf; + nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY); + nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY); + nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);} + } + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + /* iterate over and execute each draw command */ + nk_draw_foreach(cmd, ctx, &dev->cmds) { + if (!cmd->elem_count) continue; + glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); + glScissor((GLint)cmd->clip_rect.x, + height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h), + (GLint)cmd->clip_rect.w, (GLint)cmd->clip_rect.h); + glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); + offset += cmd->elem_count; + } + nk_clear(ctx); + } + + /* restore old state */ + glUseProgram((GLuint)last_prog); + glBindTexture(GL_TEXTURE_2D, (GLuint)last_tex); + glBindBuffer(GL_ARRAY_BUFFER, (GLuint)last_vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)last_ebo); + glBindVertexArray((GLuint)last_vao); + glDisable(GL_SCISSOR_TEST); +} + + +/* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/ +static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);} +static void text_input(GLFWwindow *win, unsigned int codepoint) +{nk_input_unicode((struct nk_context*)glfwGetWindowUserPointer(win), codepoint);} +static void scroll_input(GLFWwindow *win, double _, double yoff) +{UNUSED(_);nk_input_scroll((struct nk_context*)glfwGetWindowUserPointer(win), (float)yoff);} + +int main(int argc, char *argv[]) +{ + /* Platform */ + static GLFWwindow *win; + int width = 0, height = 0; + + /* GUI */ + struct device device; + struct nk_context ctx; + struct nk_font *font; + struct nk_font_atlas atlas; + + /* GLFW */ + glfwSetErrorCallback(error_callback); + if (!glfwInit()) { + fprintf(stdout, "[GFLW] failed to init!\n"); + exit(1); + } + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +#ifdef __APPLE__ + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); +#endif + win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL); + glfwMakeContextCurrent(win); + glfwSetWindowUserPointer(win, &ctx); + glfwSetCharCallback(win, text_input); + glfwSetScrollCallback(win, scroll_input); + + /* OpenGL */ + glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); + glewExperimental = 1; + if (glewInit() != GLEW_OK) { + fprintf(stderr, "Failed to setup GLEW\n"); + exit(1); + } + + {/* GUI */ + device_init(&device); + {const void *image; int w, h; + const char *font_path = (argc > 1) ? argv[1]: 0; + nk_font_atlas_init_default(&atlas); + nk_font_atlas_begin(&atlas); + if (font_path) font = nk_font_atlas_add_from_file(&atlas, font_path, 14.0f, NULL); + else font = nk_font_atlas_add_default(&atlas, 14.0f, NULL); + image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_RGBA32); + device_upload_atlas(&device, image, w, h); + nk_font_atlas_end(&atlas, nk_handle_id((int)device.font_tex), &device.null);} + nk_init_default(&ctx, &font->handle);} + + while (!glfwWindowShouldClose(win)) + { + /* Input */ + {double x, y; + nk_input_begin(&ctx); + glfwPollEvents(); + nk_input_key(&ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS); + if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || + glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL)) { + nk_input_key(&ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_P) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_SHIFT, 1); + } else { + nk_input_key(&ctx, NK_KEY_COPY, 0); + nk_input_key(&ctx, NK_KEY_PASTE, 0); + nk_input_key(&ctx, NK_KEY_CUT, 0); + nk_input_key(&ctx, NK_KEY_SHIFT, 0); + } + glfwGetCursorPos(win, &x, &y); + nk_input_motion(&ctx, (int)x, (int)y); + nk_input_button(&ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS); + nk_input_button(&ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS); + nk_input_button(&ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS); + nk_input_end(&ctx);} + + /* GUI */ + {struct nk_panel layout; + if (nk_begin(&ctx, &layout, "Calculator", nk_rect(10, 10, 180, 250), + NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE)) + { + static int set = 0, prev = 0, op = 0; + static const char numbers[] = "789456123"; + static const char ops[] = "+-*/"; + static double a = 0, b = 0; + static double *current = &a; + + size_t i = 0; + int solve = 0; + {int len; char buffer[256]; + nk_layout_row_dynamic(&ctx, 35, 1); + len = snprintf(buffer, 256, "%.2f", *current); + nk_edit_string(&ctx, NK_EDIT_SIMPLE, buffer, &len, 255, nk_filter_float); + buffer[len] = 0; + *current = atof(buffer);} + + nk_layout_row_dynamic(&ctx, 35, 4); + for (i = 0; i < 16; ++i) { + if (i >= 12 && i < 15) { + if (i > 12) continue; + if (nk_button_label(&ctx, "C", NK_BUTTON_DEFAULT)) { + a = b = op = 0; current = &a; set = 0; + } if (nk_button_label(&ctx, "0", NK_BUTTON_DEFAULT)) { + *current = *current*10.0f; set = 0; + } + if (nk_button_label(&ctx, "=", NK_BUTTON_DEFAULT)) { + solve = 1; prev = op; op = 0; + } + } else if (((i+1) % 4)) { + if (nk_button_text(&ctx, &numbers[(i/4)*3+i%4], 1, NK_BUTTON_DEFAULT)) { + *current = *current * 10.0f + numbers[(i/4)*3+i%4] - '0'; + set = 0; + } + } else if (nk_button_text(&ctx, &ops[i/4], 1, NK_BUTTON_DEFAULT)) { + if (!set) { + if (current != &b) { + current = &b; + } else { + prev = op; + solve = 1; + } + } + op = ops[i/4]; + set = 1; + } + } + if (solve) { + if (prev == '+') a = a + b; + if (prev == '-') a = a - b; + if (prev == '*') a = a * b; + if (prev == '/') a = a / b; + current = &a; + if (set) current = &b; + b = 0; set = 0; + } + } + nk_end(&ctx);} + + /* Draw */ + glfwGetWindowSize(win, &width, &height); + glViewport(0, 0, width, height); + glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0.2f, 0.2f, 0.2f, 1.0f); + device_draw(&device, &ctx, width, height, NK_ANTI_ALIASING_ON); + glfwSwapBuffers(win); + } + + nk_font_atlas_clear(&atlas); + nk_free(&ctx); + device_shutdown(&device); + glfwTerminate(); + return 0; +} + diff --git a/example/overview.c b/example/overview.c index ded95e6..827347f 100644 --- a/example/overview.c +++ b/example/overview.c @@ -116,10 +116,9 @@ overview_window(struct nk_context *ctx) if (nk_popup_begin(ctx, &popup, NK_POPUP_STATIC, "About", NK_WINDOW_CLOSABLE, s)) { nk_layout_row_dynamic(ctx, 20, 1); - nk_label(ctx, "nuklear", NK_TEXT_LEFT); + nk_label(ctx, "Nuklear", NK_TEXT_LEFT); nk_label(ctx, "By Micha Mettke", NK_TEXT_LEFT); - nk_label(ctx, "nuklear is licensed under the zlib License.", NK_TEXT_LEFT); - nk_label(ctx, "See LICENSE for more information", NK_TEXT_LEFT); + nk_label(ctx, "nuklear is licensed under the public domain License.", NK_TEXT_LEFT); nk_popup_end(ctx); } else show_app_about = nk_false; } diff --git a/nuklear.h b/nuklear.h index 6ed335c..2404636 100644 --- a/nuklear.h +++ b/nuklear.h @@ -657,7 +657,7 @@ NK_API void nk_plot_function(struct nk_context*, enum nk_cha /* Popups */ NK_API int nk_popup_begin(struct nk_context*, struct nk_panel*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds); NK_API void nk_popup_close(struct nk_context*); -NK_API void nk_popup_end(struct nk_context*); +NK_API void nk_popup_end(struct nk_context*); /* Combobox */ NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height); @@ -15273,6 +15273,17 @@ nk_window_set_focus(struct nk_context *ctx, const char *name) * PANEL * * --------------------------------------------------------------*/ +static int +nk_window_has_header(struct nk_window *win, const char *title) +{ + /* window header state */ + int active = 0; + active = (win->flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE)); + active = active || (win->flags & NK_WINDOW_TITLE); + active = active && !(win->flags & NK_WINDOW_HIDDEN) && title; + return active; +} + NK_INTERN int nk_panel_begin(struct nk_context *ctx, const char *title) { @@ -15312,16 +15323,24 @@ nk_panel_begin(struct nk_context *ctx, const char *title) if (win->flags & NK_WINDOW_HIDDEN) return 0; - /* move panel position if requested */ - layout->header_h = font->height + 2 * style->window.header.padding.y; - layout->header_h += 2 * style->window.header.label_padding.y; +#ifdef NK_INCLUDE_COMMAND_USERDATA + win->buffer.userdata = ctx->userdata; +#endif + + /* window dragging */ if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) { int incursor; struct nk_rect move; move.x = win->bounds.x; move.y = win->bounds.y; move.w = win->bounds.w; + move.h = layout->header_h; + if (nk_window_has_header(win, title)) { + move.h = font->height + 2.0f * style->window.header.padding.y; + move.h = 2.0f * style->window.header.label_padding.y; + } else move.h = window_padding.y + item_spacing.y; + incursor = nk_input_is_mouse_prev_hovering_rect(in, move); if (nk_input_is_mouse_down(in, NK_BUTTON_LEFT) && incursor) { win->bounds.x = win->bounds.x + in->mouse.delta.x; @@ -15329,10 +15348,6 @@ nk_panel_begin(struct nk_context *ctx, const char *title) } } -#ifdef NK_INCLUDE_COMMAND_USERDATA - win->buffer.userdata = ctx->userdata; -#endif - /* panel space with border */ if (win->flags & NK_WINDOW_BORDER) { if (!(win->flags & NK_WINDOW_SUB)) @@ -15372,7 +15387,7 @@ nk_panel_begin(struct nk_context *ctx, const char *title) layout->row.height = 0; } else { layout->header_h = 0; - layout->row.height = item_spacing.y; + layout->row.height = item_spacing.y + window_padding.y; } /* calculate window footer height */ @@ -15384,15 +15399,11 @@ nk_panel_begin(struct nk_context *ctx, const char *title) /* calculate the window size */ if (!(win->flags & NK_WINDOW_NO_SCROLLBAR)) layout->width = layout->bounds.w - scrollbar_size.x; - layout->height = layout->bounds.h - (layout->header_h + 2 * item_spacing.y); + layout->height = layout->bounds.h - (layout->header_h + item_spacing.y + window_padding.y); layout->height -= layout->footer_h; - /* window header state */ - header_active = (win->flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE)); - header_active = header_active || (win->flags & NK_WINDOW_TITLE); - header_active = header_active && !(win->flags & NK_WINDOW_HIDDEN) && title; - /* window header */ + header_active = nk_window_has_header(win, title); if (header_active) { struct nk_rect header; @@ -15408,7 +15419,7 @@ nk_panel_begin(struct nk_context *ctx, const char *title) /* calculate correct header height */ layout->header_h = font->height + 2.0f * style->window.header.padding.y; layout->header_h += 2.0f * style->window.header.label_padding.y; - layout->row.height += layout->header_h + style->window.padding.y; + layout->row.height += layout->header_h; header.h = layout->header_h + 0.5f; /* update window height */ @@ -15521,34 +15532,6 @@ nk_panel_begin(struct nk_context *ctx, const char *title) layout->bounds.w, layout->row.height + window_padding.y), 0, style->window.background); } - - /* draw top window border line */ - if (layout->flags & NK_WINDOW_BORDER) { - struct nk_color border; - - /* select correct border color */ - if (!(win->flags & NK_WINDOW_SUB)) - border = style->window.border_color; - else if (win->flags & NK_WINDOW_COMBO) - border = style->window.combo_border_color; - else if (win->flags & NK_WINDOW_CONTEXTUAL) - border = style->window.contextual_border_color; - else if (win->flags & NK_WINDOW_MENU) - border = style->window.menu_border_color; - else if (win->flags & NK_WINDOW_GROUP) - border = style->window.group_border_color; - else if (win->flags & NK_WINDOW_TOOLTIP) - border = style->window.tooltip_border_color; - else border = style->window.border_color; - - /* draw border */ - nk_stroke_line(out, - win->bounds.x + layout->border/2.0f, - win->bounds.y + layout->border/2.0f, - win->bounds.x + win->bounds.w - layout->border, - win->bounds.y + layout->border/2.0f, - style->window.border, border); - } { /* calculate and set the window clipping rectangle*/ struct nk_rect clip; @@ -15799,6 +15782,13 @@ nk_panel_end(struct nk_context *ctx) window->bounds.y + layout->header_h - layout->border, layout->border, border); + /* draw border top */ + nk_stroke_line(out, window->bounds.x + layout->border/2.0f, + window->bounds.y + layout->border/2.0f, + window->bounds.x + window->bounds.w - layout->border, + window->bounds.y + layout->border/2.0f, + style->window.border, border); + /* draw bottom border */ nk_stroke_line(out, window->bounds.x + layout->border/2.0f, padding_y - layout->border, @@ -16346,13 +16336,10 @@ nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, layout->row.item_width : layout->row.ratio[layout->row.index]; item_spacing = (float)layout->row.index * spacing.x; - if (layout->row.index < layout->row.columns-1) - item_width = (ratio * panel_space) - spacing.x; - else item_width = (ratio * panel_space); - + item_width = (ratio * panel_space); item_offset = layout->row.item_offset; if (modify) { - layout->row.item_offset += item_width + spacing.x; + layout->row.item_offset += item_width; layout->row.filled += ratio; } } break; @@ -16368,7 +16355,7 @@ nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, item_offset = layout->row.item_offset; item_spacing = (float)layout->row.index * spacing.x; if (modify) { - layout->row.item_offset += item_width + spacing.x; + layout->row.item_offset += item_width; layout->row.index = 0; } } break; @@ -16389,8 +16376,8 @@ nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, item_spacing = (float)layout->row.index * spacing.x; item_width = layout->row.ratio[layout->row.index]; item_offset = layout->row.item_offset; - if (modify) layout->row.item_offset += item_width + spacing.x; - } break; + if (modify) layout->row.item_offset += item_width; + } break; default: NK_ASSERT(0); break; };