diff --git a/demo/demo.c b/demo/demo.c index fdd643e..9ea63a1 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -229,21 +229,6 @@ demo_window(struct zr_layout *layout, struct zr_context *ctx, enum theme *theme) } else show_color_picker_popup = zr_false; } - /* contextual menu */ - if (zr_contextual_begin(ctx, &menu, 0, zr_vec2(100, 200), zr_window_get_bounds(ctx))) { - static size_t prog = 40; - static int slider = 10; - zr_layout_row_dynamic(ctx, 25, 1); - zr_checkbox(ctx, "Menu", &show_menu); - zr_progress(ctx, &prog, 100, ZR_MODIFIABLE); - zr_slider_int(ctx, 0, &slider, 16, 1); - if (zr_contextual_item(ctx, "About", ZR_TEXT_CENTERED)) - show_app_about = zr_true; - if (zr_contextual_item(ctx, "Quit", ZR_TEXT_CENTERED)) - show_close_popup = zr_true; - zr_contextual_end(ctx); - } - /* window flags */ if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Window")) { zr_layout_row_dynamic(ctx, 30, 2); @@ -385,10 +370,7 @@ demo_window(struct zr_layout *layout, struct zr_context *ctx, enum theme *theme) static int range_int_min = 0; static int range_int_value = 2048; static int range_int_max = 4096; - static const float ratio[] = {120, 150}; - const struct zr_input *in = &ctx->input; - struct zr_rect bounds; zr_layout_row_static(ctx, 30, 100, 1); zr_checkbox(ctx, "Checkbox", &checkbox); @@ -398,11 +380,6 @@ demo_window(struct zr_layout *layout, struct zr_context *ctx, enum theme *theme) option = zr_option(ctx, "optionB", option == B) ? B : option; option = zr_option(ctx, "optionC", option == C) ? C : option; - zr_layout_row_static(ctx, 30, 150, 1); - zr_layout_peek(&bounds, ctx); - zr_label(ctx, "Hover me for tooltip", ZR_TEXT_LEFT); - if (zr_input_is_mouse_hovering_rect(in, bounds)) - zr_tooltip(ctx, "This is a tooltip"); zr_layout_row(ctx, ZR_STATIC, 30, 2, ratio); zr_labelf(ctx, ZR_TEXT_LEFT, "Slider int"); @@ -604,7 +581,6 @@ demo_window(struct zr_layout *layout, struct zr_context *ctx, enum theme *theme) box_len += text_len[7]; text_len[7] = 0; } - zr_layout_row_end(ctx); zr_layout_pop(ctx); } @@ -675,8 +651,177 @@ demo_window(struct zr_layout *layout, struct zr_context *ctx, enum theme *theme) zr_layout_pop(ctx); } + if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Popup")) + { + enum {NONE=0, MENU=1, COLOR=2}; + static int active = MENU; + static struct zr_color color = {255,0,0, 255}; + static int select[4]; + static int popup_active; + + const struct zr_input *in = &ctx->input; + struct zr_rect menu_bounds, color_bounds, bounds; + int is_menu, is_color; + struct zr_vec2 size; + + /* contextual */ + zr_layout_row_static(ctx, 30, 150, 1); + zr_layout_peek(&menu_bounds, ctx); + zr_label(ctx, "Right click me for menu", ZR_TEXT_LEFT); + + /* color contextual */ + zr_layout_row_begin(ctx, ZR_STATIC, 30, 2); + zr_layout_row_push(ctx, 100); + zr_label(ctx, "Right Click here:", ZR_TEXT_LEFT); + zr_layout_row_push(ctx, 50); + zr_layout_peek(&color_bounds, ctx); + zr_button_color(ctx, color, ZR_BUTTON_DEFAULT); + zr_layout_row_end(ctx); + + /* This is a shitty hack to accomplish multiple contextual menus */ + is_menu = zr_input_mouse_clicked(in, ZR_BUTTON_RIGHT, menu_bounds); + is_color = zr_input_mouse_clicked(in, ZR_BUTTON_RIGHT, color_bounds); + size = (is_color || active == COLOR) ? zr_vec2(350, 60): zr_vec2(100, 200); + if (zr_contextual_begin(ctx, &menu, 0, size, is_color|is_menu)) { + if (is_menu || active == MENU) { + static size_t prog = 40; + static int slider = 10; + + active = MENU; + zr_layout_row_dynamic(ctx, 25, 1); + zr_checkbox(ctx, "Menu", &show_menu); + zr_progress(ctx, &prog, 100, ZR_MODIFIABLE); + zr_slider_int(ctx, 0, &slider, 16, 1); + zr_selectable(ctx, select[0]?"Unselect":"Select", ZR_TEXT_LEFT, &select[0]); + zr_selectable(ctx, select[1]?"Unselect":"Select", ZR_TEXT_LEFT, &select[1]); + zr_selectable(ctx, select[2]?"Unselect":"Select", ZR_TEXT_LEFT, &select[2]); + zr_selectable(ctx, select[3]?"Unselect":"Select", ZR_TEXT_LEFT, &select[3]); + if (zr_contextual_item(ctx, "About", ZR_TEXT_CENTERED)) + show_app_about = zr_true; + if (zr_contextual_item(ctx, "Quit", ZR_TEXT_CENTERED)) + show_close_popup = zr_true; + } else if (is_color || active == COLOR){ + active = COLOR; + zr_layout_row_dynamic(ctx, 30, 4); + color.r = (zr_byte)zr_propertyi(ctx, "#r", 0, color.r, 255, 1, 1); + color.g = (zr_byte)zr_propertyi(ctx, "#g", 0, color.g, 255, 1, 1); + color.b = (zr_byte)zr_propertyi(ctx, "#b", 0, color.b, 255, 1, 1); + color.a = (zr_byte)zr_propertyi(ctx, "#a", 0, color.a, 255, 1, 1); + } + zr_contextual_end(ctx); + } else active = NONE; + + /* popup */ + zr_layout_row_begin(ctx, ZR_STATIC, 30, 2); + zr_layout_row_push(ctx, 100); + zr_label(ctx, "Popup:", ZR_TEXT_LEFT); + zr_layout_row_push(ctx, 50); + if (zr_button_text(ctx, "Popup", ZR_BUTTON_DEFAULT)) + popup_active = 1; + zr_layout_row_end(ctx); + + if (popup_active) + { + static struct zr_rect s = {20, 100, 220, 150}; + if (zr_popup_begin(ctx, &menu, ZR_POPUP_STATIC, "Error", ZR_WINDOW_DYNAMIC, s)) + { + zr_layout_row_dynamic(ctx, 25, 1); + zr_label(ctx, "A terrible error as occured", ZR_TEXT_LEFT); + zr_layout_row_dynamic(ctx, 25, 2); + if (zr_button_text(ctx, "OK", ZR_BUTTON_DEFAULT)) { + popup_active = 0; + zr_popup_close(ctx); + } + if (zr_button_text(ctx, "Cancel", ZR_BUTTON_DEFAULT)) { + popup_active = 0; + zr_popup_close(ctx); + } + zr_popup_end(ctx); + } else popup_active = zr_false; + } + + /* tooltip */ + zr_layout_row_static(ctx, 30, 150, 1); + zr_layout_peek(&bounds, ctx); + zr_label(ctx, "Hover me for tooltip", ZR_TEXT_LEFT); + if (zr_input_is_mouse_hovering_rect(in, bounds)) + zr_tooltip(ctx, "This is a tooltip"); + + zr_layout_pop(ctx); + } + if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Layout")) { + if (zr_layout_push(ctx, ZR_LAYOUT_NODE, "Widget")) + { + float ratio_two[] = {0.2f, 0.6f, 0.2f}; + float width_two[] = {100, 200, 50}; + + zr_layout_row_dynamic(ctx, 30, 1); + zr_label(ctx, "Dynamic fixed column layout with generated position and size:", ZR_TEXT_LEFT); + zr_layout_row_dynamic(ctx, 30, 3); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + + zr_layout_row_dynamic(ctx, 30, 1); + zr_label(ctx, "static fixed column layout with generated position and size:", ZR_TEXT_LEFT); + zr_layout_row_static(ctx, 30, 100, 3); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + + zr_layout_row_dynamic(ctx, 30, 1); + zr_label(ctx, "Dynamic array-based custom column layout with generated position and custom size:",ZR_TEXT_LEFT); + zr_layout_row(ctx, ZR_DYNAMIC, 30, 3, ratio_two); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + + zr_layout_row_dynamic(ctx, 30, 1); + zr_label(ctx, "Static array-based custom column layout with generated position and custom size:",ZR_TEXT_LEFT ); + zr_layout_row(ctx, ZR_STATIC, 30, 3, width_two); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + + zr_layout_row_dynamic(ctx, 30, 1); + zr_label(ctx, "Dynamic immediate mode custom column layout with generated position and custom size:",ZR_TEXT_LEFT); + zr_layout_row_begin(ctx, ZR_DYNAMIC, 30, 3); + zr_layout_row_push(ctx, 0.2f); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_layout_row_push(ctx, 0.6f); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_layout_row_push(ctx, 0.2f); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_layout_row_end(ctx); + + zr_layout_row_dynamic(ctx, 30, 1); + zr_label(ctx, "Static immmediate mode custom column layout with generated position and custom size:", ZR_TEXT_LEFT); + zr_layout_row_begin(ctx, ZR_STATIC, 30, 3); + zr_layout_row_push(ctx, 100); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_layout_row_push(ctx, 200); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_layout_row_push(ctx, 50); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_layout_row_end(ctx); + + zr_layout_row_dynamic(ctx, 30, 1); + zr_label(ctx, "Static free space with custom position and custom size:", ZR_TEXT_LEFT); + zr_layout_space_begin(ctx, ZR_STATIC, 120, 4); + zr_layout_space_push(ctx, zr_rect(100, 0, 100, 30)); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_layout_space_push(ctx, zr_rect(0, 15, 100, 30)); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_layout_space_push(ctx, zr_rect(200, 15, 100, 30)); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_layout_space_push(ctx, zr_rect(100, 30, 100, 30)); + zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_layout_space_end(ctx); + zr_layout_pop(ctx); + } + if (zr_layout_push(ctx, ZR_LAYOUT_NODE, "Group")) { static int group_titlebar = zr_false; diff --git a/example/demo/demo.c b/example/demo/demo.c index f8955fb..3408648 100644 --- a/example/demo/demo.c +++ b/example/demo/demo.c @@ -131,7 +131,6 @@ ui_piemenu(struct zr_context *ctx, zr_push_color(ctx, ZR_COLOR_WINDOW, zr_rgba(0,0,0,0)); border = ctx->style.colors[ZR_COLOR_BORDER]; zr_push_color(ctx, ZR_COLOR_BORDER, zr_rgba(0,0,0,0)); - if (ctx->current != ctx->active) return 0; /* pie menu popup */ total_space = zr_window_get_content_region(ctx); @@ -229,6 +228,7 @@ button_demo(struct zr_context *ctx, struct icons *img) static int toggle0 = 1; static int toggle1 = 0; static int toggle2 = 1; + int clicked = 0; ctx->style.font.height = 20; zr_begin(ctx, &layout, "Button Demo", zr_rect(50,50,255,610), @@ -314,7 +314,8 @@ button_demo(struct zr_context *ctx, struct icons *img) /*------------------------------------------------ * CONTEXTUAL *------------------------------------------------*/ - if (zr_contextual_begin(ctx, &menu, ZR_WINDOW_NO_SCROLLBAR, zr_vec2(120, 200), zr_window_get_bounds(ctx))) { + clicked = zr_input_mouse_clicked(&ctx->input, ZR_BUTTON_RIGHT, zr_window_get_bounds(ctx)); + if (zr_contextual_begin(ctx, &menu, ZR_WINDOW_NO_SCROLLBAR, zr_vec2(120, 200), clicked)) { ctx->style.font.height = 18; zr_layout_row_dynamic(ctx, 25, 1); if (zr_contextual_item_icon(ctx, zr_image_id(img->copy), "Clone", ZR_TEXT_RIGHT)) diff --git a/zahnrad.c b/zahnrad.c index 5043640..b9af793 100644 --- a/zahnrad.c +++ b/zahnrad.c @@ -106,6 +106,7 @@ struct zr_popup { struct zr_window *win; enum zr_internal_window_flags type; zr_ulong name; + int active; }; struct zr_edit_state { @@ -7344,6 +7345,15 @@ zr_layout_end(struct zr_context *ctx) footer.y = window->bounds.y + layout->height + item_spacing.y; footer.w = window->bounds.w + scrollbar_size; layout->footer_h = 0; + + if ((layout->offset->x == 0) && !(layout->flags & ZR_WINDOW_NO_SCROLLBAR)) { + struct zr_rect bounds; + bounds.x = layout->bounds.x + layout->width; + bounds.y = layout->clip.y; + bounds.w = scrollbar_size; + bounds.h = layout->height; + zr_draw_rect(out, bounds, 0, config->colors[ZR_COLOR_WINDOW]); + } } else { footer.x = window->bounds.x; footer.w = window->bounds.w + scrollbar_size; @@ -9540,12 +9550,17 @@ zr_popup_begin(struct zr_context *ctx, struct zr_layout *layout, if (!popup) { popup = zr_create_window(ctx); win->popup.win = popup; + win->popup.active = 0; } if (win->popup.name != title_hash) { - zr_zero(popup, sizeof(*popup)); - win->popup.name = title_hash; + if (!win->popup.active) { + zr_zero(popup, sizeof(*popup)); + win->popup.name = title_hash; + win->popup.active = 1; + } else return 0; } + ctx->current = popup; rect.x += win->layout->clip.x; rect.y += win->layout->clip.y; @@ -9566,11 +9581,13 @@ zr_popup_begin(struct zr_context *ctx, struct zr_layout *layout, if (zr_layout_begin(ctx, title)) { win->layout->flags |= ZR_WINDOW_ROM; win->layout->flags &= ~(zr_flags)ZR_WINDOW_REMOVE_ROM; + win->popup.active = 1; layout->offset = &popup->scrollbar; return 1; } else { win->layout->flags |= ZR_WINDOW_REMOVE_ROM; win->layout->popup_buffer.active = 0; + win->popup.active = 0; ctx->memory.allocated = allocated; ctx->current = win; return 0; @@ -9659,9 +9676,10 @@ zr_popup_end(struct zr_context *ctx) popup = ctx->current; ZR_ASSERT(popup->parent); win = popup->parent; - if (popup->flags & ZR_WINDOW_HIDDEN) + if (popup->flags & ZR_WINDOW_HIDDEN) { win->layout->flags |= ZR_WINDOW_REMOVE_ROM; - + win->popup.active = 0; + } zr_draw_scissor(&popup->buffer, zr_null_rect); zr_end(ctx); @@ -9757,11 +9775,10 @@ zr_tooltip(struct zr_context *ctx, const char *text) */ int zr_contextual_begin(struct zr_context *ctx, struct zr_layout *layout, - zr_flags flags, struct zr_vec2 size, struct zr_rect trigger_bounds) + zr_flags flags, struct zr_vec2 size, int is_clicked) { int ret; int is_active = 0; - int is_clicked = 0; int is_open = 0; struct zr_window *win; @@ -9776,7 +9793,6 @@ zr_contextual_begin(struct zr_context *ctx, struct zr_layout *layout, win = ctx->current; popup = win->popup.win; - is_clicked = zr_input_is_mouse_click_in_rect(&ctx->input, ZR_BUTTON_RIGHT, trigger_bounds); is_open = (popup && (popup->flags & ZR_WINDOW_CONTEXTUAL) && win->popup.type == ZR_WINDOW_CONTEXTUAL); if ((is_clicked && is_open && !is_active) || (!is_open && !is_active && !is_clicked)) return 0; diff --git a/zahnrad.h b/zahnrad.h index 0604439..95c6346 100644 --- a/zahnrad.h +++ b/zahnrad.h @@ -1474,7 +1474,7 @@ void zr_combo_end(struct zr_context*); /* contextual menu */ int zr_contextual_begin(struct zr_context*, struct zr_layout*, zr_flags flags, - struct zr_vec2 size, struct zr_rect trigger_bounds); + struct zr_vec2 size, int is_clicked); int zr_contextual_item(struct zr_context*, const char*, enum zr_text_align align); int zr_contextual_item_icon(struct zr_context*, struct zr_image, const char*, enum zr_text_align); int zr_contextual_item_symbol(struct zr_context*, enum zr_symbol, const char*, enum zr_text_align);