changed window header API for less draw calls

This commit is contained in:
vurtun 2015-11-22 20:03:42 +01:00
parent 61a527f0d7
commit 19e4080537
5 changed files with 311 additions and 575 deletions

View File

@ -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);

View File

@ -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];

View File

@ -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;

627
zahnrad.c
View File

@ -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

192
zahnrad.h
View File

@ -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