changed window header API for less draw calls
This commit is contained in:
parent
61a527f0d7
commit
19e4080537
55
demo/demo.c
55
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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
627
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
|
||||
|
|
192
zahnrad.h
192
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
|
||||
|
|
Loading…
Reference in New Issue