From 9b098ff6034508e3600448f14913d8fd22ed91bc Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Jan 18 2024 17:35:03 +0000 Subject: nuklear examples --- diff --git a/nuklear-calc.c b/nuklear-calc.c new file mode 100644 index 0000000..1e220d3 --- /dev/null +++ b/nuklear-calc.c @@ -0,0 +1,97 @@ + + +#include + + +nk_heli hnk; +struct nk_context *nk; + + +void init() { + nk_heli_init(&hnk, 12); + nk = &hnk.context; +} + + +void deinit() { + nk_heli_deinit(&hnk); +} + + +void draw() { + if (nk_begin(nk, "Calculator", nk_rect(10, 10, 180, 250), + NK_WINDOW_BORDER|NK_WINDOW_TITLE|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE)) + { + static double a = 0, b = 0, c = 0, *cur = &a; + static char sign = 0; + + nk_layout_row_dynamic(nk, 35, 1); + char buffer[256]; + int len = snprintf(buffer, 256, "%g", *cur); + nk_edit_string(nk, NK_EDIT_SIMPLE, buffer, &len, 255, nk_filter_float); + + nk_layout_row_dynamic(nk, 35, 4); + int num = -1; + + if (nk_button_label(nk, "7")) num = 7; + if (nk_button_label(nk, "8")) num = 8; + if (nk_button_label(nk, "9")) num = 9; + if (nk_button_label(nk, "+")) sign = '+'; + + if (nk_button_label(nk, "4")) num = 4; + if (nk_button_label(nk, "5")) num = 5; + if (nk_button_label(nk, "6")) num = 6; + if (nk_button_label(nk, "-")) sign = '-'; + + if (nk_button_label(nk, "1")) num = 1; + if (nk_button_label(nk, "2")) num = 2; + if (nk_button_label(nk, "3")) num = 3; + if (nk_button_label(nk, "*")) sign = '*'; + + if (nk_button_label(nk, "ะก")) num = -2; + if (nk_button_label(nk, "0")) num = 5; + if (nk_button_label(nk, "=")) num = -3; + if (nk_button_label(nk, "/")) sign = '/'; + + + if (sign) cur = &b; + + // new digit + if (num >= 0) { + if (cur != &b) cur = &a; + *cur = *cur*10 + num; + } + + // reset + if (num == -2) { + cur = &a; + a = b = c = sign = 0; + } + + // solve + if (num == -3 && cur == &b) { + if (sign == '+') c = a + b; + if (sign == '-') c = a - b; + if (sign == '*') c = a * b; + if (sign == '/') c = a / b; + cur = &c; + a = b = sign = 0; + } + } + nk_end(nk); + + nk_heli_process(&hnk); +} + + +int main() { + windowSetTitle("Calculator"); + windowSetResizable(TRUE); + windowSetVariableFrameRate(); + windowSetInit(&init); + windowSetDeinit(&deinit); + windowSetDraw(&draw); + windowRun(); + return 0; +} + diff --git a/nuklear-demo.c b/nuklear-demo.c new file mode 100644 index 0000000..7dfd94b --- /dev/null +++ b/nuklear-demo.c @@ -0,0 +1,49 @@ + +#include + +#include "nuklear-demos/calculator.c" +#include "nuklear-demos/canvas.c" +#include "nuklear-demos/node_editor.c" +#include "nuklear-demos/overview.c" + + +nk_heli hnk; +struct nk_context *nk; + +Animation anim; +struct nk_image img; + + +void init() { + nk_heli_init(&hnk, 12); + nk = &hnk.context; + anim = createAnimation("data/sprite/breadball.png"); + img = nk_heli_image(anim, 64, 64); +} + + +void deinit() { + nk_heli_deinit(&hnk); +} + + +void draw() { + calculator(nk); + canvas(nk); + node_editor(nk); + overview(nk, img); + nk_heli_process(&hnk); +} + + +int main() { + windowSetTitle("Nuklear UI Demo"); + windowSetResizable(TRUE); + windowSetVariableFrameRate(); + windowSetInit(&init); + windowSetDeinit(&deinit); + windowSetDraw(&draw); + windowRun(); + return 0; +} + diff --git a/nuklear-demos/calculator.c b/nuklear-demos/calculator.c new file mode 100644 index 0000000..b871301 --- /dev/null +++ b/nuklear-demos/calculator.c @@ -0,0 +1,64 @@ +/* nuklear - v1.00 - public domain */ +static void +calculator(struct nk_context *ctx) +{ + if (nk_begin(ctx, "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")) { + a = b = op = 0; current = &a; set = 0; + } if (nk_button_label(ctx, "0")) { + *current = *current*10.0f; set = 0; + } if (nk_button_label(ctx, "=")) { + solve = 1; prev = op; op = 0; + } + } else if (((i+1) % 4)) { + if (nk_button_text(ctx, &numbers[(i/4)*3+i%4], 1)) { + *current = *current * 10.0f + numbers[(i/4)*3+i%4] - '0'; + set = 0; + } + } else if (nk_button_text(ctx, &ops[i/4], 1)) { + 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); +} + diff --git a/nuklear-demos/canvas.c b/nuklear-demos/canvas.c new file mode 100644 index 0000000..6c50bcb --- /dev/null +++ b/nuklear-demos/canvas.c @@ -0,0 +1,105 @@ +/* nuklear - v1.05 - public domain */ +struct nk_canvas { + struct nk_command_buffer *painter; + struct nk_vec2 item_spacing; + struct nk_vec2 panel_padding; + struct nk_style_item window_background; +}; + +static nk_bool +canvas_begin(struct nk_context *ctx, struct nk_canvas *canvas, nk_flags flags, + int x, int y, int width, int height, struct nk_color background_color) +{ + /* save style properties which will be overwritten */ + canvas->panel_padding = ctx->style.window.padding; + canvas->item_spacing = ctx->style.window.spacing; + canvas->window_background = ctx->style.window.fixed_background; + + /* use the complete window space and set background */ + ctx->style.window.spacing = nk_vec2(0,0); + ctx->style.window.padding = nk_vec2(0,0); + ctx->style.window.fixed_background = nk_style_item_color(background_color); + + /* create/update window and set position + size */ + if (!nk_begin(ctx, "Canvas", nk_rect(x, y, width, height), NK_WINDOW_NO_SCROLLBAR|flags)) + return nk_false; + + /* allocate the complete window space for drawing */ + { + struct nk_rect total_space; + total_space = nk_window_get_content_region(ctx); + nk_layout_row_dynamic(ctx, total_space.h, 1); + nk_widget(&total_space, ctx); + canvas->painter = nk_window_get_canvas(ctx); + } + + return nk_true; +} + +static void +canvas_end(struct nk_context *ctx, struct nk_canvas *canvas) +{ + nk_end(ctx); + ctx->style.window.spacing = canvas->panel_padding; + ctx->style.window.padding = canvas->item_spacing; + ctx->style.window.fixed_background = canvas->window_background; +} + +static void +canvas(struct nk_context *ctx) +{ + struct nk_canvas canvas; + if (canvas_begin(ctx, &canvas, NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| + NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE, 10, 10, 500, 550, nk_rgb(250,250,250))) + { + float x = canvas.painter->clip.x, y = canvas.painter->clip.y; + + nk_fill_rect(canvas.painter, nk_rect(x + 15, y + 15, 210, 210), 5, nk_rgb(247, 230, 154)); + nk_fill_rect(canvas.painter, nk_rect(x + 20, y + 20, 200, 200), 5, nk_rgb(188, 174, 118)); + /* nk_draw_text(canvas.painter, nk_rect(x + 30, y + 30, 150, 20), "Text to draw", 12, &font->handle, nk_rgb(188,174,118), nk_rgb(0,0,0)); */ + nk_fill_rect(canvas.painter, nk_rect(x + 250, y + 20, 100, 100), 0, nk_rgb(0,0,255)); + nk_fill_circle(canvas.painter, nk_rect(x + 20, y + 250, 100, 100), nk_rgb(255,0,0)); + nk_fill_triangle(canvas.painter, x + 250, y + 250, x + 350, y + 250, x + 300, y + 350, nk_rgb(0,255,0)); + nk_fill_arc(canvas.painter, x + 300, y + 420, 50, 0, 3.141592654f * 3.0f / 4.0f, nk_rgb(255,255,0)); + + { + float points[12]; + points[0] = x + 200; points[1] = y + 250; + points[2] = x + 250; points[3] = y + 350; + points[4] = x + 225; points[5] = y + 350; + points[6] = x + 200; points[7] = y + 300; + points[8] = x + 175; points[9] = y + 350; + points[10] = x + 150; points[11] = y + 350; + nk_fill_polygon(canvas.painter, points, 6, nk_rgb(0,0,0)); + } + + { + float points[12]; + points[0] = x + 200; points[1] = y + 370; + points[2] = x + 250; points[3] = y + 470; + points[4] = x + 225; points[5] = y + 470; + points[6] = x + 200; points[7] = y + 420; + points[8] = x + 175; points[9] = y + 470; + points[10] = x + 150; points[11] = y + 470; + nk_stroke_polygon(canvas.painter, points, 6, 4, nk_rgb(0,0,0)); + } + + { + float points[8]; + points[0] = x + 250; points[1] = y + 200; + points[2] = x + 275; points[3] = y + 220; + points[4] = x + 325; points[5] = y + 170; + points[6] = x + 350; points[7] = y + 200; + nk_stroke_polyline(canvas.painter, points, 4, 2, nk_rgb(255,128,0)); + } + + nk_stroke_line(canvas.painter, x + 15, y + 10, x + 200, y + 10, 2.0f, nk_rgb(189,45,75)); + nk_stroke_rect(canvas.painter, nk_rect(x + 370, y + 20, 100, 100), 10, 3, nk_rgb(0,0,255)); + nk_stroke_curve(canvas.painter, x + 380, y + 200, x + 405, y + 270, x + 455, y + 120, x + 480, y + 200, 2, nk_rgb(0,150,220)); + nk_stroke_circle(canvas.painter, nk_rect(x + 20, y + 370, 100, 100), 5, nk_rgb(0,255,120)); + nk_stroke_triangle(canvas.painter, x + 370, y + 250, x + 470, y + 250, x + 420, y + 350, 6, nk_rgb(255,0,143)); + nk_stroke_arc(canvas.painter, x + 420, y + 420, 50, 0, 3.141592654f * 3.0f / 4.0f, 5, nk_rgb(0,255,255)); + } + canvas_end(ctx, &canvas); +} + diff --git a/nuklear-demos/node_editor.c b/nuklear-demos/node_editor.c new file mode 100644 index 0000000..2396957 --- /dev/null +++ b/nuklear-demos/node_editor.c @@ -0,0 +1,343 @@ +/* nuklear - v1.00 - public domain */ +/* This is a simple node editor just to show a simple implementation and that + * it is possible to achieve it with this library. While all nodes inside this + * example use a simple color modifier as content you could change them + * to have your custom content depending on the node time. + * Biggest difference to most usual implementation is that this example does + * not have connectors on the right position of the property that it links. + * This is mainly done out of laziness and could be implemented as well but + * requires calculating the position of all rows and add connectors. + * In addition adding and removing nodes is quite limited at the + * moment since it is based on a simple fixed array. If this is to be converted + * into something more serious it is probably best to extend it.*/ +struct node { + int ID; + char name[32]; + struct nk_rect bounds; + float value; + struct nk_color color; + int input_count; + int output_count; + struct node *next; + struct node *prev; +}; + +struct node_link { + int input_id; + int input_slot; + int output_id; + int output_slot; + struct nk_vec2 in; + struct nk_vec2 out; +}; + +struct node_linking { + int active; + struct node *node; + int input_id; + int input_slot; +}; + +struct node_editor { + int initialized; + struct node node_buf[32]; + struct node_link links[64]; + struct node *begin; + struct node *end; + int node_count; + int link_count; + struct nk_rect bounds; + struct node *selected; + int show_grid; + struct nk_vec2 scrolling; + struct node_linking linking; +}; +static struct node_editor nodeEditor; + +static void +node_editor_push(struct node_editor *editor, struct node *node) +{ + if (!editor->begin) { + node->next = NULL; + node->prev = NULL; + editor->begin = node; + editor->end = node; + } else { + node->prev = editor->end; + if (editor->end) + editor->end->next = node; + node->next = NULL; + editor->end = node; + } +} + +static void +node_editor_pop(struct node_editor *editor, struct node *node) +{ + if (node->next) + node->next->prev = node->prev; + if (node->prev) + node->prev->next = node->next; + if (editor->end == node) + editor->end = node->prev; + if (editor->begin == node) + editor->begin = node->next; + node->next = NULL; + node->prev = NULL; +} + +static struct node* +node_editor_find(struct node_editor *editor, int ID) +{ + struct node *iter = editor->begin; + while (iter) { + if (iter->ID == ID) + return iter; + iter = iter->next; + } + return NULL; +} + +static void +node_editor_add(struct node_editor *editor, const char *name, struct nk_rect bounds, + struct nk_color col, int in_count, int out_count) +{ + static int IDs = 0; + struct node *node; + assert((nk_size)editor->node_count < NK_LEN(editor->node_buf)); + node = &editor->node_buf[editor->node_count++]; + node->ID = IDs++; + node->value = 0; + node->color = nk_rgb(255, 0, 0); + node->input_count = in_count; + node->output_count = out_count; + node->color = col; + node->bounds = bounds; + strcpy(node->name, name); + node_editor_push(editor, node); +} + +static void +node_editor_link(struct node_editor *editor, int in_id, int in_slot, + int out_id, int out_slot) +{ + struct node_link *link; + assert((nk_size)editor->link_count < NK_LEN(editor->links)); + link = &editor->links[editor->link_count++]; + link->input_id = in_id; + link->input_slot = in_slot; + link->output_id = out_id; + link->output_slot = out_slot; +} + +static void +node_editor_init(struct node_editor *editor) +{ + memset(editor, 0, sizeof(*editor)); + editor->begin = NULL; + editor->end = NULL; + node_editor_add(editor, "Source", nk_rect(40, 10, 180, 220), nk_rgb(255, 0, 0), 0, 1); + node_editor_add(editor, "Source", nk_rect(40, 260, 180, 220), nk_rgb(0, 255, 0), 0, 1); + node_editor_add(editor, "Combine", nk_rect(400, 100, 180, 220), nk_rgb(0,0,255), 2, 2); + node_editor_link(editor, 0, 0, 2, 0); + node_editor_link(editor, 1, 0, 2, 1); + editor->show_grid = nk_true; +} + +static int +node_editor(struct nk_context *ctx) +{ + int n = 0; + struct nk_rect total_space; + const struct nk_input *in = &ctx->input; + struct nk_command_buffer *canvas; + struct node *updated = 0; + struct node_editor *nodedit = &nodeEditor; + + if (!nodeEditor.initialized) { + node_editor_init(&nodeEditor); + nodeEditor.initialized = 1; + } + + if (nk_begin(ctx, "NodeEdit", nk_rect(0, 0, 800, 600), + NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) + { + /* allocate complete window space */ + canvas = nk_window_get_canvas(ctx); + total_space = nk_window_get_content_region(ctx); + nk_layout_space_begin(ctx, NK_STATIC, total_space.h, nodedit->node_count); + { + struct node *it = nodedit->begin; + struct nk_rect size = nk_layout_space_bounds(ctx); + struct nk_panel *node = 0; + + if (nodedit->show_grid) { + /* display grid */ + float x, y; + const float grid_size = 32.0f; + const struct nk_color grid_color = nk_rgb(50, 50, 50); + for (x = (float)fmod(size.x - nodedit->scrolling.x, grid_size); x < size.w; x += grid_size) + nk_stroke_line(canvas, x+size.x, size.y, x+size.x, size.y+size.h, 1.0f, grid_color); + for (y = (float)fmod(size.y - nodedit->scrolling.y, grid_size); y < size.h; y += grid_size) + nk_stroke_line(canvas, size.x, y+size.y, size.x+size.w, y+size.y, 1.0f, grid_color); + } + + /* execute each node as a movable group */ + while (it) { + /* calculate scrolled node window position and size */ + nk_layout_space_push(ctx, nk_rect(it->bounds.x - nodedit->scrolling.x, + it->bounds.y - nodedit->scrolling.y, it->bounds.w, it->bounds.h)); + + /* execute node window */ + if (nk_group_begin(ctx, it->name, NK_WINDOW_MOVABLE|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER|NK_WINDOW_TITLE)) + { + /* always have last selected node on top */ + + node = nk_window_get_panel(ctx); + if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, node->bounds) && + (!(it->prev && nk_input_mouse_clicked(in, NK_BUTTON_LEFT, + nk_layout_space_rect_to_screen(ctx, node->bounds)))) && + nodedit->end != it) + { + updated = it; + } + + /* ================= NODE CONTENT =====================*/ + nk_layout_row_dynamic(ctx, 25, 1); + nk_button_color(ctx, it->color); + it->color.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, it->color.r, 255, 1,1); + it->color.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, it->color.g, 255, 1,1); + it->color.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, it->color.b, 255, 1,1); + it->color.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, it->color.a, 255, 1,1); + /* ====================================================*/ + nk_group_end(ctx); + } + { + /* node connector and linking */ + float space; + struct nk_rect bounds; + bounds = nk_layout_space_rect_to_local(ctx, node->bounds); + bounds.x += nodedit->scrolling.x; + bounds.y += nodedit->scrolling.y; + it->bounds = bounds; + + /* output connector */ + space = node->bounds.h / (float)((it->output_count) + 1); + for (n = 0; n < it->output_count; ++n) { + struct nk_rect circle; + circle.x = node->bounds.x + node->bounds.w-4; + circle.y = node->bounds.y + space * (float)(n+1); + circle.w = 8; circle.h = 8; + nk_fill_circle(canvas, circle, nk_rgb(100, 100, 100)); + + /* start linking process */ + if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true)) { + nodedit->linking.active = nk_true; + nodedit->linking.node = it; + nodedit->linking.input_id = it->ID; + nodedit->linking.input_slot = n; + } + + /* draw curve from linked node slot to mouse position */ + if (nodedit->linking.active && nodedit->linking.node == it && + nodedit->linking.input_slot == n) { + struct nk_vec2 l0 = nk_vec2(circle.x + 3, circle.y + 3); + struct nk_vec2 l1 = in->mouse.pos; + nk_stroke_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y, + l1.x - 50.0f, l1.y, l1.x, l1.y, 1.0f, nk_rgb(100, 100, 100)); + } + } + + /* input connector */ + space = node->bounds.h / (float)((it->input_count) + 1); + for (n = 0; n < it->input_count; ++n) { + struct nk_rect circle; + circle.x = node->bounds.x-4; + circle.y = node->bounds.y + space * (float)(n+1); + circle.w = 8; circle.h = 8; + nk_fill_circle(canvas, circle, nk_rgb(100, 100, 100)); + if (nk_input_is_mouse_released(in, NK_BUTTON_LEFT) && + nk_input_is_mouse_hovering_rect(in, circle) && + nodedit->linking.active && nodedit->linking.node != it) { + nodedit->linking.active = nk_false; + node_editor_link(nodedit, nodedit->linking.input_id, + nodedit->linking.input_slot, it->ID, n); + } + } + } + it = it->next; + } + + /* reset linking connection */ + if (nodedit->linking.active && nk_input_is_mouse_released(in, NK_BUTTON_LEFT)) { + nodedit->linking.active = nk_false; + nodedit->linking.node = NULL; + fprintf(stdout, "linking failed\n"); + } + + /* draw each link */ + for (n = 0; n < nodedit->link_count; ++n) { + struct node_link *link = &nodedit->links[n]; + struct node *ni = node_editor_find(nodedit, link->input_id); + struct node *no = node_editor_find(nodedit, link->output_id); + float spacei = node->bounds.h / (float)((ni->output_count) + 1); + float spaceo = node->bounds.h / (float)((no->input_count) + 1); + struct nk_vec2 l0 = nk_layout_space_to_screen(ctx, + nk_vec2(ni->bounds.x + ni->bounds.w, 3.0f + ni->bounds.y + spacei * (float)(link->input_slot+1))); + struct nk_vec2 l1 = nk_layout_space_to_screen(ctx, + nk_vec2(no->bounds.x, 3.0f + no->bounds.y + spaceo * (float)(link->output_slot+1))); + + l0.x -= nodedit->scrolling.x; + l0.y -= nodedit->scrolling.y; + l1.x -= nodedit->scrolling.x; + l1.y -= nodedit->scrolling.y; + nk_stroke_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y, + l1.x - 50.0f, l1.y, l1.x, l1.y, 1.0f, nk_rgb(100, 100, 100)); + } + + if (updated) { + /* reshuffle nodes to have least recently selected node on top */ + node_editor_pop(nodedit, updated); + node_editor_push(nodedit, updated); + } + + /* node selection */ + if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nk_layout_space_bounds(ctx))) { + it = nodedit->begin; + nodedit->selected = NULL; + nodedit->bounds = nk_rect(in->mouse.pos.x, in->mouse.pos.y, 100, 200); + while (it) { + struct nk_rect b = nk_layout_space_rect_to_screen(ctx, it->bounds); + b.x -= nodedit->scrolling.x; + b.y -= nodedit->scrolling.y; + if (nk_input_is_mouse_hovering_rect(in, b)) + nodedit->selected = it; + it = it->next; + } + } + + /* contextual menu */ + if (nk_contextual_begin(ctx, 0, nk_vec2(100, 220), nk_window_get_bounds(ctx))) { + const char *grid_option[] = {"Show Grid", "Hide Grid"}; + nk_layout_row_dynamic(ctx, 25, 1); + if (nk_contextual_item_label(ctx, "New", NK_TEXT_CENTERED)) + node_editor_add(nodedit, "New", nk_rect(400, 260, 180, 220), + nk_rgb(255, 255, 255), 1, 2); + if (nk_contextual_item_label(ctx, grid_option[nodedit->show_grid],NK_TEXT_CENTERED)) + nodedit->show_grid = !nodedit->show_grid; + nk_contextual_end(ctx); + } + } + nk_layout_space_end(ctx); + + /* window content scrolling */ + if (nk_input_is_mouse_hovering_rect(in, nk_window_get_bounds(ctx)) && + nk_input_is_mouse_down(in, NK_BUTTON_MIDDLE)) { + nodedit->scrolling.x += in->mouse.delta.x; + nodedit->scrolling.y += in->mouse.delta.y; + } + } + nk_end(ctx); + return !nk_window_is_closed(ctx, "NodeEdit"); +} + diff --git a/nuklear-demos/overview.c b/nuklear-demos/overview.c new file mode 100644 index 0000000..222fb17 --- /dev/null +++ b/nuklear-demos/overview.c @@ -0,0 +1,1305 @@ + +#include +#include +#include + + +static int +overview(struct nk_context *ctx, struct nk_image img) +{ + /* window flags */ + static int show_menu = nk_true; + static nk_flags window_flags = NK_WINDOW_TITLE|NK_WINDOW_BORDER|NK_WINDOW_SCALABLE|NK_WINDOW_MOVABLE|NK_WINDOW_MINIMIZABLE; + nk_flags actual_window_flags; + + /* popups */ + static enum nk_style_header_align header_align = NK_HEADER_RIGHT; + static int show_app_about = nk_false; + + ctx->style.window.header.align = header_align; + + actual_window_flags = window_flags; + if (!(actual_window_flags & NK_WINDOW_TITLE)) + actual_window_flags &= ~(NK_WINDOW_MINIMIZABLE|NK_WINDOW_CLOSABLE); + if (nk_begin(ctx, "Overview", nk_rect(10, 10, 400, 600), actual_window_flags)) + { + if (show_menu) + { + /* menubar */ + enum menu_states {MENU_DEFAULT, MENU_WINDOWS}; + static nk_size mprog = 60; + static int mslider = 10; + static int mcheck = nk_true; + nk_menubar_begin(ctx); + + /* menu #1 */ + nk_layout_row_begin(ctx, NK_STATIC, 25, 5); + nk_layout_row_push(ctx, 45); + if (nk_menu_begin_label(ctx, "MENU", NK_TEXT_LEFT, nk_vec2(150, 200))) + { + static size_t prog = 40; + static int slider = 10; + static int check = nk_true; + nk_layout_row_dynamic(ctx, 25, 1); + if (nk_menu_item_label(ctx, "Hide", NK_TEXT_LEFT)) + show_menu = nk_false; + if (nk_menu_item_label(ctx, "About", NK_TEXT_LEFT)) + show_app_about = nk_true; + nk_progress(ctx, &prog, 100, NK_MODIFIABLE); + nk_slider_int(ctx, 0, &slider, 16, 1); + nk_checkbox_label(ctx, "check", &check); + nk_menu_end(ctx); + } + /* menu #2 */ + nk_layout_row_push(ctx, 60); + if (nk_menu_begin_label(ctx, "ADVANCED", NK_TEXT_LEFT, nk_vec2(300, 600))) + { + enum menu_state {MENU_NONE,MENU_FILE, MENU_EDIT,MENU_VIEW,MENU_CHART}; + static enum menu_state menu_state = MENU_NONE; + enum nk_collapse_states state; + + state = (menu_state == MENU_FILE) ? NK_MAXIMIZED: NK_MINIMIZED; + if (nk_tree_state_push(ctx, NK_TREE_TAB, "FILE", &state)) { + menu_state = MENU_FILE; + nk_menu_item_label(ctx, "New", NK_TEXT_LEFT); + nk_menu_item_label(ctx, "Open", NK_TEXT_LEFT); + nk_menu_item_label(ctx, "Save", NK_TEXT_LEFT); + nk_menu_item_label(ctx, "Close", NK_TEXT_LEFT); + nk_menu_item_label(ctx, "Exit", NK_TEXT_LEFT); + nk_tree_pop(ctx); + } else menu_state = (menu_state == MENU_FILE) ? MENU_NONE: menu_state; + + state = (menu_state == MENU_EDIT) ? NK_MAXIMIZED: NK_MINIMIZED; + if (nk_tree_state_push(ctx, NK_TREE_TAB, "EDIT", &state)) { + menu_state = MENU_EDIT; + nk_menu_item_label(ctx, "Copy", NK_TEXT_LEFT); + nk_menu_item_label(ctx, "Delete", NK_TEXT_LEFT); + nk_menu_item_label(ctx, "Cut", NK_TEXT_LEFT); + nk_menu_item_label(ctx, "Paste", NK_TEXT_LEFT); + nk_tree_pop(ctx); + } else menu_state = (menu_state == MENU_EDIT) ? MENU_NONE: menu_state; + + state = (menu_state == MENU_VIEW) ? NK_MAXIMIZED: NK_MINIMIZED; + if (nk_tree_state_push(ctx, NK_TREE_TAB, "VIEW", &state)) { + menu_state = MENU_VIEW; + nk_menu_item_label(ctx, "About", NK_TEXT_LEFT); + nk_menu_item_label(ctx, "Options", NK_TEXT_LEFT); + nk_menu_item_label(ctx, "Customize", NK_TEXT_LEFT); + nk_tree_pop(ctx); + } else menu_state = (menu_state == MENU_VIEW) ? MENU_NONE: menu_state; + + state = (menu_state == MENU_CHART) ? NK_MAXIMIZED: NK_MINIMIZED; + if (nk_tree_state_push(ctx, NK_TREE_TAB, "CHART", &state)) { + size_t i = 0; + const float values[]={26.0f,13.0f,30.0f,15.0f,25.0f,10.0f,20.0f,40.0f,12.0f,8.0f,22.0f,28.0f}; + menu_state = MENU_CHART; + nk_layout_row_dynamic(ctx, 150, 1); + nk_chart_begin(ctx, NK_CHART_COLUMN, NK_LEN(values), 0, 50); + for (i = 0; i < NK_LEN(values); ++i) + nk_chart_push(ctx, values[i]); + nk_chart_end(ctx); + nk_tree_pop(ctx); + } else menu_state = (menu_state == MENU_CHART) ? MENU_NONE: menu_state; + nk_menu_end(ctx); + } + /* menu widgets */ + nk_layout_row_push(ctx, 70); + nk_progress(ctx, &mprog, 100, NK_MODIFIABLE); + nk_slider_int(ctx, 0, &mslider, 16, 1); + nk_checkbox_label(ctx, "check", &mcheck); + nk_menubar_end(ctx); + } + + if (show_app_about) + { + /* about popup */ + static struct nk_rect s = {20, 100, 300, 190}; + if (nk_popup_begin(ctx, 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, "By Micha Mettke", 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; + } + + /* window flags */ + if (nk_tree_push(ctx, NK_TREE_TAB, "Window", NK_MINIMIZED)) { + nk_layout_row_dynamic(ctx, 30, 2); + nk_checkbox_label(ctx, "Menu", &show_menu); + nk_checkbox_flags_label(ctx, "Titlebar", &window_flags, NK_WINDOW_TITLE); + nk_checkbox_flags_label(ctx, "Border", &window_flags, NK_WINDOW_BORDER); + nk_checkbox_flags_label(ctx, "Resizable", &window_flags, NK_WINDOW_SCALABLE); + nk_checkbox_flags_label(ctx, "Movable", &window_flags, NK_WINDOW_MOVABLE); + nk_checkbox_flags_label(ctx, "No Scrollbar", &window_flags, NK_WINDOW_NO_SCROLLBAR); + nk_checkbox_flags_label(ctx, "Minimizable", &window_flags, NK_WINDOW_MINIMIZABLE); + nk_checkbox_flags_label(ctx, "Scale Left", &window_flags, NK_WINDOW_SCALE_LEFT); + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_TAB, "Widgets", NK_MINIMIZED)) + { + enum options {A,B,C}; + static int checkbox; + static int option; + if (nk_tree_push(ctx, NK_TREE_NODE, "Text", NK_MINIMIZED)) + { + /* Text Widgets */ + nk_layout_row_dynamic(ctx, 20, 1); + nk_label(ctx, "Label aligned left", NK_TEXT_LEFT); + nk_label(ctx, "Label aligned centered", NK_TEXT_CENTERED); + nk_label(ctx, "Label aligned right", NK_TEXT_RIGHT); + nk_label_colored(ctx, "Blue text", NK_TEXT_LEFT, nk_rgb(0,0,255)); + nk_label_colored(ctx, "Yellow text", NK_TEXT_LEFT, nk_rgb(255,255,0)); + nk_text(ctx, "Text without /0", 15, NK_TEXT_RIGHT); + + nk_layout_row_static(ctx, 100, 200, 1); + nk_label_wrap(ctx, "This is a very long line to hopefully get this text to be wrapped into multiple lines to show line wrapping"); + nk_layout_row_dynamic(ctx, 100, 1); + nk_label_wrap(ctx, "This is another long text to show dynamic window changes on multiline text"); + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Button", NK_MINIMIZED)) + { + /* Buttons Widgets */ + nk_layout_row_static(ctx, 30, 100, 3); + if (nk_button_label(ctx, "Button")) + fprintf(stdout, "Button pressed!\n"); + nk_button_set_behavior(ctx, NK_BUTTON_REPEATER); + if (nk_button_label(ctx, "Repeater")) + fprintf(stdout, "Repeater is being pressed!\n"); + nk_button_set_behavior(ctx, NK_BUTTON_DEFAULT); + nk_button_color(ctx, nk_rgb(0,0,255)); + + nk_layout_row_static(ctx, 25, 25, 8); + nk_button_symbol(ctx, NK_SYMBOL_CIRCLE_SOLID); + nk_button_symbol(ctx, NK_SYMBOL_CIRCLE_OUTLINE); + nk_button_symbol(ctx, NK_SYMBOL_RECT_SOLID); + nk_button_symbol(ctx, NK_SYMBOL_RECT_OUTLINE); + nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_UP); + nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_DOWN); + nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_LEFT); + nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_RIGHT); + + nk_layout_row_static(ctx, 30, 100, 2); + nk_button_symbol_label(ctx, NK_SYMBOL_TRIANGLE_LEFT, "prev", NK_TEXT_RIGHT); + nk_button_symbol_label(ctx, NK_SYMBOL_TRIANGLE_RIGHT, "next", NK_TEXT_LEFT); + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Basic", NK_MINIMIZED)) + { + /* Basic widgets */ + static int int_slider = 5; + static float float_slider = 2.5f; + static nk_size prog_value = 40; + static float property_float = 2; + static int property_int = 10; + static int property_neg = 10; + + static float range_float_min = 0; + static float range_float_max = 100; + static float range_float_value = 50; + static int range_int_min = 0; + static int range_int_value = 2048; + static int range_int_max = 4096; + static const float ratio[] = {120, 150}; + + nk_layout_row_static(ctx, 64, 64, 1); + nk_image(ctx, img); + + nk_layout_row_static(ctx, 30, 100, 1); + nk_checkbox_label(ctx, "Checkbox", &checkbox); + + nk_layout_row_static(ctx, 30, 80, 3); + option = nk_option_label(ctx, "optionA", option == A) ? A : option; + option = nk_option_label(ctx, "optionB", option == B) ? B : option; + option = nk_option_label(ctx, "optionC", option == C) ? C : option; + + nk_layout_row(ctx, NK_STATIC, 30, 2, ratio); + nk_labelf(ctx, NK_TEXT_LEFT, "Slider int"); + nk_slider_int(ctx, 0, &int_slider, 10, 1); + + nk_label(ctx, "Slider float", NK_TEXT_LEFT); + nk_slider_float(ctx, 0, &float_slider, 5.0, 0.5f); + nk_labelf(ctx, NK_TEXT_LEFT, "Progressbar: %u" , (int)prog_value); + nk_progress(ctx, &prog_value, 100, NK_MODIFIABLE); + + nk_layout_row(ctx, NK_STATIC, 25, 2, ratio); + nk_label(ctx, "Property float:", NK_TEXT_LEFT); + nk_property_float(ctx, "Float:", 0, &property_float, 64.0f, 0.1f, 0.2f); + nk_label(ctx, "Property int:", NK_TEXT_LEFT); + nk_property_int(ctx, "Int:", 0, &property_int, 100, 1, 1); + nk_label(ctx, "Property neg:", NK_TEXT_LEFT); + nk_property_int(ctx, "Neg:", -10, &property_neg, 10, 1, 1); + + nk_layout_row_dynamic(ctx, 25, 1); + nk_label(ctx, "Range:", NK_TEXT_LEFT); + nk_layout_row_dynamic(ctx, 25, 3); + nk_property_float(ctx, "#min:", 0, &range_float_min, range_float_max, 1.0f, 0.2f); + nk_property_float(ctx, "#float:", range_float_min, &range_float_value, range_float_max, 1.0f, 0.2f); + nk_property_float(ctx, "#max:", range_float_min, &range_float_max, 100, 1.0f, 0.2f); + + nk_property_int(ctx, "#min:", INT_MIN, &range_int_min, range_int_max, 1, 10); + nk_property_int(ctx, "#neg:", range_int_min, &range_int_value, range_int_max, 1, 10); + nk_property_int(ctx, "#max:", range_int_min, &range_int_max, INT_MAX, 1, 10); + + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Inactive", NK_MINIMIZED)) + { + static int inactive = 1; + nk_layout_row_dynamic(ctx, 30, 1); + nk_checkbox_label(ctx, "Inactive", &inactive); + + nk_layout_row_static(ctx, 30, 80, 1); + if (inactive) { + struct nk_style_button button; + button = ctx->style.button; + ctx->style.button.normal = nk_style_item_color(nk_rgb(40,40,40)); + ctx->style.button.hover = nk_style_item_color(nk_rgb(40,40,40)); + ctx->style.button.active = nk_style_item_color(nk_rgb(40,40,40)); + ctx->style.button.border_color = nk_rgb(60,60,60); + ctx->style.button.text_background = nk_rgb(60,60,60); + ctx->style.button.text_normal = nk_rgb(60,60,60); + ctx->style.button.text_hover = nk_rgb(60,60,60); + ctx->style.button.text_active = nk_rgb(60,60,60); + nk_button_label(ctx, "button"); + ctx->style.button = button; + } else if (nk_button_label(ctx, "button")) + fprintf(stdout, "button pressed\n"); + nk_tree_pop(ctx); + } + + + if (nk_tree_push(ctx, NK_TREE_NODE, "Selectable", NK_MINIMIZED)) + { + if (nk_tree_push(ctx, NK_TREE_NODE, "List", NK_MINIMIZED)) + { + static int selected[4] = {nk_false, nk_false, nk_true, nk_false}; + nk_layout_row_static(ctx, 18, 100, 1); + nk_selectable_label(ctx, "Selectable", NK_TEXT_LEFT, &selected[0]); + nk_selectable_label(ctx, "Selectable", NK_TEXT_LEFT, &selected[1]); + nk_label(ctx, "Not Selectable", NK_TEXT_LEFT); + nk_selectable_label(ctx, "Selectable", NK_TEXT_LEFT, &selected[2]); + nk_selectable_label(ctx, "Selectable", NK_TEXT_LEFT, &selected[3]); + nk_tree_pop(ctx); + } + if (nk_tree_push(ctx, NK_TREE_NODE, "Grid", NK_MINIMIZED)) + { + int i; + static int selected[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; + nk_layout_row_static(ctx, 50, 50, 4); + for (i = 0; i < 16; ++i) { + if (nk_selectable_label(ctx, "Z", NK_TEXT_CENTERED, &selected[i])) { + int x = (i % 4), y = i / 4; + if (x > 0) selected[i - 1] ^= 1; + if (x < 3) selected[i + 1] ^= 1; + if (y > 0) selected[i - 4] ^= 1; + if (y < 3) selected[i + 4] ^= 1; + } + } + nk_tree_pop(ctx); + } + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Combo", NK_MINIMIZED)) + { + /* Combobox Widgets + * In this library comboboxes are not limited to being a popup + * list of selectable text. Instead it is a abstract concept of + * having something that is *selected* or displayed, a popup window + * which opens if something needs to be modified and the content + * of the popup which causes the *selected* or displayed value to + * change or if wanted close the combobox. + * + * While strange at first handling comboboxes in a abstract way + * solves the problem of overloaded window content. For example + * changing a color value requires 4 value modifier (slider, property,...) + * for RGBA then you need a label and ways to display the current color. + * If you want to go fancy you even add rgb and hsv ratio boxes. + * While fine for one color if you have a lot of them it because + * tedious to look at and quite wasteful in space. You could add + * a popup which modifies the color but this does not solve the + * fact that it still requires a lot of cluttered space to do. + * + * In these kind of instance abstract comboboxes are quite handy. All + * value modifiers are hidden inside the combobox popup and only + * the color is shown if not open. This combines the clarity of the + * popup with the ease of use of just using the space for modifiers. + * + * Other instances are for example time and especially date picker, + * which only show the currently activated time/data and hide the + * selection logic inside the combobox popup. + */ + static float chart_selection = 8.0f; + static int current_weapon = 0; + static int check_values[5]; + static float position[3]; + static struct nk_color combo_color = {130, 50, 50, 255}; + static struct nk_colorf combo_color2 = {0.509f, 0.705f, 0.2f, 1.0f}; + static size_t prog_a = 20, prog_b = 40, prog_c = 10, prog_d = 90; + static const char *weapons[] = {"Fist","Pistol","Shotgun","Plasma","BFG"}; + + char buffer[64]; + size_t sum = 0; + + /* default combobox */ + nk_layout_row_static(ctx, 25, 200, 1); + current_weapon = nk_combo(ctx, weapons, NK_LEN(weapons), current_weapon, 25, nk_vec2(200,200)); + + /* slider color combobox */ + if (nk_combo_begin_color(ctx, combo_color, nk_vec2(200,200))) { + float ratios[] = {0.15f, 0.85f}; + nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratios); + nk_label(ctx, "R:", NK_TEXT_LEFT); + combo_color.r = (nk_byte)nk_slide_int(ctx, 0, combo_color.r, 255, 5); + nk_label(ctx, "G:", NK_TEXT_LEFT); + combo_color.g = (nk_byte)nk_slide_int(ctx, 0, combo_color.g, 255, 5); + nk_label(ctx, "B:", NK_TEXT_LEFT); + combo_color.b = (nk_byte)nk_slide_int(ctx, 0, combo_color.b, 255, 5); + nk_label(ctx, "A:", NK_TEXT_LEFT); + combo_color.a = (nk_byte)nk_slide_int(ctx, 0, combo_color.a , 255, 5); + nk_combo_end(ctx); + } + /* complex color combobox */ + if (nk_combo_begin_color(ctx, nk_rgb_cf(combo_color2), nk_vec2(200,400))) { + enum color_mode {COL_RGB, COL_HSV}; + static int col_mode = COL_RGB; + #ifndef DEMO_DO_NOT_USE_COLOR_PICKER + nk_layout_row_dynamic(ctx, 120, 1); + combo_color2 = nk_color_picker(ctx, combo_color2, NK_RGBA); + #endif + + nk_layout_row_dynamic(ctx, 25, 2); + col_mode = nk_option_label(ctx, "RGB", col_mode == COL_RGB) ? COL_RGB : col_mode; + col_mode = nk_option_label(ctx, "HSV", col_mode == COL_HSV) ? COL_HSV : col_mode; + + nk_layout_row_dynamic(ctx, 25, 1); + if (col_mode == COL_RGB) { + combo_color2.r = nk_propertyf(ctx, "#R:", 0, combo_color2.r, 1.0f, 0.01f,0.005f); + combo_color2.g = nk_propertyf(ctx, "#G:", 0, combo_color2.g, 1.0f, 0.01f,0.005f); + combo_color2.b = nk_propertyf(ctx, "#B:", 0, combo_color2.b, 1.0f, 0.01f,0.005f); + combo_color2.a = nk_propertyf(ctx, "#A:", 0, combo_color2.a, 1.0f, 0.01f,0.005f); + } else { + float hsva[4]; + nk_colorf_hsva_fv(hsva, combo_color2); + hsva[0] = nk_propertyf(ctx, "#H:", 0, hsva[0], 1.0f, 0.01f,0.05f); + hsva[1] = nk_propertyf(ctx, "#S:", 0, hsva[1], 1.0f, 0.01f,0.05f); + hsva[2] = nk_propertyf(ctx, "#V:", 0, hsva[2], 1.0f, 0.01f,0.05f); + hsva[3] = nk_propertyf(ctx, "#A:", 0, hsva[3], 1.0f, 0.01f,0.05f); + combo_color2 = nk_hsva_colorfv(hsva); + } + nk_combo_end(ctx); + } + /* progressbar combobox */ + sum = prog_a + prog_b + prog_c + prog_d; + sprintf(buffer, "%u", (unsigned int)sum); + if (nk_combo_begin_label(ctx, buffer, nk_vec2(200,200))) { + nk_layout_row_dynamic(ctx, 30, 1); + nk_progress(ctx, &prog_a, 100, NK_MODIFIABLE); + nk_progress(ctx, &prog_b, 100, NK_MODIFIABLE); + nk_progress(ctx, &prog_c, 100, NK_MODIFIABLE); + nk_progress(ctx, &prog_d, 100, NK_MODIFIABLE); + nk_combo_end(ctx); + } + + /* checkbox combobox */ + sum = (size_t)(check_values[0] + check_values[1] + check_values[2] + check_values[3] + check_values[4]); + sprintf(buffer, "%u", (unsigned int)sum); + if (nk_combo_begin_label(ctx, buffer, nk_vec2(200,200))) { + nk_layout_row_dynamic(ctx, 30, 1); + nk_checkbox_label(ctx, weapons[0], &check_values[0]); + nk_checkbox_label(ctx, weapons[1], &check_values[1]); + nk_checkbox_label(ctx, weapons[2], &check_values[2]); + nk_checkbox_label(ctx, weapons[3], &check_values[3]); + nk_combo_end(ctx); + } + + /* complex text combobox */ + sprintf(buffer, "%.2f, %.2f, %.2f", position[0], position[1],position[2]); + if (nk_combo_begin_label(ctx, buffer, nk_vec2(200,200))) { + nk_layout_row_dynamic(ctx, 25, 1); + nk_property_float(ctx, "#X:", -1024.0f, &position[0], 1024.0f, 1,0.5f); + nk_property_float(ctx, "#Y:", -1024.0f, &position[1], 1024.0f, 1,0.5f); + nk_property_float(ctx, "#Z:", -1024.0f, &position[2], 1024.0f, 1,0.5f); + nk_combo_end(ctx); + } + + /* chart combobox */ + sprintf(buffer, "%.1f", chart_selection); + if (nk_combo_begin_label(ctx, buffer, nk_vec2(200,250))) { + size_t i = 0; + static const float values[]={26.0f,13.0f,30.0f,15.0f,25.0f,10.0f,20.0f,40.0f, 12.0f, 8.0f, 22.0f, 28.0f, 5.0f}; + nk_layout_row_dynamic(ctx, 150, 1); + nk_chart_begin(ctx, NK_CHART_COLUMN, NK_LEN(values), 0, 50); + for (i = 0; i < NK_LEN(values); ++i) { + nk_flags res = nk_chart_push(ctx, values[i]); + if (res & NK_CHART_CLICKED) { + chart_selection = values[i]; + nk_combo_close(ctx); + } + } + nk_chart_end(ctx); + nk_combo_end(ctx); + } + + { + static int time_selected = 0; + static int date_selected = 0; + static struct tm sel_time; + static struct tm sel_date; + if (!time_selected || !date_selected) { + /* keep time and date updated if nothing is selected */ + time_t cur_time = time(0); + struct tm *n = localtime(&cur_time); + if (!time_selected) + memcpy(&sel_time, n, sizeof(struct tm)); + if (!date_selected) + memcpy(&sel_date, n, sizeof(struct tm)); + } + + /* time combobox */ + sprintf(buffer, "%02d:%02d:%02d", sel_time.tm_hour, sel_time.tm_min, sel_time.tm_sec); + if (nk_combo_begin_label(ctx, buffer, nk_vec2(200,250))) { + time_selected = 1; + nk_layout_row_dynamic(ctx, 25, 1); + sel_time.tm_sec = nk_propertyi(ctx, "#S:", 0, sel_time.tm_sec, 60, 1, 1); + sel_time.tm_min = nk_propertyi(ctx, "#M:", 0, sel_time.tm_min, 60, 1, 1); + sel_time.tm_hour = nk_propertyi(ctx, "#H:", 0, sel_time.tm_hour, 23, 1, 1); + nk_combo_end(ctx); + } + + /* date combobox */ + sprintf(buffer, "%02d-%02d-%02d", sel_date.tm_mday, sel_date.tm_mon+1, sel_date.tm_year+1900); + if (nk_combo_begin_label(ctx, buffer, nk_vec2(350,400))) + { + int i = 0; + const char *month[] = {"January", "February", "March", + "April", "May", "June", "July", "August", "September", + "October", "November", "December"}; + const char *week_days[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}; + const int month_days[] = {31,28,31,30,31,30,31,31,30,31,30,31}; + int year = sel_date.tm_year+1900; + int leap_year = (!(year % 4) && ((year % 100))) || !(year % 400); + int days = (sel_date.tm_mon == 1) ? + month_days[sel_date.tm_mon] + leap_year: + month_days[sel_date.tm_mon]; + + /* header with month and year */ + date_selected = 1; + nk_layout_row_begin(ctx, NK_DYNAMIC, 20, 3); + nk_layout_row_push(ctx, 0.05f); + if (nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_LEFT)) { + if (sel_date.tm_mon == 0) { + sel_date.tm_mon = 11; + sel_date.tm_year = NK_MAX(0, sel_date.tm_year-1); + } else sel_date.tm_mon--; + } + nk_layout_row_push(ctx, 0.9f); + sprintf(buffer, "%s %d", month[sel_date.tm_mon], year); + nk_label(ctx, buffer, NK_TEXT_CENTERED); + nk_layout_row_push(ctx, 0.05f); + if (nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_RIGHT)) { + if (sel_date.tm_mon == 11) { + sel_date.tm_mon = 0; + sel_date.tm_year++; + } else sel_date.tm_mon++; + } + nk_layout_row_end(ctx); + + /* good old week day formula (double because precision) */ + {int year_n = (sel_date.tm_mon < 2) ? year-1: year; + int y = year_n % 100; + int c = year_n / 100; + int y4 = (int)((float)y / 4); + int c4 = (int)((float)c / 4); + int m = (int)(2.6 * (double)(((sel_date.tm_mon + 10) % 12) + 1) - 0.2); + int week_day = (((1 + m + y + y4 + c4 - 2 * c) % 7) + 7) % 7; + + /* weekdays */ + nk_layout_row_dynamic(ctx, 35, 7); + for (i = 0; i < (int)NK_LEN(week_days); ++i) + nk_label(ctx, week_days[i], NK_TEXT_CENTERED); + + /* days */ + if (week_day > 0) nk_spacing(ctx, week_day); + for (i = 1; i <= days; ++i) { + sprintf(buffer, "%d", i); + if (nk_button_label(ctx, buffer)) { + sel_date.tm_mday = i; + nk_combo_close(ctx); + } + }} + nk_combo_end(ctx); + } + } + + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Input", NK_MINIMIZED)) + { + static const float ratio[] = {120, 150}; + static char field_buffer[64]; + static char text[9][64]; + static int text_len[9]; + static char box_buffer[512]; + static int field_len; + static int box_len; + nk_flags active; + + nk_layout_row(ctx, NK_STATIC, 25, 2, ratio); + nk_label(ctx, "Default:", NK_TEXT_LEFT); + + nk_edit_string(ctx, NK_EDIT_SIMPLE, text[0], &text_len[0], 64, nk_filter_default); + nk_label(ctx, "Int:", NK_TEXT_LEFT); + nk_edit_string(ctx, NK_EDIT_SIMPLE, text[1], &text_len[1], 64, nk_filter_decimal); + nk_label(ctx, "Float:", NK_TEXT_LEFT); + nk_edit_string(ctx, NK_EDIT_SIMPLE, text[2], &text_len[2], 64, nk_filter_float); + nk_label(ctx, "Hex:", NK_TEXT_LEFT); + nk_edit_string(ctx, NK_EDIT_SIMPLE, text[4], &text_len[4], 64, nk_filter_hex); + nk_label(ctx, "Octal:", NK_TEXT_LEFT); + nk_edit_string(ctx, NK_EDIT_SIMPLE, text[5], &text_len[5], 64, nk_filter_oct); + nk_label(ctx, "Binary:", NK_TEXT_LEFT); + nk_edit_string(ctx, NK_EDIT_SIMPLE, text[6], &text_len[6], 64, nk_filter_binary); + + nk_label(ctx, "Password:", NK_TEXT_LEFT); + { + int i = 0; + int old_len = text_len[8]; + char buffer[64]; + for (i = 0; i < text_len[8]; ++i) buffer[i] = '*'; + nk_edit_string(ctx, NK_EDIT_FIELD, buffer, &text_len[8], 64, nk_filter_default); + if (old_len < text_len[8]) + memcpy(&text[8][old_len], &buffer[old_len], (nk_size)(text_len[8] - old_len)); + } + + nk_label(ctx, "Field:", NK_TEXT_LEFT); + nk_edit_string(ctx, NK_EDIT_FIELD, field_buffer, &field_len, 64, nk_filter_default); + + nk_label(ctx, "Box:", NK_TEXT_LEFT); + nk_layout_row_static(ctx, 180, 278, 1); + nk_edit_string(ctx, NK_EDIT_BOX, box_buffer, &box_len, 512, nk_filter_default); + + nk_layout_row(ctx, NK_STATIC, 25, 2, ratio); + active = nk_edit_string(ctx, NK_EDIT_FIELD|NK_EDIT_SIG_ENTER, text[7], &text_len[7], 64, nk_filter_ascii); + if (nk_button_label(ctx, "Submit") || + (active & NK_EDIT_COMMITED)) + { + text[7][text_len[7]] = '\n'; + text_len[7]++; + memcpy(&box_buffer[box_len], &text[7], (nk_size)text_len[7]); + box_len += text_len[7]; + text_len[7] = 0; + } + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Horizontal Rule", NK_MINIMIZED)) + { + nk_layout_row_dynamic(ctx, 12, 1); + nk_label(ctx, "Use this to subdivide spaces visually", NK_TEXT_LEFT); + nk_layout_row_dynamic(ctx, 4, 1); + nk_rule_horizontal(ctx, nk_rgb(255, 255, 255), nk_true); + nk_layout_row_dynamic(ctx, 75, 1); + nk_label_wrap(ctx, "Best used in 'Card'-like layouts, with a bigger title font on top. Takes on the size of the previous layout definition. Rounding optional."); + nk_tree_pop(ctx); + } + + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_TAB, "Chart", NK_MINIMIZED)) + { + /* Chart Widgets + * This library has two different rather simple charts. The line and the + * column chart. Both provide a simple way of visualizing values and + * have a retained mode and immediate mode API version. For the retain + * mode version `nk_plot` and `nk_plot_function` you either provide + * an array or a callback to call to handle drawing the graph. + * For the immediate mode version you start by calling `nk_chart_begin` + * and need to provide min and max values for scaling on the Y-axis. + * and then call `nk_chart_push` to push values into the chart. + * Finally `nk_chart_end` needs to be called to end the process. */ + float id = 0; + static int col_index = -1; + static int line_index = -1; + float step = (2*3.141592654f) / 32; + + int i; + int index = -1; + + /* line chart */ + id = 0; + index = -1; + nk_layout_row_dynamic(ctx, 100, 1); + if (nk_chart_begin(ctx, NK_CHART_LINES, 32, -1.0f, 1.0f)) { + for (i = 0; i < 32; ++i) { + nk_flags res = nk_chart_push(ctx, (float)cos(id)); + if (res & NK_CHART_HOVERING) + index = (int)i; + if (res & NK_CHART_CLICKED) + line_index = (int)i; + id += step; + } + nk_chart_end(ctx); + } + + if (index != -1) + nk_tooltipf(ctx, "Value: %.2f", (float)cos((float)index*step)); + if (line_index != -1) { + nk_layout_row_dynamic(ctx, 20, 1); + nk_labelf(ctx, NK_TEXT_LEFT, "Selected value: %.2f", (float)cos((float)index*step)); + } + + /* column chart */ + nk_layout_row_dynamic(ctx, 100, 1); + if (nk_chart_begin(ctx, NK_CHART_COLUMN, 32, 0.0f, 1.0f)) { + for (i = 0; i < 32; ++i) { + nk_flags res = nk_chart_push(ctx, (float)fabs(sin(id))); + if (res & NK_CHART_HOVERING) + index = (int)i; + if (res & NK_CHART_CLICKED) + col_index = (int)i; + id += step; + } + nk_chart_end(ctx); + } + if (index != -1) + nk_tooltipf(ctx, "Value: %.2f", (float)fabs(sin(step * (float)index))); + if (col_index != -1) { + nk_layout_row_dynamic(ctx, 20, 1); + nk_labelf(ctx, NK_TEXT_LEFT, "Selected value: %.2f", (float)fabs(sin(step * (float)col_index))); + } + + /* mixed chart */ + nk_layout_row_dynamic(ctx, 100, 1); + if (nk_chart_begin(ctx, NK_CHART_COLUMN, 32, 0.0f, 1.0f)) { + nk_chart_add_slot(ctx, NK_CHART_LINES, 32, -1.0f, 1.0f); + nk_chart_add_slot(ctx, NK_CHART_LINES, 32, -1.0f, 1.0f); + for (id = 0, i = 0; i < 32; ++i) { + nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0); + nk_chart_push_slot(ctx, (float)cos(id), 1); + nk_chart_push_slot(ctx, (float)sin(id), 2); + id += step; + } + } + nk_chart_end(ctx); + + /* mixed colored chart */ + nk_layout_row_dynamic(ctx, 100, 1); + if (nk_chart_begin_colored(ctx, NK_CHART_LINES, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) { + nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,0,255), nk_rgb(0,0,150),32, -1.0f, 1.0f); + nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,255,0), nk_rgb(0,150,0), 32, -1.0f, 1.0f); + for (id = 0, i = 0; i < 32; ++i) { + nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0); + nk_chart_push_slot(ctx, (float)cos(id), 1); + nk_chart_push_slot(ctx, (float)sin(id), 2); + id += step; + } + } + nk_chart_end(ctx); + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_TAB, "Popup", NK_MINIMIZED)) + { + static struct nk_color color = {255,0,0, 255}; + static int select[4]; + static int popup_active; + const struct nk_input *in = &ctx->input; + struct nk_rect bounds; + + /* menu contextual */ + nk_layout_row_static(ctx, 30, 160, 1); + bounds = nk_widget_bounds(ctx); + nk_label(ctx, "Right click me for menu", NK_TEXT_LEFT); + + if (nk_contextual_begin(ctx, 0, nk_vec2(100, 300), bounds)) { + static size_t prog = 40; + static int slider = 10; + + nk_layout_row_dynamic(ctx, 25, 1); + nk_checkbox_label(ctx, "Menu", &show_menu); + nk_progress(ctx, &prog, 100, NK_MODIFIABLE); + nk_slider_int(ctx, 0, &slider, 16, 1); + if (nk_contextual_item_label(ctx, "About", NK_TEXT_CENTERED)) + show_app_about = nk_true; + nk_selectable_label(ctx, select[0]?"Unselect":"Select", NK_TEXT_LEFT, &select[0]); + nk_selectable_label(ctx, select[1]?"Unselect":"Select", NK_TEXT_LEFT, &select[1]); + nk_selectable_label(ctx, select[2]?"Unselect":"Select", NK_TEXT_LEFT, &select[2]); + nk_selectable_label(ctx, select[3]?"Unselect":"Select", NK_TEXT_LEFT, &select[3]); + nk_contextual_end(ctx); + } + + /* color contextual */ + nk_layout_row_begin(ctx, NK_STATIC, 30, 2); + nk_layout_row_push(ctx, 120); + nk_label(ctx, "Right Click here:", NK_TEXT_LEFT); + nk_layout_row_push(ctx, 50); + bounds = nk_widget_bounds(ctx); + nk_button_color(ctx, color); + nk_layout_row_end(ctx); + + if (nk_contextual_begin(ctx, 0, nk_vec2(350, 60), bounds)) { + nk_layout_row_dynamic(ctx, 30, 4); + color.r = (nk_byte)nk_propertyi(ctx, "#r", 0, color.r, 255, 1, 1); + color.g = (nk_byte)nk_propertyi(ctx, "#g", 0, color.g, 255, 1, 1); + color.b = (nk_byte)nk_propertyi(ctx, "#b", 0, color.b, 255, 1, 1); + color.a = (nk_byte)nk_propertyi(ctx, "#a", 0, color.a, 255, 1, 1); + nk_contextual_end(ctx); + } + + /* popup */ + nk_layout_row_begin(ctx, NK_STATIC, 30, 2); + nk_layout_row_push(ctx, 120); + nk_label(ctx, "Popup:", NK_TEXT_LEFT); + nk_layout_row_push(ctx, 50); + if (nk_button_label(ctx, "Popup")) + popup_active = 1; + nk_layout_row_end(ctx); + + if (popup_active) + { + static struct nk_rect s = {20, 100, 220, 90}; + if (nk_popup_begin(ctx, NK_POPUP_STATIC, "Error", 0, s)) + { + nk_layout_row_dynamic(ctx, 25, 1); + nk_label(ctx, "A terrible error as occurred", NK_TEXT_LEFT); + nk_layout_row_dynamic(ctx, 25, 2); + if (nk_button_label(ctx, "OK")) { + popup_active = 0; + nk_popup_close(ctx); + } + if (nk_button_label(ctx, "Cancel")) { + popup_active = 0; + nk_popup_close(ctx); + } + nk_popup_end(ctx); + } else popup_active = nk_false; + } + + /* tooltip */ + nk_layout_row_static(ctx, 30, 150, 1); + bounds = nk_widget_bounds(ctx); + nk_label(ctx, "Hover me for tooltip", NK_TEXT_LEFT); + if (nk_input_is_mouse_hovering_rect(in, bounds)) + nk_tooltip(ctx, "This is a tooltip"); + + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_TAB, "Layout", NK_MINIMIZED)) + { + if (nk_tree_push(ctx, NK_TREE_NODE, "Widget", NK_MINIMIZED)) + { + float ratio_two[] = {0.2f, 0.6f, 0.2f}; + float width_two[] = {100, 200, 50}; + + nk_layout_row_dynamic(ctx, 30, 1); + nk_label(ctx, "Dynamic fixed column layout with generated position and size:", NK_TEXT_LEFT); + nk_layout_row_dynamic(ctx, 30, 3); + nk_button_label(ctx, "button"); + nk_button_label(ctx, "button"); + nk_button_label(ctx, "button"); + + nk_layout_row_dynamic(ctx, 30, 1); + nk_label(ctx, "static fixed column layout with generated position and size:", NK_TEXT_LEFT); + nk_layout_row_static(ctx, 30, 100, 3); + nk_button_label(ctx, "button"); + nk_button_label(ctx, "button"); + nk_button_label(ctx, "button"); + + nk_layout_row_dynamic(ctx, 30, 1); + nk_label(ctx, "Dynamic array-based custom column layout with generated position and custom size:",NK_TEXT_LEFT); + nk_layout_row(ctx, NK_DYNAMIC, 30, 3, ratio_two); + nk_button_label(ctx, "button"); + nk_button_label(ctx, "button"); + nk_button_label(ctx, "button"); + + nk_layout_row_dynamic(ctx, 30, 1); + nk_label(ctx, "Static array-based custom column layout with generated position and custom size:",NK_TEXT_LEFT ); + nk_layout_row(ctx, NK_STATIC, 30, 3, width_two); + nk_button_label(ctx, "button"); + nk_button_label(ctx, "button"); + nk_button_label(ctx, "button"); + + nk_layout_row_dynamic(ctx, 30, 1); + nk_label(ctx, "Dynamic immediate mode custom column layout with generated position and custom size:",NK_TEXT_LEFT); + nk_layout_row_begin(ctx, NK_DYNAMIC, 30, 3); + nk_layout_row_push(ctx, 0.2f); + nk_button_label(ctx, "button"); + nk_layout_row_push(ctx, 0.6f); + nk_button_label(ctx, "button"); + nk_layout_row_push(ctx, 0.2f); + nk_button_label(ctx, "button"); + nk_layout_row_end(ctx); + + nk_layout_row_dynamic(ctx, 30, 1); + nk_label(ctx, "Static immediate mode custom column layout with generated position and custom size:", NK_TEXT_LEFT); + nk_layout_row_begin(ctx, NK_STATIC, 30, 3); + nk_layout_row_push(ctx, 100); + nk_button_label(ctx, "button"); + nk_layout_row_push(ctx, 200); + nk_button_label(ctx, "button"); + nk_layout_row_push(ctx, 50); + nk_button_label(ctx, "button"); + nk_layout_row_end(ctx); + + nk_layout_row_dynamic(ctx, 30, 1); + nk_label(ctx, "Static free space with custom position and custom size:", NK_TEXT_LEFT); + nk_layout_space_begin(ctx, NK_STATIC, 60, 4); + nk_layout_space_push(ctx, nk_rect(100, 0, 100, 30)); + nk_button_label(ctx, "button"); + nk_layout_space_push(ctx, nk_rect(0, 15, 100, 30)); + nk_button_label(ctx, "button"); + nk_layout_space_push(ctx, nk_rect(200, 15, 100, 30)); + nk_button_label(ctx, "button"); + nk_layout_space_push(ctx, nk_rect(100, 30, 100, 30)); + nk_button_label(ctx, "button"); + nk_layout_space_end(ctx); + + nk_layout_row_dynamic(ctx, 30, 1); + nk_label(ctx, "Row template:", NK_TEXT_LEFT); + nk_layout_row_template_begin(ctx, 30); + nk_layout_row_template_push_dynamic(ctx); + nk_layout_row_template_push_variable(ctx, 80); + nk_layout_row_template_push_static(ctx, 80); + nk_layout_row_template_end(ctx); + nk_button_label(ctx, "button"); + nk_button_label(ctx, "button"); + nk_button_label(ctx, "button"); + + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Group", NK_MINIMIZED)) + { + static int group_titlebar = nk_false; + static int group_border = nk_true; + static int group_no_scrollbar = nk_false; + static int group_width = 320; + static int group_height = 200; + + nk_flags group_flags = 0; + if (group_border) group_flags |= NK_WINDOW_BORDER; + if (group_no_scrollbar) group_flags |= NK_WINDOW_NO_SCROLLBAR; + if (group_titlebar) group_flags |= NK_WINDOW_TITLE; + + nk_layout_row_dynamic(ctx, 30, 3); + nk_checkbox_label(ctx, "Titlebar", &group_titlebar); + nk_checkbox_label(ctx, "Border", &group_border); + nk_checkbox_label(ctx, "No Scrollbar", &group_no_scrollbar); + + nk_layout_row_begin(ctx, NK_STATIC, 22, 3); + nk_layout_row_push(ctx, 50); + nk_label(ctx, "size:", NK_TEXT_LEFT); + nk_layout_row_push(ctx, 130); + nk_property_int(ctx, "#Width:", 100, &group_width, 500, 10, 1); + nk_layout_row_push(ctx, 130); + nk_property_int(ctx, "#Height:", 100, &group_height, 500, 10, 1); + nk_layout_row_end(ctx); + + nk_layout_row_static(ctx, (float)group_height, group_width, 2); + if (nk_group_begin(ctx, "Group", group_flags)) { + int i = 0; + static int selected[16]; + nk_layout_row_static(ctx, 18, 100, 1); + for (i = 0; i < 16; ++i) + nk_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_CENTERED, &selected[i]); + nk_group_end(ctx); + } + nk_tree_pop(ctx); + } + if (nk_tree_push(ctx, NK_TREE_NODE, "Tree", NK_MINIMIZED)) + { + static int root_selected = 0; + int sel = root_selected; + if (nk_tree_element_push(ctx, NK_TREE_NODE, "Root", NK_MINIMIZED, &sel)) { + static int selected[8]; + int i = 0, node_select = selected[0]; + if (sel != root_selected) { + root_selected = sel; + for (i = 0; i < 8; ++i) + selected[i] = sel; + } + if (nk_tree_element_push(ctx, NK_TREE_NODE, "Node", NK_MINIMIZED, &node_select)) { + int j = 0; + static int sel_nodes[4]; + if (node_select != selected[0]) { + selected[0] = node_select; + for (i = 0; i < 4; ++i) + sel_nodes[i] = node_select; + } + nk_layout_row_static(ctx, 18, 100, 1); + for (j = 0; j < 4; ++j) + nk_selectable_symbol_label(ctx, NK_SYMBOL_CIRCLE_SOLID, (sel_nodes[j]) ? "Selected": "Unselected", NK_TEXT_RIGHT, &sel_nodes[j]); + nk_tree_element_pop(ctx); + } + nk_layout_row_static(ctx, 18, 100, 1); + for (i = 1; i < 8; ++i) + nk_selectable_symbol_label(ctx, NK_SYMBOL_CIRCLE_SOLID, (selected[i]) ? "Selected": "Unselected", NK_TEXT_RIGHT, &selected[i]); + nk_tree_element_pop(ctx); + } + nk_tree_pop(ctx); + } + if (nk_tree_push(ctx, NK_TREE_NODE, "Notebook", NK_MINIMIZED)) + { + static int current_tab = 0; + float step = (2*3.141592654f) / 32; + enum chart_type {CHART_LINE, CHART_HISTO, CHART_MIXED}; + const char *names[] = {"Lines", "Columns", "Mixed"}; + float id = 0; + int i; + + /* Header */ + nk_style_push_vec2(ctx, &ctx->style.window.spacing, nk_vec2(0,0)); + nk_style_push_float(ctx, &ctx->style.button.rounding, 0); + nk_layout_row_begin(ctx, NK_STATIC, 20, 3); + for (i = 0; i < 3; ++i) { + /* make sure button perfectly fits text */ + const struct nk_user_font *f = ctx->style.font; + float text_width = f->width(f->userdata, f->height, names[i], nk_strlen(names[i])); + float widget_width = text_width + 3 * ctx->style.button.padding.x; + nk_layout_row_push(ctx, widget_width); + if (current_tab == i) { + /* active tab gets highlighted */ + struct nk_style_item button_color = ctx->style.button.normal; + ctx->style.button.normal = ctx->style.button.active; + current_tab = nk_button_label(ctx, names[i]) ? i: current_tab; + ctx->style.button.normal = button_color; + } else current_tab = nk_button_label(ctx, names[i]) ? i: current_tab; + } + nk_style_pop_float(ctx); + + /* Body */ + nk_layout_row_dynamic(ctx, 140, 1); + if (nk_group_begin(ctx, "Notebook", NK_WINDOW_BORDER)) + { + nk_style_pop_vec2(ctx); + switch (current_tab) { + default: break; + case CHART_LINE: + nk_layout_row_dynamic(ctx, 100, 1); + if (nk_chart_begin_colored(ctx, NK_CHART_LINES, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) { + nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,0,255), nk_rgb(0,0,150),32, -1.0f, 1.0f); + for (i = 0, id = 0; i < 32; ++i) { + nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0); + nk_chart_push_slot(ctx, (float)cos(id), 1); + id += step; + } + } + nk_chart_end(ctx); + break; + case CHART_HISTO: + nk_layout_row_dynamic(ctx, 100, 1); + if (nk_chart_begin_colored(ctx, NK_CHART_COLUMN, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) { + for (i = 0, id = 0; i < 32; ++i) { + nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0); + id += step; + } + } + nk_chart_end(ctx); + break; + case CHART_MIXED: + nk_layout_row_dynamic(ctx, 100, 1); + if (nk_chart_begin_colored(ctx, NK_CHART_LINES, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) { + nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,0,255), nk_rgb(0,0,150),32, -1.0f, 1.0f); + nk_chart_add_slot_colored(ctx, NK_CHART_COLUMN, nk_rgb(0,255,0), nk_rgb(0,150,0), 32, 0.0f, 1.0f); + for (i = 0, id = 0; i < 32; ++i) { + nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0); + nk_chart_push_slot(ctx, (float)fabs(cos(id)), 1); + nk_chart_push_slot(ctx, (float)fabs(sin(id)), 2); + id += step; + } + } + nk_chart_end(ctx); + break; + } + nk_group_end(ctx); + } else nk_style_pop_vec2(ctx); + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Simple", NK_MINIMIZED)) + { + nk_layout_row_dynamic(ctx, 300, 2); + if (nk_group_begin(ctx, "Group_Without_Border", 0)) { + int i = 0; + char buffer[64]; + nk_layout_row_static(ctx, 18, 150, 1); + for (i = 0; i < 64; ++i) { + sprintf(buffer, "0x%02x", i); + nk_labelf(ctx, NK_TEXT_LEFT, "%s: scrollable region", buffer); + } + nk_group_end(ctx); + } + if (nk_group_begin(ctx, "Group_With_Border", NK_WINDOW_BORDER)) { + int i = 0; + char buffer[64]; + nk_layout_row_dynamic(ctx, 25, 2); + for (i = 0; i < 64; ++i) { + sprintf(buffer, "%08d", ((((i%7)*10)^32))+(64+(i%2)*2)); + nk_button_label(ctx, buffer); + } + nk_group_end(ctx); + } + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Complex", NK_MINIMIZED)) + { + int i; + nk_layout_space_begin(ctx, NK_STATIC, 500, 64); + nk_layout_space_push(ctx, nk_rect(0,0,150,500)); + if (nk_group_begin(ctx, "Group_left", NK_WINDOW_BORDER)) { + static int selected[32]; + nk_layout_row_static(ctx, 18, 100, 1); + for (i = 0; i < 32; ++i) + nk_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_CENTERED, &selected[i]); + nk_group_end(ctx); + } + + nk_layout_space_push(ctx, nk_rect(160,0,150,240)); + if (nk_group_begin(ctx, "Group_top", NK_WINDOW_BORDER)) { + nk_layout_row_dynamic(ctx, 25, 1); + nk_button_label(ctx, "#FFAA"); + nk_button_label(ctx, "#FFBB"); + nk_button_label(ctx, "#FFCC"); + nk_button_label(ctx, "#FFDD"); + nk_button_label(ctx, "#FFEE"); + nk_button_label(ctx, "#FFFF"); + nk_group_end(ctx); + } + + nk_layout_space_push(ctx, nk_rect(160,250,150,250)); + if (nk_group_begin(ctx, "Group_buttom", NK_WINDOW_BORDER)) { + nk_layout_row_dynamic(ctx, 25, 1); + nk_button_label(ctx, "#FFAA"); + nk_button_label(ctx, "#FFBB"); + nk_button_label(ctx, "#FFCC"); + nk_button_label(ctx, "#FFDD"); + nk_button_label(ctx, "#FFEE"); + nk_button_label(ctx, "#FFFF"); + nk_group_end(ctx); + } + + nk_layout_space_push(ctx, nk_rect(320,0,150,150)); + if (nk_group_begin(ctx, "Group_right_top", NK_WINDOW_BORDER)) { + static int selected[4]; + nk_layout_row_static(ctx, 18, 100, 1); + for (i = 0; i < 4; ++i) + nk_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_CENTERED, &selected[i]); + nk_group_end(ctx); + } + + nk_layout_space_push(ctx, nk_rect(320,160,150,150)); + if (nk_group_begin(ctx, "Group_right_center", NK_WINDOW_BORDER)) { + static int selected[4]; + nk_layout_row_static(ctx, 18, 100, 1); + for (i = 0; i < 4; ++i) + nk_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_CENTERED, &selected[i]); + nk_group_end(ctx); + } + + nk_layout_space_push(ctx, nk_rect(320,320,150,150)); + if (nk_group_begin(ctx, "Group_right_bottom", NK_WINDOW_BORDER)) { + static int selected[4]; + nk_layout_row_static(ctx, 18, 100, 1); + for (i = 0; i < 4; ++i) + nk_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_CENTERED, &selected[i]); + nk_group_end(ctx); + } + nk_layout_space_end(ctx); + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Splitter", NK_MINIMIZED)) + { + const struct nk_input *in = &ctx->input; + nk_layout_row_static(ctx, 20, 320, 1); + nk_label(ctx, "Use slider and spinner to change tile size", NK_TEXT_LEFT); + nk_label(ctx, "Drag the space between tiles to change tile ratio", NK_TEXT_LEFT); + + if (nk_tree_push(ctx, NK_TREE_NODE, "Vertical", NK_MINIMIZED)) + { + static float a = 100, b = 100, c = 100; + struct nk_rect bounds; + + float row_layout[5]; + row_layout[0] = a; + row_layout[1] = 8; + row_layout[2] = b; + row_layout[3] = 8; + row_layout[4] = c; + + /* header */ + nk_layout_row_static(ctx, 30, 100, 2); + nk_label(ctx, "left:", NK_TEXT_LEFT); + nk_slider_float(ctx, 10.0f, &a, 200.0f, 10.0f); + + nk_label(ctx, "middle:", NK_TEXT_LEFT); + nk_slider_float(ctx, 10.0f, &b, 200.0f, 10.0f); + + nk_label(ctx, "right:", NK_TEXT_LEFT); + nk_slider_float(ctx, 10.0f, &c, 200.0f, 10.0f); + + /* tiles */ + nk_layout_row(ctx, NK_STATIC, 200, 5, row_layout); + + /* left space */ + if (nk_group_begin(ctx, "left", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR)) { + nk_layout_row_dynamic(ctx, 25, 1); + nk_button_label(ctx, "#FFAA"); + nk_button_label(ctx, "#FFBB"); + nk_button_label(ctx, "#FFCC"); + nk_button_label(ctx, "#FFDD"); + nk_button_label(ctx, "#FFEE"); + nk_button_label(ctx, "#FFFF"); + nk_group_end(ctx); + } + + /* scaler */ + bounds = nk_widget_bounds(ctx); + nk_spacing(ctx, 1); + if ((nk_input_is_mouse_hovering_rect(in, bounds) || + nk_input_is_mouse_prev_hovering_rect(in, bounds)) && + nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) + { + a = row_layout[0] + in->mouse.delta.x; + b = row_layout[2] - in->mouse.delta.x; + } + + /* middle space */ + if (nk_group_begin(ctx, "center", NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR)) { + nk_layout_row_dynamic(ctx, 25, 1); + nk_button_label(ctx, "#FFAA"); + nk_button_label(ctx, "#FFBB"); + nk_button_label(ctx, "#FFCC"); + nk_button_label(ctx, "#FFDD"); + nk_button_label(ctx, "#FFEE"); + nk_button_label(ctx, "#FFFF"); + nk_group_end(ctx); + } + + /* scaler */ + bounds = nk_widget_bounds(ctx); + nk_spacing(ctx, 1); + if ((nk_input_is_mouse_hovering_rect(in, bounds) || + nk_input_is_mouse_prev_hovering_rect(in, bounds)) && + nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) + { + b = (row_layout[2] + in->mouse.delta.x); + c = (row_layout[4] - in->mouse.delta.x); + } + + /* right space */ + if (nk_group_begin(ctx, "right", NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR)) { + nk_layout_row_dynamic(ctx, 25, 1); + nk_button_label(ctx, "#FFAA"); + nk_button_label(ctx, "#FFBB"); + nk_button_label(ctx, "#FFCC"); + nk_button_label(ctx, "#FFDD"); + nk_button_label(ctx, "#FFEE"); + nk_button_label(ctx, "#FFFF"); + nk_group_end(ctx); + } + + nk_tree_pop(ctx); + } + + if (nk_tree_push(ctx, NK_TREE_NODE, "Horizontal", NK_MINIMIZED)) + { + static float a = 100, b = 100, c = 100; + struct nk_rect bounds; + + /* header */ + nk_layout_row_static(ctx, 30, 100, 2); + nk_label(ctx, "top:", NK_TEXT_LEFT); + nk_slider_float(ctx, 10.0f, &a, 200.0f, 10.0f); + + nk_label(ctx, "middle:", NK_TEXT_LEFT); + nk_slider_float(ctx, 10.0f, &b, 200.0f, 10.0f); + + nk_label(ctx, "bottom:", NK_TEXT_LEFT); + nk_slider_float(ctx, 10.0f, &c, 200.0f, 10.0f); + + /* top space */ + nk_layout_row_dynamic(ctx, a, 1); + if (nk_group_begin(ctx, "top", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER)) { + nk_layout_row_dynamic(ctx, 25, 3); + nk_button_label(ctx, "#FFAA"); + nk_button_label(ctx, "#FFBB"); + nk_button_label(ctx, "#FFCC"); + nk_button_label(ctx, "#FFDD"); + nk_button_label(ctx, "#FFEE"); + nk_button_label(ctx, "#FFFF"); + nk_group_end(ctx); + } + + /* scaler */ + nk_layout_row_dynamic(ctx, 8, 1); + bounds = nk_widget_bounds(ctx); + nk_spacing(ctx, 1); + if ((nk_input_is_mouse_hovering_rect(in, bounds) || + nk_input_is_mouse_prev_hovering_rect(in, bounds)) && + nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) + { + a = a + in->mouse.delta.y; + b = b - in->mouse.delta.y; + } + + /* middle space */ + nk_layout_row_dynamic(ctx, b, 1); + if (nk_group_begin(ctx, "middle", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER)) { + nk_layout_row_dynamic(ctx, 25, 3); + nk_button_label(ctx, "#FFAA"); + nk_button_label(ctx, "#FFBB"); + nk_button_label(ctx, "#FFCC"); + nk_button_label(ctx, "#FFDD"); + nk_button_label(ctx, "#FFEE"); + nk_button_label(ctx, "#FFFF"); + nk_group_end(ctx); + } + + { + /* scaler */ + nk_layout_row_dynamic(ctx, 8, 1); + bounds = nk_widget_bounds(ctx); + if ((nk_input_is_mouse_hovering_rect(in, bounds) || + nk_input_is_mouse_prev_hovering_rect(in, bounds)) && + nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) + { + b = b + in->mouse.delta.y; + c = c - in->mouse.delta.y; + } + } + + /* bottom space */ + nk_layout_row_dynamic(ctx, c, 1); + if (nk_group_begin(ctx, "bottom", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER)) { + nk_layout_row_dynamic(ctx, 25, 3); + nk_button_label(ctx, "#FFAA"); + nk_button_label(ctx, "#FFBB"); + nk_button_label(ctx, "#FFCC"); + nk_button_label(ctx, "#FFDD"); + nk_button_label(ctx, "#FFEE"); + nk_button_label(ctx, "#FFFF"); + nk_group_end(ctx); + } + nk_tree_pop(ctx); + } + nk_tree_pop(ctx); + } + nk_tree_pop(ctx); + } + } + nk_end(ctx); + return !nk_window_is_closed(ctx, "Overview"); +} +