diff --git a/demo/demo.c b/demo/demo.c index c481bf6..38172b5 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -54,13 +54,10 @@ show_test_window(struct zr_window *window, struct zr_style *config, enum theme * static int moveable = zr_true; static int no_scrollbar = zr_false; static zr_flags window_flags = 0; - - /* header flags */ static int minimizable = zr_true; static int close = zr_true; static int scale = zr_false; static int move = zr_false; - static zr_flags header_flags = 0; /* collapsable headers */ static int window_option_state = ZR_MINIMIZED; @@ -72,7 +69,7 @@ show_test_window(struct zr_window *window, struct zr_style *config, enum theme * static int splitter_state = ZR_MINIMIZED; /* popups */ - static enum zr_header_align header_align = ZR_HEADER_RIGHT; + static enum zr_style_header_align header_align = ZR_HEADER_RIGHT; static int show_app_about = zr_false; static int show_contextual = zr_false; static struct zr_rect contextual_bounds; @@ -82,6 +79,7 @@ show_test_window(struct zr_window *window, struct zr_style *config, enum theme * static struct zr_color color_picker_color; /* window flags */ + config->header.align = header_align; window->style = config; window_flags = 0; if (border) window_flags |= ZR_WINDOW_BORDER; @@ -91,23 +89,14 @@ show_test_window(struct zr_window *window, struct zr_style *config, enum theme * if (window->flags & ZR_WINDOW_ACTIVE) window_flags |= ZR_WINDOW_ACTIVE; if (window->flags & ZR_WINDOW_ROM) window_flags |= ZR_WINDOW_ROM; if (window->flags & ZR_WINDOW_MINIMIZED) window_flags |= ZR_WINDOW_MINIMIZED; - - /* header flags */ - header_flags = 0; - if (minimizable) header_flags |= ZR_MINIMIZABLE; - if (close) header_flags |= ZR_CLOSEABLE; - if (scale) header_flags |= ZR_SCALEABLE; - if (move) header_flags |= ZR_MOVEABLE; + if (minimizable) window_flags |= ZR_WINDOW_MINIMIZABLE; + if (close) window_flags |= ZR_WINDOW_CLOSEABLE; /* main window */ window->flags = window_flags; - zr_begin(&layout, window); - ret = zr_header(&layout, (titlebar)? "Zahnrad":"", header_flags, header_flags, header_align); - if (ret & ZR_CLOSEABLE) { - layout.flags &= (zr_flags)~ZR_WINDOW_HIDDEN; - layout.valid = zr_true; + ret = zr_begin(&layout, window, (titlebar)? "Zahnrad":""); + if (ret & ZR_WINDOW_CLOSEABLE) return 0; - } if (show_menu) { @@ -160,11 +149,13 @@ show_test_window(struct zr_window *window, struct zr_style *config, enum theme * struct zr_context popup; static struct zr_vec2 about_scrollbar; static struct zr_rect s = {20, 100, 300, 190}; - zr_popup_begin(&layout, &popup, ZR_POPUP_STATIC, 0, s, about_scrollbar); - if (zr_header(&popup, "About", ZR_CLOSEABLE, ZR_CLOSEABLE, ZR_HEADER_LEFT)){ + zr_flags r = zr_popup_begin(&layout, &popup, ZR_POPUP_STATIC, "About", + ZR_WINDOW_CLOSEABLE, s, about_scrollbar); + if (r & ZR_WINDOW_CLOSEABLE){ show_app_about = zr_false; zr_popup_close(&popup); } + zr_layout_row_dynamic(&popup, 20, 1); zr_label(&popup, "Zahnrad", ZR_TEXT_LEFT); zr_label(&popup, "By Micha Mettke", ZR_TEXT_LEFT); @@ -179,8 +170,9 @@ show_test_window(struct zr_window *window, struct zr_style *config, enum theme * struct zr_context popup; static struct zr_vec2 close_scrollbar = {0,0}; static const struct zr_rect s = {20, 150, 230, 150}; - zr_popup_begin(&layout, &popup, ZR_POPUP_STATIC, 0, s, close_scrollbar); - if (zr_header(&popup, "Quit", ZR_CLOSEABLE, ZR_CLOSEABLE, ZR_HEADER_LEFT)) { + zr_flags r = zr_popup_begin(&layout, &popup, ZR_POPUP_STATIC, "Quit", + ZR_WINDOW_CLOSEABLE, s, close_scrollbar); + if (r & ZR_WINDOW_CLOSEABLE) { show_close_popup = zr_false; zr_popup_close(&popup); } @@ -206,8 +198,9 @@ show_test_window(struct zr_window *window, struct zr_style *config, enum theme * static int active[4]; struct zr_context popup; int r,g,b,a; - zr_popup_begin(&layout, &popup, ZR_POPUP_STATIC,0, zr_rect(10, 100, 350, 280), zr_vec2(0,0)); - if (zr_header(&popup, "Color", ZR_CLOSEABLE, ZR_CLOSEABLE, ZR_HEADER_LEFT)) + zr_flags res = zr_popup_begin(&layout, &popup, ZR_POPUP_STATIC, "Color Picker", + ZR_WINDOW_CLOSEABLE, zr_rect(10, 100, 350, 280), zr_vec2(0,0)); + if (res & ZR_WINDOW_CLOSEABLE) { zr_popup_close(&popup); show_color_picker_popup = zr_false; @@ -1004,13 +997,16 @@ init_demo(struct demo *gui) /* windows */ zr_window_init(&gui->panel, zr_rect(30, 30, 400, 600), - ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_SCALEABLE, + ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_SCALEABLE| + ZR_WINDOW_CLOSEABLE|ZR_WINDOW_MINIMIZABLE, &gui->queue, &gui->config_black, &gui->input); zr_window_init(&gui->sub, zr_rect(400, 50, 220, 180), - ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_SCALEABLE, + ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_SCALEABLE| + ZR_WINDOW_CLOSEABLE|ZR_WINDOW_MINIMIZABLE, &gui->queue, &gui->config_black, &gui->input); zr_window_init(&gui->metrics, zr_rect(200, 400, 250, 300), - ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_SCALEABLE, + ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_SCALEABLE| + ZR_WINDOW_CLOSEABLE|ZR_WINDOW_MINIMIZABLE, &gui->queue, &gui->config_black, &gui->input); { @@ -1027,18 +1023,18 @@ init_demo(struct demo *gui) static void run_demo(struct demo *gui) { + int res; struct zr_context layout; struct zr_style *current = (gui->theme == THEME_BLACK) ? &gui->config_black : &gui->config_white; gui->running = show_test_window(&gui->panel, current, &gui->theme, &gui->text); /* ussage example */ gui->sub.style = current; - zr_begin(&layout, &gui->sub); + zr_begin(&layout, &gui->sub, "Show"); { enum {EASY, HARD}; static int op = EASY; static float value = 0.5f; - zr_header(&layout, "Show", ZR_CLOSEABLE, 0, ZR_HEADER_LEFT); zr_layout_row_static(&layout, 30, 80, 1); if (zr_button_text(&layout, "button", ZR_BUTTON_DEFAULT)) { /* event handling */ @@ -1059,7 +1055,7 @@ run_demo(struct demo *gui) /* metrics window */ gui->metrics.style = current; - zr_begin(&layout, &gui->metrics); + zr_begin(&layout, &gui->metrics, "Metrics"); { static int prim_state = ZR_MINIMIZED; static int mem_state = ZR_MINIMIZED; @@ -1067,7 +1063,6 @@ run_demo(struct demo *gui) struct zr_command_stats *stats = &gui->panel.buffer.stats; zr_buffer_info(&status, &gui->queue.buffer); - zr_header(&layout, "Metrics", ZR_CLOSEABLE, 0, ZR_HEADER_LEFT); if (zr_layout_push(&layout, ZR_LAYOUT_NODE, "Memory", &mem_state)) { zr_layout_row_dynamic(&layout, 20, 2); diff --git a/example/filex/filex.c b/example/filex/filex.c index 606e0d9..0f53afe 100644 --- a/example/filex/filex.c +++ b/example/filex/filex.c @@ -470,7 +470,7 @@ file_browser_run(struct file_browser *browser, int width, int height) browser->window.bounds.w = width; browser->window.bounds.h = height; - zr_begin(&context, &browser->window); + zr_begin(&context, &browser->window, NULL); { struct zr_context sub; float row_layout[3]; diff --git a/example/nodedit/nodedit.c b/example/nodedit/nodedit.c index 77675bf..ab3e58e 100644 --- a/example/nodedit/nodedit.c +++ b/example/nodedit/nodedit.c @@ -666,9 +666,10 @@ main(int argc, char *argv[]) nvgTextMetrics(vg, NULL, NULL, &gui.font.height); gui.font.width = font_get_width; zr_style_default(&gui.config, ZR_DEFAULT_ALL, &gui.font); + gui.config.header.align = ZR_HEADER_RIGHT; zr_window_init(&gui.window, zr_rect(0, 0, width, height), - ZR_WINDOW_BORDER|ZR_WINDOW_NO_SCROLLBAR, + ZR_WINDOW_BORDER|ZR_WINDOW_NO_SCROLLBAR|ZR_WINDOW_CLOSEABLE, &gui.queue, &gui.config, &gui.input); node_editor_init(&nodedit); @@ -694,14 +695,15 @@ main(int argc, char *argv[]) int incursor; struct zr_context layout; struct zr_rect bounds = gui.window.bounds; + zr_flags ret; - zr_begin(&layout, &gui.window); - if (zr_header(&layout, "Node Editor", ZR_CLOSEABLE, ZR_CLOSEABLE, ZR_HEADER_RIGHT)) + ret = zr_begin(&layout, &gui.window, "Node Editor"); + if (ret & ZR_WINDOW_CLOSEABLE) goto cleanup; /* borderless os window dragging */ incursor = zr_input_is_mouse_hovering_rect(&gui.input, - zr_rect(layout.bounds.x, layout.bounds.y, layout.bounds.w, layout.header.h)); + zr_rect(layout.bounds.x, layout.bounds.y, layout.bounds.w, layout.header_h)); if (zr_input_is_mouse_down(&gui.input, ZR_BUTTON_LEFT) && incursor) { x += gui.input.mouse.delta.x; y += gui.input.mouse.delta.y; diff --git a/zahnrad.c b/zahnrad.c index 447160c..a9510ed 100644 --- a/zahnrad.c +++ b/zahnrad.c @@ -5529,6 +5529,11 @@ zr_style_default(struct zr_style *style, zr_flags flags, zr_style_default_properties(style); if (flags & ZR_DEFAULT_ROUNDING) zr_style_default_rounding(style); + + style->header.align = ZR_HEADER_RIGHT; + style->header.close_symbol = 'x'; + style->header.minimize_symbol = '-'; + style->header.maximize_symbol = '+'; } void @@ -5703,14 +5708,118 @@ int zr_window_is_minimized(struct zr_window *panel) {return panel->flags & ZR_WINDOW_MINIMIZED;} +/*------------------------------------------------------------- + * + * HEADER + * + * --------------------------------------------------------------*/ +struct zr_window_header { + float x, y, w, h; + float front, back; +}; + +static int +zr_header_button(struct zr_context *layout, struct zr_window_header *header, + zr_rune symbol, enum zr_style_header_align align) +{ + /* calculate the position of the close icon position and draw it */ + zr_glyph glyph; + struct zr_rect sym = {0,0,0,0}; + float sym_bw = 0; + int ret = zr_false; + + const struct zr_style *c; + struct zr_command_buffer *out; + struct zr_vec2 item_padding; + + ZR_ASSERT(layout); + ZR_ASSERT(layout->buffer); + ZR_ASSERT(layout->style); + if (!layout || layout->flags & ZR_WINDOW_HIDDEN) + return zr_false; + + /* cache configuration data */ + c = layout->style; + out = layout->buffer; + item_padding = zr_style_property(c, ZR_PROPERTY_ITEM_PADDING); + + sym.x = header->front; + sym.y = header->y; + { + /* single unicode rune text icon */ + const char *X = glyph; + const zr_size len = zr_utf_encode(symbol, glyph, sizeof(glyph)); + const zr_size t = c->font.width(c->font.userdata, c->font.height, X, len); + const float text_width = (float)t; + + /* calculate bounds of the icon */ + sym_bw = text_width; + sym.w = (float)text_width + 2 * item_padding.x; + sym.h = c->font.height + 2 * item_padding.y; + if (align == ZR_HEADER_RIGHT) + sym.x = header->back - sym.w; + zr_command_buffer_push_text(out, sym, X, len, &c->font, + c->colors[ZR_COLOR_HEADER],c->colors[ZR_COLOR_TEXT]); + } + + /* check if the icon has been pressed */ + if (!(layout->flags & ZR_WINDOW_ROM)) { + float mouse_x = layout->input->mouse.pos.x; + float mouse_y = layout->input->mouse.pos.y; + float clicked_x = layout->input->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.x; + float clicked_y = layout->input->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.y; + if (ZR_INBOX(mouse_x, mouse_y, sym.x, sym.y, sym_bw, sym.h)) { + if (ZR_INBOX(clicked_x, clicked_y, sym.x, sym.y, sym_bw, sym.h)) + ret = (layout->input->mouse.buttons[ZR_BUTTON_LEFT].down && + layout->input->mouse.buttons[ZR_BUTTON_LEFT].clicked); + } + } + + /* update the header space */ + if (align == ZR_HEADER_RIGHT) + header->back -= (sym.w + item_padding.x); + else header->front += sym.w + item_padding.x; + return ret; +} + +static int +zr_header_toggle(struct zr_context *layout,struct zr_window_header *header, + zr_rune active, zr_rune inactive, enum zr_style_header_align align, int state) +{ + int ret = zr_header_button(layout, header,(state) ? active : inactive, align); + if (ret) return !state; + return state; +} + +static int +zr_header_flag(struct zr_context *layout, struct zr_window_header *header, + zr_rune inactive, zr_rune active, enum zr_style_header_align align, + enum zr_window_flags flag) +{ + zr_flags flags = layout->flags; + int state = (flags & flag) ? zr_true : zr_false; + int ret = zr_header_toggle(layout, header, inactive, active, align, state); + if (ret != ((flags & flag) ? zr_true : zr_false)) { + /* the state of the toggle icon has been changed */ + if (!ret) layout->flags &= ~flag; + else layout->flags |= flag; + /* update the state of the panel since the flag have changed */ + layout->valid = !(layout->flags & ZR_WINDOW_HIDDEN) && + !(layout->flags & ZR_WINDOW_MINIMIZED); + return zr_true; + } + return zr_false; +} + /*------------------------------------------------------------- * * CONTEXT * * --------------------------------------------------------------*/ zr_flags -zr_begin(struct zr_context *context, struct zr_window *window) +zr_begin(struct zr_context *context, struct zr_window *window, const char *title) { + int header_active = 0; zr_flags ret = 0; const struct zr_style *c; float scrollbar_size; @@ -5780,15 +5889,15 @@ zr_begin(struct zr_context *context, struct zr_window *window) } /* move panel position if requested */ - context->header.h = c->font.height + 4 * item_padding.y; - context->header.h += window_padding.y; + context->header_h = c->font.height + 4 * item_padding.y; + context->header_h += window_padding.y; if ((window->flags & ZR_WINDOW_MOVEABLE) && !(window->flags & ZR_WINDOW_ROM)) { int incursor; struct zr_rect move; move.x = window->bounds.x; move.y = window->bounds.y; move.w = window->bounds.w; - move.h = context->header.h; + move.h = context->header_h; incursor = zr_input_is_mouse_prev_hovering_rect(in, move); if (zr_input_is_mouse_down(in, ZR_BUTTON_LEFT) && incursor) { window->bounds.x = window->bounds.x + in->mouse.delta.x; @@ -5817,14 +5926,14 @@ zr_begin(struct zr_context *context, struct zr_window *window) /* window header */ if (window->flags & ZR_WINDOW_MINIMIZED) { - context->header.h = 0; + context->header_h = 0; context->row.height = 0; } else { - context->header.h = 2 * item_spacing.y; - context->row.height = context->header.h; + context->header_h = 2 * item_spacing.y; + context->row.height = context->header_h; } - /* panel activation by clicks inside of the panel */ + /* window activation by click inside */ if (!(window->flags & ZR_WINDOW_TAB) && !(window->flags & ZR_WINDOW_ROM)) { float clicked_x = in->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.x; float clicked_y = in->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.y; @@ -5848,7 +5957,7 @@ zr_begin(struct zr_context *context, struct zr_window *window) /* calculate the window size */ if (!(window->flags & ZR_WINDOW_NO_SCROLLBAR)) context->width = window->bounds.w - scrollbar_size; - context->height = window->bounds.h - (context->header.h + 2 * item_spacing.y); + context->height = window->bounds.h - (context->header_h + 2 * item_spacing.y); context->height -= context->footer_h; /* draw window background if not a dynamic window */ @@ -5859,7 +5968,87 @@ zr_begin(struct zr_context *context, struct zr_window *window) context->bounds.w, context->row.height + window_padding.y), 0, c->colors[ZR_COLOR_WINDOW]); } - /* draw top border line */ + /* window header */ + header_active = (window->flags & (ZR_WINDOW_CLOSEABLE|ZR_WINDOW_MINIMIZABLE)); + header_active = header_active || (title != 0); + header_active = header_active && !(window->flags & ZR_WINDOW_HIDDEN); + if (header_active) { + zr_flags old; + struct zr_rect old_clip = out->clip; + struct zr_window_header header, sym; + + /* This is a little bit of a performace hack. To make sure the header does + * not get overdrawn with text you do not have to push a scissor rect. This + * is possible because the command buffer automatically clips text by using + * its clipping rectangle. But since the clipping rect gets reused to calculate + * the window clipping rect the old clipping rect has to be stored and reset afterwards. */ + out->clip.x = header.x = context->bounds.x + window_padding.x; + out->clip.y = header.y = context->bounds.y + item_padding.y; + out->clip.w = header.w = MAX(context->bounds.w, 2 * window_padding.x); + out->clip.h = header.w -= 2 * window_padding.x; + + /* update the header height and first row height */ + context->header_h = c->font.height + 2 * item_padding.y; + context->header_h += window_padding.y; + context->row.height += context->header_h; + + header.h = context->header_h; + header.back = header.x + header.w; + header.front = header.x; + + context->height = context->bounds.h - (header.h + 2 * item_spacing.y); + context->height -= context->footer_h; + + /* draw header background */ + if (!(context->flags & ZR_WINDOW_BORDER)) { + zr_command_buffer_push_rect(out, zr_rect(context->bounds.x, context->bounds.y, + context->bounds.w, context->header_h), 0, c->colors[ZR_COLOR_HEADER]); + } else { + zr_command_buffer_push_rect(out, zr_rect(context->bounds.x, context->bounds.y+1, + context->bounds.w, context->header_h), 0, c->colors[ZR_COLOR_HEADER]); + } + + /* window header icons */ + old = window->flags; + if (window->flags & ZR_WINDOW_CLOSEABLE) + zr_header_flag(context, &header, c->header.close_symbol, c->header.close_symbol, + c->header.align, ZR_WINDOW_HIDDEN); + if (window->flags & ZR_WINDOW_MINIMIZABLE) + zr_header_flag(context, &header, c->header.maximize_symbol, c->header.minimize_symbol, + c->header.align, ZR_WINDOW_MINIMIZED); + + /* window state change notifcations */ + if ((old & ZR_WINDOW_HIDDEN) ^ (context->flags & ZR_WINDOW_HIDDEN)) + ret |= ZR_WINDOW_CLOSEABLE; + if ((old & ZR_WINDOW_MINIMIZED) ^ (context->flags & ZR_WINDOW_MINIMIZED)) + ret |= ZR_WINDOW_MINIMIZABLE; + + /* window header title */ + if (title) { + zr_size text_len = zr_strsiz(title); + struct zr_rect label = {0,0,0,0}; + + /* calculate and allocate space from the header */ + zr_size t = c->font.width(c->font.userdata, c->font.height, title, text_len); + if (c->header.align == ZR_HEADER_LEFT) { + header.back = header.back - (3 * item_padding.x + (float)t); + label.x = header.back; + } else { + label.x = header.front; + header.front += 3 * item_padding.x + (float)t; + } + + /* calculate label bounds and draw text */ + label.y = header.y; + label.h = c->font.height + 2 * item_padding.y; + label.w = MAX((float)t + 2 * item_padding.x, 4 * item_padding.x); + zr_command_buffer_push_text(out, label, (const char*)title, text_len, + &c->font, c->colors[ZR_COLOR_HEADER], c->colors[ZR_COLOR_TEXT]); + } + out->clip = old_clip; + } + + /* draw top window border line */ if (context->flags & ZR_WINDOW_BORDER) { zr_command_buffer_push_line(out, context->bounds.x, context->bounds.y, context->bounds.x + context->bounds.w, context->bounds.y, @@ -5877,9 +6066,15 @@ zr_begin(struct zr_context *context, struct zr_window *window) context->clip.w = context->width; } - context->clip.y = window->bounds.y + context->header.h; - context->clip.h = window->bounds.h - (context->footer_h + context->header.h); + context->clip.h = window->bounds.h - (context->footer_h + context->header_h); context->clip.h -= (window_padding.y + item_padding.y); + context->clip.y = window->bounds.y; + if (!(window->flags & ZR_WINDOW_COMBO_MENU) && header_active) + context->clip.y += context->header_h; + if (window->flags & ZR_WINDOW_BORDER) { + context->clip.y += 1; + context->clip.h -= 1; + } zr_unify(&clip, &context->buffer->clip, context->clip.x, context->clip.y, context->clip.x + context->clip.w, context->clip.y + context->clip.h); zr_command_buffer_push_scissor(out, clip); @@ -5971,14 +6166,14 @@ zr_end(struct zr_context *layout, struct zr_window *window) bounds.x = layout->bounds.x + layout->width; bounds.y = (layout->flags & ZR_WINDOW_BORDER) ? layout->bounds.y + 1 : layout->bounds.y; - bounds.y += layout->header.h + layout->menu.h; + bounds.y += layout->header_h + layout->menu.h; bounds.w = scrollbar_size; bounds.h = layout->height; if (layout->flags & ZR_WINDOW_BORDER) bounds.h -= 1; scroll_offset = layout->offset.y; scroll_step = layout->clip.h * 0.10f; - scroll_target = (layout->at_y - layout->bounds.y)-(layout->header.h+2*item_spacing.y); + scroll_target = (layout->at_y - layout->bounds.y)-(layout->header_h+2*item_spacing.y); scroll.has_scrolling = (layout->flags & ZR_WINDOW_ACTIVE); window->offset.y = zr_widget_scrollbarv(out, bounds, scroll_offset, scroll_target, scroll_step, &scroll, in); @@ -5990,7 +6185,7 @@ zr_end(struct zr_context *layout, struct zr_window *window) bounds.h = scrollbar_size; bounds.y = (layout->flags & ZR_WINDOW_BORDER) ? layout->bounds.y + 1 : layout->bounds.y; - bounds.y += layout->header.h + layout->menu.h + layout->height; + bounds.y += layout->header_h + layout->menu.h + layout->height; bounds.w = layout->clip.w; } else if (layout->flags & ZR_WINDOW_DYNAMIC) { bounds.h = MIN(scrollbar_size, layout->footer_h); @@ -6047,14 +6242,14 @@ zr_end(struct zr_context *layout, struct zr_window *window) const float width = (layout->flags & ZR_WINDOW_NO_SCROLLBAR) ? layout->width: layout->width + scrollbar_size; const float padding_y = (!layout->valid) ? - window->bounds.y + layout->header.h: + window->bounds.y + layout->header_h: (layout->flags & ZR_WINDOW_DYNAMIC)? layout->footer_h + footer.y: layout->bounds.y + layout->bounds.h; if (window->flags & ZR_WINDOW_BORDER_HEADER) - zr_command_buffer_push_line(out, window->bounds.x, window->bounds.y + layout->header.h, - window->bounds.x + window->bounds.w, window->bounds.y + layout->header.h, + zr_command_buffer_push_line(out, window->bounds.x, window->bounds.y + layout->header_h, + window->bounds.x + window->bounds.w, window->bounds.y + layout->header_h, config->colors[ZR_COLOR_BORDER]); zr_command_buffer_push_line(out, window->bounds.x, padding_y, window->bounds.x + width, padding_y, config->colors[ZR_COLOR_BORDER]); @@ -6097,351 +6292,6 @@ struct zr_rect zr_space(struct zr_context *layout) {ZR_ASSERT(layout); return layout->clip;} -/* ------------------------------------------------------------- - * - * HEADER - * - * --------------------------------------------------------------*/ -void -zr_header_begin(struct zr_context *layout) -{ - const struct zr_style *c; - struct zr_vec2 item_padding; - struct zr_vec2 item_spacing; - struct zr_vec2 panel_padding; - struct zr_command_buffer *out; - struct zr_rect clip; - float old; - - ZR_ASSERT(layout); - if (!layout) return; - if (layout->flags & ZR_WINDOW_HIDDEN) - return; - - c = layout->style; - out = layout->buffer; - - /* cache some configuration data */ - panel_padding = zr_style_property(c, ZR_PROPERTY_PADDING); - item_padding = zr_style_property(c, ZR_PROPERTY_ITEM_PADDING); - item_spacing = zr_style_property(c, ZR_PROPERTY_ITEM_SPACING); - - old = layout->header.h; - if (layout->valid) - zr_command_buffer_push_scissor(out, - zr_rect(out->clip.x, out->clip.y - old, out->clip.w, out->clip.h)); - - /* update the header height and first row height */ - layout->header.h = c->font.height + 2 * item_padding.y; - layout->header.h += panel_padding.y; - layout->row.height += layout->header.h; - if (layout->valid) - zr_command_buffer_push_rect(out, - zr_rect(layout->bounds.x, layout->bounds.y + layout->header.h, - layout->bounds.w, layout->row.height), 0, c->colors[ZR_COLOR_WINDOW]); - - /* setup header bounds and growable icon space */ - layout->header.x = layout->bounds.x + panel_padding.x; - layout->header.y = layout->bounds.y + item_padding.y; - layout->header.w = MAX(layout->bounds.w, 2 * panel_padding.x); - layout->header.w -= 2 * panel_padding.x; - layout->header.front = layout->header.x; - layout->header.back = layout->header.x + layout->header.w; - layout->height = layout->bounds.h - (layout->header.h + 2 * item_spacing.y); - layout->height -= layout->footer_h; - - zr_unify(&clip, &layout->buffer->clip, layout->bounds.x, layout->bounds.y, - layout->bounds.x + layout->bounds.w, layout->bounds.y + layout->bounds.h); - zr_command_buffer_push_scissor(out, clip); - if (!(layout->flags & ZR_WINDOW_BORDER)) { - zr_command_buffer_push_rect(out, zr_rect(layout->bounds.x, layout->bounds.y, - layout->bounds.w, layout->header.h), 0, c->colors[ZR_COLOR_HEADER]); - } else { - zr_command_buffer_push_rect(out, zr_rect(layout->bounds.x, layout->bounds.y+1, - layout->bounds.w, layout->header.h), 0, c->colors[ZR_COLOR_HEADER]); - } -} - -int -zr_header_button(struct zr_context *layout, - enum zr_symbol symbol, enum zr_header_align align) -{ - /* calculate the position of the close icon position and draw it */ - struct zr_rect sym = {0,0,0,0}; - float sym_bw = 0; - int ret = zr_false; - - const struct zr_style *c; - struct zr_command_buffer *out; - struct zr_vec2 item_padding; - - ZR_ASSERT(layout); - ZR_ASSERT(layout->buffer); - ZR_ASSERT(layout->style); - if (!layout || layout->flags & ZR_WINDOW_HIDDEN) - return zr_false; - - /* cache configuration data */ - c = layout->style; - out = layout->buffer; - item_padding = zr_style_property(c, ZR_PROPERTY_ITEM_PADDING); - - sym.x = layout->header.front; - sym.y = layout->header.y; - - switch (symbol) { - case ZR_SYMBOL_MINUS: - case ZR_SYMBOL_PLUS: - case ZR_SYMBOL_UNDERSCORE: - case ZR_SYMBOL_X: { - /* single character text icon */ - const char *X = (symbol == ZR_SYMBOL_X) ? "x": - (symbol == ZR_SYMBOL_UNDERSCORE) ? "_": - (symbol == ZR_SYMBOL_PLUS) ? "+": "-"; - const zr_size t = c->font.width(c->font.userdata, c->font.height, X, 1); - const float text_width = (float)t; - - /* calculate bounds of the icon */ - sym_bw = text_width; - sym.w = (float)text_width + 2 * item_padding.x; - sym.h = c->font.height + 2 * item_padding.y; - if (align == ZR_HEADER_RIGHT) - sym.x = layout->header.back - sym.w; - zr_command_buffer_push_text(out, sym, X, 1, &c->font, c->colors[ZR_COLOR_HEADER], - c->colors[ZR_COLOR_TEXT]); - } break; - case ZR_SYMBOL_CIRCLE_FILLED: - case ZR_SYMBOL_CIRCLE: - case ZR_SYMBOL_RECT_FILLED: - case ZR_SYMBOL_RECT: { - /* simple empty/filled shapes */ - sym_bw = sym.w = c->font.height; - sym.h = c->font.height; - sym.y = sym.y + c->font.height/2; - if (align == ZR_HEADER_RIGHT) - sym.x = layout->header.back - (c->font.height + 2 * item_padding.x); - - if (symbol == ZR_SYMBOL_RECT || symbol == ZR_SYMBOL_RECT_FILLED) { - /* rectangle shape */ - zr_command_buffer_push_rect(out, sym, 0, c->colors[ZR_COLOR_TEXT]); - if (symbol == ZR_SYMBOL_RECT_FILLED) - zr_command_buffer_push_rect(out, zr_shrink_rect(sym, 1), - 0, c->colors[ZR_COLOR_HEADER]); - } else { - /* circle shape */ - zr_command_buffer_push_circle(out, sym, c->colors[ZR_COLOR_TEXT]); - if (symbol == ZR_SYMBOL_CIRCLE_FILLED) - zr_command_buffer_push_circle(out, zr_shrink_rect(sym, 1), - c->colors[ZR_COLOR_HEADER]); - } - - /* calculate the space the icon occupied */ - sym.w = c->font.height + 2 * item_padding.x; - } break; - case ZR_SYMBOL_TRIANGLE_UP: - case ZR_SYMBOL_TRIANGLE_DOWN: - case ZR_SYMBOL_TRIANGLE_LEFT: - case ZR_SYMBOL_TRIANGLE_RIGHT: { - /* triangle icon with direction */ - enum zr_heading heading; - struct zr_vec2 points[3]; - heading = (symbol == ZR_SYMBOL_TRIANGLE_RIGHT) ? ZR_RIGHT : - (symbol == ZR_SYMBOL_TRIANGLE_LEFT) ? ZR_LEFT: - (symbol == ZR_SYMBOL_TRIANGLE_UP) ? ZR_UP: ZR_DOWN; - - /* calculate bounds of the icon */ - sym_bw = sym.w = c->font.height; - sym.h = c->font.height; - sym.y = sym.y + c->font.height/2; - if (align == ZR_HEADER_RIGHT) - sym.x = layout->header.back - (c->font.height + 2 * item_padding.x); - - /* calculate the triangle point positions and draw triangle */ - zr_triangle_from_direction(points, sym, 0, 0, heading); - zr_command_buffer_push_triangle(layout->buffer, points[0].x, points[0].y, - points[1].x, points[1].y, points[2].x, points[2].y, c->colors[ZR_COLOR_TEXT]); - - /* calculate the space the icon occupies */ - sym.w = c->font.height + 2 * item_padding.x; - } break; - case ZR_SYMBOL_MAX: - default: return ret; - } - - /* check if the icon has been pressed */ - if (!(layout->flags & ZR_WINDOW_ROM)) { - float mouse_x = layout->input->mouse.pos.x; - float mouse_y = layout->input->mouse.pos.y; - float clicked_x = layout->input->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.x; - float clicked_y = layout->input->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.y; - if (ZR_INBOX(mouse_x, mouse_y, sym.x, sym.y, sym_bw, sym.h)) { - if (ZR_INBOX(clicked_x, clicked_y, sym.x, sym.y, sym_bw, sym.h)) - ret = (layout->input->mouse.buttons[ZR_BUTTON_LEFT].down && - layout->input->mouse.buttons[ZR_BUTTON_LEFT].clicked); - } - } - - /* update the header space */ - if (align == ZR_HEADER_RIGHT) - layout->header.back -= (sym.w + item_padding.x); - else layout->header.front += sym.w + item_padding.x; - return ret; -} - -int -zr_header_toggle(struct zr_context *layout, - enum zr_symbol inactive, enum zr_symbol active, - enum zr_header_align align, int state) -{ - int ret = zr_header_button(layout, (state) ? active : inactive, align); - if (ret) return !state; - return state; -} - -int -zr_header_flag(struct zr_context *layout, enum zr_symbol inactive, - enum zr_symbol active, enum zr_header_align align, - enum zr_window_flags flag) -{ - zr_flags flags = layout->flags; - int state = (flags & flag) ? zr_true : zr_false; - int ret = zr_header_toggle(layout, inactive, active, align, state); - if (ret != ((flags & flag) ? zr_true : zr_false)) { - /* the state of the toggle icon has been changed */ - if (!ret) layout->flags &= ~flag; - else layout->flags |= flag; - /* update the state of the panel since the flag have changed */ - layout->valid = !(layout->flags & ZR_WINDOW_HIDDEN) && - !(layout->flags & ZR_WINDOW_MINIMIZED); - return zr_true; - } - return zr_false; -} - -void -zr_header_title(struct zr_context *layout, const char *title, - enum zr_header_align align) -{ - struct zr_rect label = {0,0,0,0}; - const struct zr_style *c; - struct zr_command_buffer *out; - struct zr_vec2 item_padding; - zr_size text_len; - zr_size t; - - /* make sure correct values and layout state */ - ZR_ASSERT(layout); - if (!layout || !title) return; - if (layout->flags & ZR_WINDOW_HIDDEN) - return; - - /* cache configuration and title length */ - c = layout->style; - out = layout->buffer; - item_padding = zr_style_property(c, ZR_PROPERTY_ITEM_PADDING); - text_len = zr_strsiz(title); - - /* calculate and allocate space from the header */ - t = c->font.width(c->font.userdata, c->font.height, title, text_len); - if (align == ZR_HEADER_RIGHT) { - layout->header.back = layout->header.back - (3 * item_padding.x + (float)t); - label.x = layout->header.back; - } else { - label.x = layout->header.front; - layout->header.front += 3 * item_padding.x + (float)t; - } - - /* calculate label bounds and draw text */ - label.y = layout->header.y; - label.h = c->font.height + 2 * item_padding.y; - if (align == ZR_HEADER_LEFT) - label.w = MAX((float)t + 2 * item_padding.x, 4 * item_padding.x); - else label.w = MAX((float)t + 2 * item_padding.x, 4 * item_padding.x); - zr_command_buffer_push_text(out, label, (const char*)title, text_len, - &c->font, c->colors[ZR_COLOR_HEADER], c->colors[ZR_COLOR_TEXT]); -} - -void -zr_header_end(struct zr_context *layout) -{ - const struct zr_style *c; - struct zr_command_buffer *out; - struct zr_vec2 item_padding; - struct zr_vec2 panel_padding; - - ZR_ASSERT(layout); - if (!layout) return; - if (layout->flags & ZR_WINDOW_HIDDEN) - return; - - /* cache configuration data */ - c = layout->style; - out = layout->buffer; - panel_padding = zr_style_property(c, ZR_PROPERTY_PADDING); - item_padding = zr_style_property(c, ZR_PROPERTY_ITEM_PADDING); - - /* draw panel header border */ - if (layout->flags & ZR_WINDOW_BORDER) { - /* draw the header border lines */ - zr_command_buffer_push_line(out, layout->bounds.x, layout->bounds.y, layout->bounds.x, - layout->bounds.y + layout->header.h, c->colors[ZR_COLOR_BORDER]); - zr_command_buffer_push_line(out, layout->bounds.x + layout->bounds.w, layout->bounds.y, - layout->bounds.x + layout->bounds.w, layout->bounds.y + layout->header.h, - c->colors[ZR_COLOR_BORDER]); - if (layout->flags & ZR_WINDOW_BORDER_HEADER) - zr_command_buffer_push_line(out, layout->bounds.x, layout->bounds.y + layout->header.h, - layout->bounds.x + layout->bounds.w, layout->bounds.y + layout->header.h, - c->colors[ZR_COLOR_BORDER]); - } - - /* update the panel clipping rect to exclude the header */ - layout->clip.y = layout->bounds.y + layout->header.h + 1; - layout->clip.h = layout->bounds.h - (layout->footer_h + layout->header.h); - layout->clip.h -= (panel_padding.y + item_padding.y); - zr_command_buffer_push_scissor(out, layout->clip); -} - -zr_flags -zr_header(struct zr_context *layout, const char *title, - zr_flags flags, zr_flags notify, enum zr_header_align align) -{ - zr_flags ret = 0; - zr_flags old = layout->flags; - ZR_ASSERT(layout); - if (!layout || layout->flags & ZR_WINDOW_HIDDEN) - return zr_false; - - /* basic standart header with fixed icon/title sequence */ - zr_header_begin(layout); - { - if (flags & ZR_CLOSEABLE) - zr_header_flag(layout, ZR_SYMBOL_X, ZR_SYMBOL_X, - align, ZR_WINDOW_HIDDEN); - if (flags & ZR_MINIMIZABLE) - zr_header_flag(layout, ZR_SYMBOL_MINUS, ZR_SYMBOL_PLUS, - align, ZR_WINDOW_MINIMIZED); - if (flags & ZR_SCALEABLE) - zr_header_flag(layout, ZR_SYMBOL_RECT, ZR_SYMBOL_RECT_FILLED, - align, ZR_WINDOW_SCALEABLE); - if (flags & ZR_MOVEABLE) - zr_header_flag(layout, ZR_SYMBOL_CIRCLE, - ZR_SYMBOL_CIRCLE_FILLED, align, ZR_WINDOW_MOVEABLE); - if (title) zr_header_title(layout, title, ZR_HEADER_LEFT); - } - zr_header_end(layout); - - /* notifcation if one if the icon buttons has been pressed */ - if ((notify & ZR_CLOSEABLE) && ((old & ZR_CLOSEABLE) ^ (layout->flags & ZR_CLOSEABLE))) - ret |= ZR_CLOSEABLE; - if ((notify & ZR_MINIMIZABLE) && ((old & ZR_MINIMIZABLE)^(layout->flags&ZR_MINIMIZABLE))) - ret |= ZR_MINIMIZABLE; - if ((notify & ZR_SCALEABLE) && ((old & ZR_SCALEABLE) ^ (layout->flags & ZR_SCALEABLE))) - ret |= ZR_SCALEABLE; - if ((notify & ZR_MOVEABLE) && ((old & ZR_MOVEABLE) ^ (layout->flags & ZR_MOVEABLE))) - ret |= ZR_MOVEABLE; - return ret; -} - void zr_menubar_begin(struct zr_context *layout) { @@ -6449,7 +6299,7 @@ zr_menubar_begin(struct zr_context *layout) if (!layout || layout->flags & ZR_WINDOW_HIDDEN || layout->flags & ZR_WINDOW_MINIMIZED) return; layout->menu.x = layout->at_x; - layout->menu.y = layout->bounds.y + layout->header.h; + layout->menu.y = layout->bounds.y + layout->header_h; layout->menu.w = layout->width; layout->menu.offset = layout->offset; layout->offset.y = 0; @@ -6465,7 +6315,7 @@ zr_menubar_end(struct zr_context *layout) out = layout->buffer; layout->menu.h = layout->at_y - layout->menu.y; - layout->clip.y = layout->bounds.y + layout->header.h + layout->menu.h + layout->row.height; + layout->clip.y = layout->bounds.y + layout->header_h + layout->menu.h + layout->row.height; layout->height -= layout->menu.h; layout->offset = layout->menu.offset; layout->clip.h -= layout->menu.h + layout->row.height; @@ -7039,10 +6889,8 @@ zr_spacing(struct zr_context *l, zr_size cols) if (!l) return; if (!l->valid) return; - index = (l->row.index + cols) % l->row.columns; - n = index - l->row.index; - /* spacing over row boundries */ + index = (l->row.index + cols) % l->row.columns; if (l->row.index + cols > l->row.columns) { zr_size rows = (l->row.index + cols) / l->row.columns; for (i = 0; i < rows; ++i) @@ -7052,7 +6900,7 @@ zr_spacing(struct zr_context *l, zr_size cols) /* non table layout need to allocate space */ if (l->row.type != ZR_LAYOUT_DYNAMIC_FIXED && l->row.type != ZR_LAYOUT_STATIC_FIXED) { - for (i = 0; i < n; ++i) + for (i = 0; i < index; ++i) zr_panel_alloc_space(&nil, l); } l->row.index = index; @@ -7995,29 +7843,11 @@ zr_group_begin(struct zr_context *p, struct zr_context *g, zr_window_init(&panel, bounds, flags, 0, p->style, p->input); panel.buffer = *p->buffer; - zr_begin(g, &panel); + zr_begin(g, &panel, title); *p->buffer = panel.buffer; g->buffer = p->buffer; g->offset = offset; g->queue = p->queue; - - if (title) - { - /* setup correct clipping rectangle for the header */ - struct zr_rect clip; - struct zr_command_buffer *out = p->buffer; - - zr_unify(&clip, &temp, g->bounds.x, g->clip.y, g->clip.x + g->bounds.w, - g->clip.y + g->clip.h); - zr_command_buffer_push_scissor(out, clip); - - zr_header(g, title, 0, 0, ZR_HEADER_LEFT); - zr_unify(&clip, &p->clip, g->clip.x, g->clip.y, g->clip.x + g->clip.w, - g->clip.y + g->clip.h); - - zr_command_buffer_push_scissor(out, clip); - g->clip = clip; - } return; failed: @@ -8050,7 +7880,7 @@ zr_group_end(struct zr_context *p, struct zr_context *g, struct zr_vec2 *scrollb pan.flags = g->flags|ZR_WINDOW_TAB; /* setup clipping rect to finalize group panel drawing back to parent */ - zr_unify(&clip, &p->clip, g->bounds.x, g->clip.y - g->header.h, g->bounds.x + g->bounds.w+1, + zr_unify(&clip, &p->clip, g->bounds.x, g->clip.y - g->header_h, g->bounds.x + g->bounds.w+1, g->bounds.y + g->bounds.h + 1); zr_command_buffer_push_scissor(out, clip); @@ -8068,9 +7898,10 @@ zr_group_end(struct zr_context *p, struct zr_context *g, struct zr_vec2 *scrollb */ zr_flags zr_popup_begin(struct zr_context *parent, struct zr_context *popup, - enum zr_popup_type type, zr_flags flags, + enum zr_popup_type type, const char *title, zr_flags flags, struct zr_rect rect, struct zr_vec2 scrollbar) { + zr_flags ret; struct zr_window panel; ZR_ASSERT(parent); ZR_ASSERT(popup); @@ -8099,14 +7930,14 @@ zr_popup_begin(struct zr_context *parent, struct zr_context *popup, zr_command_buffer_push_scissor(parent->buffer, zr_null_rect); zr_command_queue_start_child(parent->queue, parent->buffer); panel.buffer = *parent->buffer; - zr_begin(popup, &panel); + ret = zr_begin(popup, &panel, title); *parent->buffer = panel.buffer; parent->flags |= ZR_WINDOW_ROM; popup->buffer = parent->buffer; popup->offset = scrollbar; popup->queue = parent->queue; - return 1; + return ret; } void @@ -8178,7 +8009,7 @@ zr_popup_nonblocking_begin(struct zr_context *parent, /* if active create popup otherwise deactive the panel layout */ if (!is_active && *active) { - zr_popup_begin(parent, popup, ZR_POPUP_DYNAMIC, flags, body, scrollbar); + zr_popup_begin(parent, popup, ZR_POPUP_DYNAMIC, 0, flags, body, scrollbar); zr_popup_close(popup); popup->flags &= ~(zr_flags)ZR_WINDOW_MINIMIZED; parent->flags &= ~(zr_flags)ZR_WINDOW_ROM; @@ -8187,7 +8018,7 @@ zr_popup_nonblocking_begin(struct zr_context *parent, popup->flags |= ZR_WINDOW_MINIMIZED; return zr_false; } else { - zr_popup_begin(parent, popup, ZR_POPUP_DYNAMIC, flags, body, zr_vec2(0,0)); + zr_popup_begin(parent, popup, ZR_POPUP_DYNAMIC, 0, flags, body, zr_vec2(0,0)); popup->flags &= ~(zr_flags)ZR_WINDOW_MINIMIZED; } *active = is_active; @@ -8437,9 +8268,8 @@ zr_combo_begin(struct zr_context *parent, struct zr_context *combo, body.w = header.w; body.y = header.y + header.h; body.h = zr_null_rect.h; - if (!zr_popup_nonblocking_begin(parent, combo, ZR_WINDOW_NO_SCROLLBAR, + if (!zr_popup_nonblocking_begin(parent, combo, ZR_WINDOW_COMBO_MENU|ZR_WINDOW_NO_SCROLLBAR, active, is_active, body, zr_vec2(0,0))) goto failed; - combo->flags |= ZR_WINDOW_COMBO_MENU; } return; @@ -8521,9 +8351,8 @@ zr_menu_begin(struct zr_context *parent, struct zr_context *menu, body.w = width; body.y = header.y + header.h; body.h = (parent->bounds.y + parent->bounds.h) - body.y; - if (!zr_popup_nonblocking_begin(parent, menu, ZR_WINDOW_NO_SCROLLBAR, active, + if (!zr_popup_nonblocking_begin(parent, menu, ZR_WINDOW_COMBO_MENU|ZR_WINDOW_NO_SCROLLBAR, active, is_active, body, zr_vec2(0,0))) goto failed; - menu->flags |= ZR_WINDOW_COMBO_MENU; } return; @@ -8588,7 +8417,7 @@ zr_tooltip_begin(struct zr_context *parent, struct zr_context *tip, float width) bounds.h = zr_null_rect.h; bounds.x = (in->mouse.pos.x + 1) - parent->clip.x; bounds.y = (in->mouse.pos.y + 1) - parent->clip.y; - zr_popup_begin(parent, tip, ZR_POPUP_DYNAMIC, ZR_WINDOW_NO_SCROLLBAR, bounds, zr_vec2(0,0)); + zr_popup_begin(parent, tip, ZR_POPUP_DYNAMIC, 0, ZR_WINDOW_NO_SCROLLBAR, bounds, zr_vec2(0,0)); } void diff --git a/zahnrad.h b/zahnrad.h index 69c77c3..cb22a98 100644 --- a/zahnrad.h +++ b/zahnrad.h @@ -1858,6 +1858,11 @@ enum zr_style_properties { ZR_PROPERTY_MAX }; +enum zr_style_header_align { + ZR_HEADER_LEFT, + ZR_HEADER_RIGHT +}; + struct zr_saved_property { enum zr_style_properties type; /* identifier of the current modified property */ @@ -1894,11 +1899,24 @@ struct zr_style_mod_stack { /* current color stack pushing index */ }; +struct zr_style_header { + enum zr_style_header_align align; + /* header content alignment */ + zr_rune close_symbol; + /* header close icon unicode rune */ + zr_rune minimize_symbol; + /* header minimize icon unicode rune */ + zr_rune maximize_symbol; + /* header maximize icon unicode rune */ +}; + struct zr_style { struct zr_user_font font; /* the from the user provided font */ float rounding[ZR_ROUNDING_MAX]; /* rectangle widget rounding */ + struct zr_style_header header; + /* window header style */ struct zr_vec2 properties[ZR_PROPERTY_MAX]; /* configuration properties to modify the style */ struct zr_color colors[ZR_COLOR_COUNT]; @@ -2029,39 +2047,43 @@ const char *zr_style_property_name(enum zr_style_properties); Window Popup API -- Popup window with either non-blocking or blocking capabilities Window Menu API -- Popup menus with currently one single depth */ +#define ZR_FLAG(x) (1 << (x)) enum zr_window_flags { - ZR_WINDOW_HIDDEN = 0x01, + ZR_WINDOW_HIDDEN = ZR_FLAG(0), /* Hiddes the window and stops any window interaction and drawing can be set * by user input or by closing the window */ - ZR_WINDOW_BORDER = 0x02, - /* Draws a border around the window to visually seperate the window from the - * background */ - ZR_WINDOW_BORDER_HEADER = 0x04, + ZR_WINDOW_MINIMIZED = ZR_FLAG(1), + /* marks the window as minimized */ + ZR_WINDOW_BORDER = ZR_FLAG(2), + /* Draws a border around the window to visually seperate the window from the background */ + ZR_WINDOW_BORDER_HEADER = ZR_FLAG(3), /* Draws a border between window header and body */ - ZR_WINDOW_MOVEABLE = 0x08, + ZR_WINDOW_MOVEABLE = ZR_FLAG(4), /* The moveable flag inidicates that a window can be move by user input by * dragging the window header */ - ZR_WINDOW_SCALEABLE = 0x10, + ZR_WINDOW_SCALEABLE = ZR_FLAG(5), /* The scaleable flag indicates that a window can be scaled by user input * by dragging a scaler icon at the button of the window */ - ZR_WINDOW_MINIMIZED = 0x20, - /* marks the window as minimized */ - ZR_WINDOW_ROM = 0x40, + ZR_WINDOW_CLOSEABLE = ZR_FLAG(6), + /* adds a closeable icon into the header */ + ZR_WINDOW_MINIMIZABLE = ZR_FLAG(7), + /* adds a minimize icon into the header */ + ZR_WINDOW_ROM = ZR_FLAG(8), /* sets the window into a read only mode and does not allow input changes */ - ZR_WINDOW_DYNAMIC = 0x80, + ZR_WINDOW_DYNAMIC = ZR_FLAG(9), /* special type of window which grows up in height while being filled to a * certain maximum height. It is mainly used for combo boxes but can be * used to create perfectly fitting windows as well */ - ZR_WINDOW_ACTIVE = 0x10000, + ZR_WINDOW_NO_SCROLLBAR = ZR_FLAG(10), + /* Removes the scrollbar from the window */ + ZR_WINDOW_ACTIVE = ZR_FLAG(11), /* INTERNAL ONLY!: marks the window as active, used by the window stack */ - ZR_WINDOW_TAB = 0x20000, + ZR_WINDOW_TAB = ZR_FLAG(12), /* INTERNAL ONLY!: Marks the window as subwindow of another window(Groups/Tabs)*/ - ZR_WINDOW_COMBO_MENU = 0x40000, - /* INTERNAL ONLY!: Marks the window as an combo box or menu */ - ZR_WINDOW_REMOVE_ROM = 0x80000, + ZR_WINDOW_COMBO_MENU = ZR_FLAG(13), + /* INTERNAL ONLY!: Marks the window as a combo box or menu */ + ZR_WINDOW_REMOVE_ROM = ZR_FLAG(14) /* INTERNAL ONLY!: removes the read only mode at the end of the window */ - ZR_WINDOW_NO_SCROLLBAR = 0x100000 - /* INTERNAL ONLY!: removes the scrollbar from the window */ }; struct zr_window { @@ -2201,13 +2223,6 @@ struct zr_row_layout { /* temporary clipping rect */ }; -struct zr_header { - float x, y, w, h; - /* header bounds */ - float front, back; - /* visual header filling deque */ -}; - struct zr_menu { float x, y, w, h; /* menu bounds */ @@ -2230,10 +2245,10 @@ struct zr_context { /* size of the actual useable space inside the window */ float footer_h; /* height of the window footer space */ + float header_h; + /* height of the window footer space */ struct zr_rect clip; /* window clipping rect */ - struct zr_header header; - /* window header bounds */ struct zr_menu menu; /* window menubar bounds */ struct zr_row_layout row; @@ -2248,13 +2263,16 @@ struct zr_context { /* command draw call output command buffer */ }; -zr_flags zr_begin(struct zr_context*, struct zr_window*); +zr_flags zr_begin(struct zr_context*, struct zr_window*, const char *title); /* this function begins the window build up process by creating a context to fill Input: - input structure holding all user generated state changes Output: - window context to fill up with widgets - - ZR_WINDOW_MOVABLE if window was moved + - flags : + o ZR_WINDOW_MOVABLE if window was moved + o ZR_WINDOW_MINIMIZABLE if window was minimized/maximized + o ZR_WINDOW_CLOSEABLE if window was closed */ zr_flags zr_end(struct zr_context*, struct zr_window*); /* this function ends the window layout build up process and updates the window. @@ -2272,117 +2290,9 @@ struct zr_command_queue *zr_queue(struct zr_context*); /* -------------------------------------------------------------- * - * HEADER + * MENUBAR * - * -------------------------------------------------------------- - HEADER - The header API is for adding a window space at the top of the window for - buttons, icons and window title. It is useful for toggling the visiblity - aswell as minmized state of the window. The header can be filled with buttons - and icons from the left and as well as the right side and allows therefore - a wide range of header layouts. - - USAGE - To create a header you have to call one of two API after the window layout - has been created with `zr_begin`. The first and easiest way is to - just call `zr_header` which provides a basic header with - with title and button and buton pressed notification if a button was pressed. - The layout supported is hereby limited and custom button and icons cannot be - added. To achieve that you have to use the more extensive header API. - You start by calling `zr_header_begin` after `zr_begin` and - call the different `zr_header_xxx` functions to add icons or the title - either at the left or right side of the window. Each function returns if the - icon or button has been pressed or in the case of the toggle the current state. - Finally if all button/icons/toggles have been added the process is finished - by calling `zr_header_end`. - - window header function API - zr_header_begin -- begins the header build up process - zr_header_button -- adds a button into the header - zr_header_button_icon -- adds a image button into the header - zr_header_toggle -- adds a toggle button into the header - zr_header_flag -- adds a window flag toggle button - zr_header_title -- adds the title of the window into the header - zr_header_end -- finishes the header build up process - zr_header -- short cut version of the header build up process - zr_menubar_begin -- marks the beginning of the menubar building process - zr_menubar_end -- marks the end the menubar build up process -*/ -enum zr_header_flags { - ZR_CLOSEABLE = 0x01, - /* adds a closeable icon into the header */ - ZR_MINIMIZABLE = 0x02, - /* adds a minimize icon into the header */ - ZR_SCALEABLE = 0x04, - /* adds a scaleable flag icon into the header */ - ZR_MOVEABLE = 0x08 - /* adds a moveable flag icon into the header */ -}; - -enum zr_header_align { - ZR_HEADER_LEFT, - /* header elements are added at the left side of the header */ - ZR_HEADER_RIGHT - /* header elements are added at the right side of the header */ -}; - -zr_flags zr_header(struct zr_context*, const char *title, zr_flags show, - zr_flags notify, enum zr_header_align); -/* this function is a shorthand for the header build up process - flag by the user - Input: - - title of the header or NULL if not needed - - flags indicating which icons should be drawn to the header - - flags indicating which icons should notify if clicked -*/ -void zr_header_begin(struct zr_context*); -/* this function begins the window header build up process */ -int zr_header_button(struct zr_context *layout, enum zr_symbol symbol, - enum zr_header_align); -/* this function adds a header button icon - Input: - - - - symbol that shall be shown in the header as a icon - Output: - - zr_true if the button was pressed zr_false otherwise -*/ -int zr_header_button_icon(struct zr_context*, struct zr_image, - enum zr_header_align); -/* this function adds a header image button icon - Input: - - symbol that shall be shown in the header as a icon - Output: - - zr_true if the button was pressed zr_false otherwise -*/ -int zr_header_toggle(struct zr_context*, enum zr_symbol inactive, - enum zr_symbol active, enum zr_header_align, - int state); -/* this function adds a header toggle button - Input: - - symbol that will be drawn if the toggle is inactive - - symbol that will be drawn if the toggle is active - - state of the toggle with either active or inactive - Output: - - updated state of the toggle -*/ -int zr_header_flag(struct zr_context *layout, enum zr_symbol inactive, - enum zr_symbol active, enum zr_header_align, - enum zr_window_flags flag); -/* this function adds a header toggle button for modifing a certain window flag - Input: - - symbol that will be drawn if the flag is inactive - - symbol that will be drawn if the flag is active - - window flag whose state will be display by the toggle button - Output: - - zr_true if the button was pressed zr_false otherwise -*/ -void zr_header_title(struct zr_context*, const char*, enum zr_header_align); -/* this function adds a title to the window header - Input: - - title of the header -*/ -void zr_header_end(struct zr_context*); -/* this function ends the window header build up process */ + * --------------------------------------------------------------*/ void zr_menubar_begin(struct zr_context*); /* this function begins the window menubar build up process */ void zr_menubar_end(struct zr_context*); @@ -3175,8 +3085,8 @@ enum zr_popup_type { }; zr_flags zr_popup_begin(struct zr_context *parent, struct zr_context *popup, - enum zr_popup_type, zr_flags, struct zr_rect bounds, - struct zr_vec2 offset); + enum zr_popup_type, const char *title, + zr_flags, struct zr_rect bounds, struct zr_vec2 offset); /* this function adds a overlapping blocking popup menu Input: - type of the popup as either growing or static