Blame src-nuklear/nuklear_panel.c

Ivan Mahonin b53a5c
#include "nuklear.h"
Ivan Mahonin b53a5c
#include "nuklear_internal.h"
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
/* ===============================================================
Ivan Mahonin b53a5c
 *
Ivan Mahonin b53a5c
 *                              PANEL
Ivan Mahonin b53a5c
 *
Ivan Mahonin b53a5c
 * ===============================================================*/
Ivan Mahonin b53a5c
NK_LIB void*
Ivan Mahonin b53a5c
nk_create_panel(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_page_element *elem;
Ivan Mahonin b53a5c
    elem = nk_create_page_element(ctx);
Ivan Mahonin b53a5c
    if (!elem) return 0;
Ivan Mahonin b53a5c
    nk_zero_struct(*elem);
Ivan Mahonin b53a5c
    return &elem->data.pan;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
Ivan Mahonin b53a5c
    struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
Ivan Mahonin b53a5c
    nk_free_page_element(ctx, pe);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB nk_bool
Ivan Mahonin b53a5c
nk_panel_has_header(nk_flags flags, const char *title)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    nk_bool active = 0;
Ivan Mahonin b53a5c
    active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
Ivan Mahonin b53a5c
    active = active || (flags & NK_WINDOW_TITLE);
Ivan Mahonin b53a5c
    active = active && !(flags & NK_WINDOW_HIDDEN) && title;
Ivan Mahonin b53a5c
    return active;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB struct nk_vec2
Ivan Mahonin b53a5c
nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    switch (type) {
Ivan Mahonin b53a5c
    default:
Ivan Mahonin b53a5c
    case NK_PANEL_WINDOW: return style->window.padding;
Ivan Mahonin b53a5c
    case NK_PANEL_GROUP: return style->window.group_padding;
Ivan Mahonin b53a5c
    case NK_PANEL_POPUP: return style->window.popup_padding;
Ivan Mahonin b53a5c
    case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
Ivan Mahonin b53a5c
    case NK_PANEL_COMBO: return style->window.combo_padding;
Ivan Mahonin b53a5c
    case NK_PANEL_MENU: return style->window.menu_padding;
Ivan Mahonin b53a5c
    case NK_PANEL_TOOLTIP: return style->window.menu_padding;}
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB float
Ivan Mahonin b53a5c
nk_panel_get_border(const struct nk_style *style, nk_flags flags,
Ivan Mahonin b53a5c
    enum nk_panel_type type)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    if (flags & NK_WINDOW_BORDER) {
Ivan Mahonin b53a5c
        switch (type) {
Ivan Mahonin b53a5c
        default:
Ivan Mahonin b53a5c
        case NK_PANEL_WINDOW: return style->window.border;
Ivan Mahonin b53a5c
        case NK_PANEL_GROUP: return style->window.group_border;
Ivan Mahonin b53a5c
        case NK_PANEL_POPUP: return style->window.popup_border;
Ivan Mahonin b53a5c
        case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
Ivan Mahonin b53a5c
        case NK_PANEL_COMBO: return style->window.combo_border;
Ivan Mahonin b53a5c
        case NK_PANEL_MENU: return style->window.menu_border;
Ivan Mahonin b53a5c
        case NK_PANEL_TOOLTIP: return style->window.menu_border;
Ivan Mahonin b53a5c
    }} else return 0;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB struct nk_color
Ivan Mahonin b53a5c
nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    switch (type) {
Ivan Mahonin b53a5c
    default:
Ivan Mahonin b53a5c
    case NK_PANEL_WINDOW: return style->window.border_color;
Ivan Mahonin b53a5c
    case NK_PANEL_GROUP: return style->window.group_border_color;
Ivan Mahonin b53a5c
    case NK_PANEL_POPUP: return style->window.popup_border_color;
Ivan Mahonin b53a5c
    case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
Ivan Mahonin b53a5c
    case NK_PANEL_COMBO: return style->window.combo_border_color;
Ivan Mahonin b53a5c
    case NK_PANEL_MENU: return style->window.menu_border_color;
Ivan Mahonin b53a5c
    case NK_PANEL_TOOLTIP: return style->window.menu_border_color;}
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB nk_bool
Ivan Mahonin b53a5c
nk_panel_is_sub(enum nk_panel_type type)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    return (type & NK_PANEL_SET_SUB)?1:0;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB nk_bool
Ivan Mahonin b53a5c
nk_panel_is_nonblock(enum nk_panel_type type)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    return (type & NK_PANEL_SET_NONBLOCK)?1:0;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB nk_bool
Ivan Mahonin b53a5c
nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_input *in;
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    struct nk_panel *layout;
Ivan Mahonin b53a5c
    struct nk_command_buffer *out;
Ivan Mahonin b53a5c
    const struct nk_style *style;
Ivan Mahonin b53a5c
    const struct nk_user_font *font;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    struct nk_vec2 scrollbar_size;
Ivan Mahonin b53a5c
    struct nk_vec2 panel_padding;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current->layout);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current || !ctx->current->layout) return 0;
Ivan Mahonin b53a5c
    nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
Ivan Mahonin b53a5c
    if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
Ivan Mahonin b53a5c
        nk_zero(ctx->current->layout, sizeof(struct nk_panel));
Ivan Mahonin b53a5c
        ctx->current->layout->type = panel_type;
Ivan Mahonin b53a5c
        return 0;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    /* pull state into local stack */
Ivan Mahonin b53a5c
    style = &ctx->style;
Ivan Mahonin b53a5c
    font = style->font;
Ivan Mahonin b53a5c
    win = ctx->current;
Ivan Mahonin b53a5c
    layout = win->layout;
Ivan Mahonin b53a5c
    out = &win->buffer;
Ivan Mahonin b53a5c
    in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
Ivan Mahonin b53a5c
#ifdef NK_INCLUDE_COMMAND_USERDATA
Ivan Mahonin b53a5c
    win->buffer.userdata = ctx->userdata;
Ivan Mahonin b53a5c
#endif
Ivan Mahonin b53a5c
    /* pull style configuration into local stack */
Ivan Mahonin b53a5c
    scrollbar_size = style->window.scrollbar_size;
Ivan Mahonin b53a5c
    panel_padding = nk_panel_get_padding(style, panel_type);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* window movement */
Ivan Mahonin b53a5c
    if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
Ivan Mahonin b53a5c
        nk_bool left_mouse_down;
Ivan Mahonin b53a5c
        unsigned int left_mouse_clicked;
Ivan Mahonin b53a5c
        int left_mouse_click_in_cursor;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* calculate draggable window space */
Ivan Mahonin b53a5c
        struct nk_rect header;
Ivan Mahonin b53a5c
        header.x = win->bounds.x;
Ivan Mahonin b53a5c
        header.y = win->bounds.y;
Ivan Mahonin b53a5c
        header.w = win->bounds.w;
Ivan Mahonin b53a5c
        if (nk_panel_has_header(win->flags, title)) {
Ivan Mahonin b53a5c
            header.h = font->height + 2.0f * style->window.header.padding.y;
Ivan Mahonin b53a5c
            header.h += 2.0f * style->window.header.label_padding.y;
Ivan Mahonin b53a5c
        } else header.h = panel_padding.y;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* window movement by dragging */
Ivan Mahonin b53a5c
        left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
Ivan Mahonin b53a5c
        left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked;
Ivan Mahonin b53a5c
        left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
Ivan Mahonin b53a5c
            NK_BUTTON_LEFT, header, nk_true);
Ivan Mahonin b53a5c
        if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
Ivan Mahonin b53a5c
            win->bounds.x = win->bounds.x + in->mouse.delta.x;
Ivan Mahonin b53a5c
            win->bounds.y = win->bounds.y + in->mouse.delta.y;
Ivan Mahonin b53a5c
            in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x;
Ivan Mahonin b53a5c
            in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y;
Ivan Mahonin b53a5c
            ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE];
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* setup panel */
Ivan Mahonin b53a5c
    layout->type = panel_type;
Ivan Mahonin b53a5c
    layout->flags = win->flags;
Ivan Mahonin b53a5c
    layout->bounds = win->bounds;
Ivan Mahonin b53a5c
    layout->bounds.x += panel_padding.x;
Ivan Mahonin b53a5c
    layout->bounds.w -= 2*panel_padding.x;
Ivan Mahonin b53a5c
    if (win->flags & NK_WINDOW_BORDER) {
Ivan Mahonin b53a5c
        layout->border = nk_panel_get_border(style, win->flags, panel_type);
Ivan Mahonin b53a5c
        layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
Ivan Mahonin b53a5c
    } else layout->border = 0;
Ivan Mahonin b53a5c
    layout->at_y = layout->bounds.y;
Ivan Mahonin b53a5c
    layout->at_x = layout->bounds.x;
Ivan Mahonin b53a5c
    layout->max_x = 0;
Ivan Mahonin b53a5c
    layout->header_height = 0;
Ivan Mahonin b53a5c
    layout->footer_height = 0;
Ivan Mahonin b53a5c
    nk_layout_reset_min_row_height(ctx);
Ivan Mahonin b53a5c
    layout->row.index = 0;
Ivan Mahonin b53a5c
    layout->row.columns = 0;
Ivan Mahonin b53a5c
    layout->row.ratio = 0;
Ivan Mahonin b53a5c
    layout->row.item_width = 0;
Ivan Mahonin b53a5c
    layout->row.tree_depth = 0;
Ivan Mahonin b53a5c
    layout->row.height = panel_padding.y;
Ivan Mahonin b53a5c
    layout->has_scrolling = nk_true;
Ivan Mahonin b53a5c
    if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
Ivan Mahonin b53a5c
        layout->bounds.w -= scrollbar_size.x;
Ivan Mahonin b53a5c
    if (!nk_panel_is_nonblock(panel_type)) {
Ivan Mahonin b53a5c
        layout->footer_height = 0;
Ivan Mahonin b53a5c
        if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
Ivan Mahonin b53a5c
            layout->footer_height = scrollbar_size.y;
Ivan Mahonin b53a5c
        layout->bounds.h -= layout->footer_height;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* panel header */
Ivan Mahonin b53a5c
    if (nk_panel_has_header(win->flags, title))
Ivan Mahonin b53a5c
    {
Ivan Mahonin b53a5c
        struct nk_text text;
Ivan Mahonin b53a5c
        struct nk_rect header;
Ivan Mahonin b53a5c
        const struct nk_style_item *background = 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* calculate header bounds */
Ivan Mahonin b53a5c
        header.x = win->bounds.x;
Ivan Mahonin b53a5c
        header.y = win->bounds.y;
Ivan Mahonin b53a5c
        header.w = win->bounds.w;
Ivan Mahonin b53a5c
        header.h = font->height + 2.0f * style->window.header.padding.y;
Ivan Mahonin b53a5c
        header.h += (2.0f * style->window.header.label_padding.y);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* shrink panel by header */
Ivan Mahonin b53a5c
        layout->header_height = header.h;
Ivan Mahonin b53a5c
        layout->bounds.y += header.h;
Ivan Mahonin b53a5c
        layout->bounds.h -= header.h;
Ivan Mahonin b53a5c
        layout->at_y += header.h;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* select correct header background and text color */
Ivan Mahonin b53a5c
        if (ctx->active == win) {
Ivan Mahonin b53a5c
            background = &style->window.header.active;
Ivan Mahonin b53a5c
            text.text = style->window.header.label_active;
Ivan Mahonin b53a5c
        } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
Ivan Mahonin b53a5c
            background = &style->window.header.hover;
Ivan Mahonin b53a5c
            text.text = style->window.header.label_hover;
Ivan Mahonin b53a5c
        } else {
Ivan Mahonin b53a5c
            background = &style->window.header.normal;
Ivan Mahonin b53a5c
            text.text = style->window.header.label_normal;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* draw header background */
Ivan Mahonin b53a5c
        header.h += 1.0f;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        switch(background->type) {
Ivan Mahonin b53a5c
            case NK_STYLE_ITEM_IMAGE:
Ivan Mahonin b53a5c
                text.background = nk_rgba(0,0,0,0);
Ivan Mahonin b53a5c
                nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
Ivan Mahonin b53a5c
                break;
Ivan Mahonin b53a5c
            case NK_STYLE_ITEM_NINE_SLICE:
Ivan Mahonin b53a5c
                text.background = nk_rgba(0, 0, 0, 0);
Ivan Mahonin b53a5c
                nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white);
Ivan Mahonin b53a5c
                break;
Ivan Mahonin b53a5c
            case NK_STYLE_ITEM_COLOR:
Ivan Mahonin b53a5c
                text.background = background->data.color;
Ivan Mahonin b53a5c
                nk_fill_rect(out, header, 0, background->data.color);
Ivan Mahonin b53a5c
                break;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* window close button */
Ivan Mahonin b53a5c
        {struct nk_rect button;
Ivan Mahonin b53a5c
        button.y = header.y + style->window.header.padding.y;
Ivan Mahonin b53a5c
        button.h = header.h - 2 * style->window.header.padding.y;
Ivan Mahonin b53a5c
        button.w = button.h;
Ivan Mahonin b53a5c
        if (win->flags & NK_WINDOW_CLOSABLE) {
Ivan Mahonin b53a5c
            nk_flags ws = 0;
Ivan Mahonin b53a5c
            if (style->window.header.align == NK_HEADER_RIGHT) {
Ivan Mahonin b53a5c
                button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
Ivan Mahonin b53a5c
                header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
Ivan Mahonin b53a5c
            } else {
Ivan Mahonin b53a5c
                button.x = header.x + style->window.header.padding.x;
Ivan Mahonin b53a5c
                header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
            if (nk_do_button_symbol(&ws, &win->buffer, button,
Ivan Mahonin b53a5c
                style->window.header.close_symbol, NK_BUTTON_DEFAULT,
Ivan Mahonin b53a5c
                &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
Ivan Mahonin b53a5c
            {
Ivan Mahonin b53a5c
                layout->flags |= NK_WINDOW_HIDDEN;
Ivan Mahonin b53a5c
                layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* window minimize button */
Ivan Mahonin b53a5c
        if (win->flags & NK_WINDOW_MINIMIZABLE) {
Ivan Mahonin b53a5c
            nk_flags ws = 0;
Ivan Mahonin b53a5c
            if (style->window.header.align == NK_HEADER_RIGHT) {
Ivan Mahonin b53a5c
                button.x = (header.w + header.x) - button.w;
Ivan Mahonin b53a5c
                if (!(win->flags & NK_WINDOW_CLOSABLE)) {
Ivan Mahonin b53a5c
                    button.x -= style->window.header.padding.x;
Ivan Mahonin b53a5c
                    header.w -= style->window.header.padding.x;
Ivan Mahonin b53a5c
                }
Ivan Mahonin b53a5c
                header.w -= button.w + style->window.header.spacing.x;
Ivan Mahonin b53a5c
            } else {
Ivan Mahonin b53a5c
                button.x = header.x;
Ivan Mahonin b53a5c
                header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
            if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
Ivan Mahonin b53a5c
                style->window.header.maximize_symbol: style->window.header.minimize_symbol,
Ivan Mahonin b53a5c
                NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
Ivan Mahonin b53a5c
                layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
Ivan Mahonin b53a5c
                    layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
Ivan Mahonin b53a5c
                    layout->flags | NK_WINDOW_MINIMIZED;
Ivan Mahonin b53a5c
        }}
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        {/* window header title */
Ivan Mahonin b53a5c
        int text_len = nk_strlen(title);
Ivan Mahonin b53a5c
        struct nk_rect label = {0,0,0,0};
Ivan Mahonin b53a5c
        float t = font->width(font->userdata, font->height, title, text_len);
Ivan Mahonin b53a5c
        text.padding = nk_vec2(0,0);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        label.x = header.x + style->window.header.padding.x;
Ivan Mahonin b53a5c
        label.x += style->window.header.label_padding.x;
Ivan Mahonin b53a5c
        label.y = header.y + style->window.header.label_padding.y;
Ivan Mahonin b53a5c
        label.h = font->height + 2 * style->window.header.label_padding.y;
Ivan Mahonin b53a5c
        label.w = t + 2 * style->window.header.spacing.x;
Ivan Mahonin b53a5c
        label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
Ivan Mahonin b53a5c
        nk_widget_text(out, label, (const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* draw window background */
Ivan Mahonin b53a5c
    if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
Ivan Mahonin b53a5c
        struct nk_rect body;
Ivan Mahonin b53a5c
        body.x = win->bounds.x;
Ivan Mahonin b53a5c
        body.w = win->bounds.w;
Ivan Mahonin b53a5c
        body.y = (win->bounds.y + layout->header_height);
Ivan Mahonin b53a5c
        body.h = (win->bounds.h - layout->header_height);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        switch(style->window.fixed_background.type) {
Ivan Mahonin b53a5c
            case NK_STYLE_ITEM_IMAGE:
Ivan Mahonin b53a5c
                nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
Ivan Mahonin b53a5c
                break;
Ivan Mahonin b53a5c
            case NK_STYLE_ITEM_NINE_SLICE:
Ivan Mahonin b53a5c
                nk_draw_nine_slice(out, body, &style->window.fixed_background.data.slice, nk_white);
Ivan Mahonin b53a5c
                break;
Ivan Mahonin b53a5c
            case NK_STYLE_ITEM_COLOR:
Ivan Mahonin b53a5c
                nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
Ivan Mahonin b53a5c
                break;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* set clipping rectangle */
Ivan Mahonin b53a5c
    {struct nk_rect clip;
Ivan Mahonin b53a5c
    layout->clip = layout->bounds;
Ivan Mahonin b53a5c
    nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
Ivan Mahonin b53a5c
        layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
Ivan Mahonin b53a5c
    nk_push_scissor(out, clip);
Ivan Mahonin b53a5c
    layout->clip = clip;}
Ivan Mahonin b53a5c
    return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_panel_end(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_input *in;
Ivan Mahonin b53a5c
    struct nk_window *window;
Ivan Mahonin b53a5c
    struct nk_panel *layout;
Ivan Mahonin b53a5c
    const struct nk_style *style;
Ivan Mahonin b53a5c
    struct nk_command_buffer *out;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    struct nk_vec2 scrollbar_size;
Ivan Mahonin b53a5c
    struct nk_vec2 panel_padding;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current->layout);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current || !ctx->current->layout)
Ivan Mahonin b53a5c
        return;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    window = ctx->current;
Ivan Mahonin b53a5c
    layout = window->layout;
Ivan Mahonin b53a5c
    style = &ctx->style;
Ivan Mahonin b53a5c
    out = &window->buffer;
Ivan Mahonin b53a5c
    in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
Ivan Mahonin b53a5c
    if (!nk_panel_is_sub(layout->type))
Ivan Mahonin b53a5c
        nk_push_scissor(out, nk_null_rect);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* cache configuration data */
Ivan Mahonin b53a5c
    scrollbar_size = style->window.scrollbar_size;
Ivan Mahonin b53a5c
    panel_padding = nk_panel_get_padding(style, layout->type);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* update the current cursor Y-position to point over the last added widget */
Ivan Mahonin b53a5c
    layout->at_y += layout->row.height;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* dynamic panels */
Ivan Mahonin b53a5c
    if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
Ivan Mahonin b53a5c
    {
Ivan Mahonin b53a5c
        /* update panel height to fit dynamic growth */
Ivan Mahonin b53a5c
        struct nk_rect empty_space;
Ivan Mahonin b53a5c
        if (layout->at_y < (layout->bounds.y + layout->bounds.h))
Ivan Mahonin b53a5c
            layout->bounds.h = layout->at_y - layout->bounds.y;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* fill top empty space */
Ivan Mahonin b53a5c
        empty_space.x = window->bounds.x;
Ivan Mahonin b53a5c
        empty_space.y = layout->bounds.y;
Ivan Mahonin b53a5c
        empty_space.h = panel_padding.y;
Ivan Mahonin b53a5c
        empty_space.w = window->bounds.w;
Ivan Mahonin b53a5c
        nk_fill_rect(out, empty_space, 0, style->window.background);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* fill left empty space */
Ivan Mahonin b53a5c
        empty_space.x = window->bounds.x;
Ivan Mahonin b53a5c
        empty_space.y = layout->bounds.y;
Ivan Mahonin b53a5c
        empty_space.w = panel_padding.x + layout->border;
Ivan Mahonin b53a5c
        empty_space.h = layout->bounds.h;
Ivan Mahonin b53a5c
        nk_fill_rect(out, empty_space, 0, style->window.background);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* fill right empty space */
Ivan Mahonin b53a5c
        empty_space.x = layout->bounds.x + layout->bounds.w;
Ivan Mahonin b53a5c
        empty_space.y = layout->bounds.y;
Ivan Mahonin b53a5c
        empty_space.w = panel_padding.x + layout->border;
Ivan Mahonin b53a5c
        empty_space.h = layout->bounds.h;
Ivan Mahonin b53a5c
        if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
Ivan Mahonin b53a5c
            empty_space.w += scrollbar_size.x;
Ivan Mahonin b53a5c
        nk_fill_rect(out, empty_space, 0, style->window.background);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* fill bottom empty space */
Ivan Mahonin b53a5c
        if (layout->footer_height > 0) {
Ivan Mahonin b53a5c
            empty_space.x = window->bounds.x;
Ivan Mahonin b53a5c
            empty_space.y = layout->bounds.y + layout->bounds.h;
Ivan Mahonin b53a5c
            empty_space.w = window->bounds.w;
Ivan Mahonin b53a5c
            empty_space.h = layout->footer_height;
Ivan Mahonin b53a5c
            nk_fill_rect(out, empty_space, 0, style->window.background);
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* scrollbars */
Ivan Mahonin b53a5c
    if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
Ivan Mahonin b53a5c
        !(layout->flags & NK_WINDOW_MINIMIZED) &&
Ivan Mahonin b53a5c
        window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT)
Ivan Mahonin b53a5c
    {
Ivan Mahonin b53a5c
        struct nk_rect scroll;
Ivan Mahonin b53a5c
        int scroll_has_scrolling;
Ivan Mahonin b53a5c
        float scroll_target;
Ivan Mahonin b53a5c
        float scroll_offset;
Ivan Mahonin b53a5c
        float scroll_step;
Ivan Mahonin b53a5c
        float scroll_inc;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* mouse wheel scrolling */
Ivan Mahonin b53a5c
        if (nk_panel_is_sub(layout->type))
Ivan Mahonin b53a5c
        {
Ivan Mahonin b53a5c
            /* sub-window mouse wheel scrolling */
Ivan Mahonin b53a5c
            struct nk_window *root_window = window;
Ivan Mahonin b53a5c
            struct nk_panel *root_panel = window->layout;
Ivan Mahonin b53a5c
            while (root_panel->parent)
Ivan Mahonin b53a5c
                root_panel = root_panel->parent;
Ivan Mahonin b53a5c
            while (root_window->parent)
Ivan Mahonin b53a5c
                root_window = root_window->parent;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
            /* only allow scrolling if parent window is active */
Ivan Mahonin b53a5c
            scroll_has_scrolling = 0;
Ivan Mahonin b53a5c
            if ((root_window == ctx->active) && layout->has_scrolling) {
Ivan Mahonin b53a5c
                /* and panel is being hovered and inside clip rect*/
Ivan Mahonin b53a5c
                if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
Ivan Mahonin b53a5c
                    NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
Ivan Mahonin b53a5c
                        root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
Ivan Mahonin b53a5c
                {
Ivan Mahonin b53a5c
                    /* deactivate all parent scrolling */
Ivan Mahonin b53a5c
                    root_panel = window->layout;
Ivan Mahonin b53a5c
                    while (root_panel->parent) {
Ivan Mahonin b53a5c
                        root_panel->has_scrolling = nk_false;
Ivan Mahonin b53a5c
                        root_panel = root_panel->parent;
Ivan Mahonin b53a5c
                    }
Ivan Mahonin b53a5c
                    root_panel->has_scrolling = nk_false;
Ivan Mahonin b53a5c
                    scroll_has_scrolling = nk_true;
Ivan Mahonin b53a5c
                }
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
        } else if (!nk_panel_is_sub(layout->type)) {
Ivan Mahonin b53a5c
            /* window mouse wheel scrolling */
Ivan Mahonin b53a5c
            scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
Ivan Mahonin b53a5c
            if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
Ivan Mahonin b53a5c
                window->scrolled = nk_true;
Ivan Mahonin b53a5c
            else window->scrolled = nk_false;
Ivan Mahonin b53a5c
        } else scroll_has_scrolling = nk_false;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        {
Ivan Mahonin b53a5c
            /* vertical scrollbar */
Ivan Mahonin b53a5c
            nk_flags state = 0;
Ivan Mahonin b53a5c
            scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
Ivan Mahonin b53a5c
            scroll.y = layout->bounds.y;
Ivan Mahonin b53a5c
            scroll.w = scrollbar_size.x;
Ivan Mahonin b53a5c
            scroll.h = layout->bounds.h;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
            scroll_offset = (float)*layout->offset_y;
Ivan Mahonin b53a5c
            scroll_step = scroll.h * 0.10f;
Ivan Mahonin b53a5c
            scroll_inc = scroll.h * 0.01f;
Ivan Mahonin b53a5c
            scroll_target = (float)(int)(layout->at_y - scroll.y);
Ivan Mahonin b53a5c
            scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
Ivan Mahonin b53a5c
                scroll_offset, scroll_target, scroll_step, scroll_inc,
Ivan Mahonin b53a5c
                &ctx->style.scrollv, in, style->font);
Ivan Mahonin b53a5c
            *layout->offset_y = (nk_uint)scroll_offset;
Ivan Mahonin b53a5c
            if (in && scroll_has_scrolling)
Ivan Mahonin b53a5c
                in->mouse.scroll_delta.y = 0;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
        {
Ivan Mahonin b53a5c
            /* horizontal scrollbar */
Ivan Mahonin b53a5c
            nk_flags state = 0;
Ivan Mahonin b53a5c
            scroll.x = layout->bounds.x;
Ivan Mahonin b53a5c
            scroll.y = layout->bounds.y + layout->bounds.h;
Ivan Mahonin b53a5c
            scroll.w = layout->bounds.w;
Ivan Mahonin b53a5c
            scroll.h = scrollbar_size.y;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
            scroll_offset = (float)*layout->offset_x;
Ivan Mahonin b53a5c
            scroll_target = (float)(int)(layout->max_x - scroll.x);
Ivan Mahonin b53a5c
            scroll_step = layout->max_x * 0.05f;
Ivan Mahonin b53a5c
            scroll_inc = layout->max_x * 0.005f;
Ivan Mahonin b53a5c
            scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
Ivan Mahonin b53a5c
                scroll_offset, scroll_target, scroll_step, scroll_inc,
Ivan Mahonin b53a5c
                &ctx->style.scrollh, in, style->font);
Ivan Mahonin b53a5c
            *layout->offset_x = (nk_uint)scroll_offset;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* hide scroll if no user input */
Ivan Mahonin b53a5c
    if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
Ivan Mahonin b53a5c
        int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
Ivan Mahonin b53a5c
        int is_window_hovered = nk_window_is_hovered(ctx);
Ivan Mahonin b53a5c
        int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
Ivan Mahonin b53a5c
        if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
Ivan Mahonin b53a5c
            window->scrollbar_hiding_timer += ctx->delta_time_seconds;
Ivan Mahonin b53a5c
        else window->scrollbar_hiding_timer = 0;
Ivan Mahonin b53a5c
    } else window->scrollbar_hiding_timer = 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* window border */
Ivan Mahonin b53a5c
    if (layout->flags & NK_WINDOW_BORDER)
Ivan Mahonin b53a5c
    {
Ivan Mahonin b53a5c
        struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
Ivan Mahonin b53a5c
        const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED)
Ivan Mahonin b53a5c
            ? (style->window.border + window->bounds.y + layout->header_height)
Ivan Mahonin b53a5c
            : ((layout->flags & NK_WINDOW_DYNAMIC)
Ivan Mahonin b53a5c
                ? (layout->bounds.y + layout->bounds.h + layout->footer_height)
Ivan Mahonin b53a5c
                : (window->bounds.y + window->bounds.h));
Ivan Mahonin b53a5c
        struct nk_rect b = window->bounds;
Ivan Mahonin b53a5c
        b.h = padding_y - window->bounds.y;
Ivan Mahonin b53a5c
        nk_stroke_rect(out, b, 0, layout->border, border_color);
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* scaler */
Ivan Mahonin b53a5c
    if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
Ivan Mahonin b53a5c
    {
Ivan Mahonin b53a5c
        /* calculate scaler bounds */
Ivan Mahonin b53a5c
        struct nk_rect scaler;
Ivan Mahonin b53a5c
        scaler.w = scrollbar_size.x;
Ivan Mahonin b53a5c
        scaler.h = scrollbar_size.y;
Ivan Mahonin b53a5c
        scaler.y = layout->bounds.y + layout->bounds.h;
Ivan Mahonin b53a5c
        if (layout->flags & NK_WINDOW_SCALE_LEFT)
Ivan Mahonin b53a5c
            scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
Ivan Mahonin b53a5c
        else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
Ivan Mahonin b53a5c
        if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
Ivan Mahonin b53a5c
            scaler.x -= scaler.w;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* draw scaler */
Ivan Mahonin b53a5c
        {const struct nk_style_item *item = &style->window.scaler;
Ivan Mahonin b53a5c
        if (item->type == NK_STYLE_ITEM_IMAGE)
Ivan Mahonin b53a5c
            nk_draw_image(out, scaler, &item->data.image, nk_white);
Ivan Mahonin b53a5c
        else {
Ivan Mahonin b53a5c
            if (layout->flags & NK_WINDOW_SCALE_LEFT) {
Ivan Mahonin b53a5c
                nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
Ivan Mahonin b53a5c
                    scaler.y + scaler.h, scaler.x + scaler.w,
Ivan Mahonin b53a5c
                    scaler.y + scaler.h, item->data.color);
Ivan Mahonin b53a5c
            } else {
Ivan Mahonin b53a5c
                nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
Ivan Mahonin b53a5c
                    scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
        }}
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* do window scaling */
Ivan Mahonin b53a5c
        if (!(window->flags & NK_WINDOW_ROM)) {
Ivan Mahonin b53a5c
            struct nk_vec2 window_size = style->window.min_size;
Ivan Mahonin b53a5c
            int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
Ivan Mahonin b53a5c
            int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
Ivan Mahonin b53a5c
                    NK_BUTTON_LEFT, scaler, nk_true);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
            if (left_mouse_down && left_mouse_click_in_scaler) {
Ivan Mahonin b53a5c
                float delta_x = in->mouse.delta.x;
Ivan Mahonin b53a5c
                if (layout->flags & NK_WINDOW_SCALE_LEFT) {
Ivan Mahonin b53a5c
                    delta_x = -delta_x;
Ivan Mahonin b53a5c
                    window->bounds.x += in->mouse.delta.x;
Ivan Mahonin b53a5c
                }
Ivan Mahonin b53a5c
                /* dragging in x-direction  */
Ivan Mahonin b53a5c
                if (window->bounds.w + delta_x >= window_size.x) {
Ivan Mahonin b53a5c
                    if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
Ivan Mahonin b53a5c
                        window->bounds.w = window->bounds.w + delta_x;
Ivan Mahonin b53a5c
                        scaler.x += in->mouse.delta.x;
Ivan Mahonin b53a5c
                    }
Ivan Mahonin b53a5c
                }
Ivan Mahonin b53a5c
                /* dragging in y-direction (only possible if static window) */
Ivan Mahonin b53a5c
                if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
Ivan Mahonin b53a5c
                    if (window_size.y < window->bounds.h + in->mouse.delta.y) {
Ivan Mahonin b53a5c
                        if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
Ivan Mahonin b53a5c
                            window->bounds.h = window->bounds.h + in->mouse.delta.y;
Ivan Mahonin b53a5c
                            scaler.y += in->mouse.delta.y;
Ivan Mahonin b53a5c
                        }
Ivan Mahonin b53a5c
                    }
Ivan Mahonin b53a5c
                }
Ivan Mahonin b53a5c
                ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT];
Ivan Mahonin b53a5c
                in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
Ivan Mahonin b53a5c
                in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    if (!nk_panel_is_sub(layout->type)) {
Ivan Mahonin b53a5c
        /* window is hidden so clear command buffer  */
Ivan Mahonin b53a5c
        if (layout->flags & NK_WINDOW_HIDDEN)
Ivan Mahonin b53a5c
            nk_command_buffer_reset(&window->buffer);
Ivan Mahonin b53a5c
        /* window is visible and not tab */
Ivan Mahonin b53a5c
        else nk_finish(ctx, window);
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
Ivan Mahonin b53a5c
    if (layout->flags & NK_WINDOW_REMOVE_ROM) {
Ivan Mahonin b53a5c
        layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
Ivan Mahonin b53a5c
        layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    window->flags = layout->flags;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* property garbage collector */
Ivan Mahonin b53a5c
    if (window->property.active && window->property.old != window->property.seq &&
Ivan Mahonin b53a5c
        window->property.active == window->property.prev) {
Ivan Mahonin b53a5c
        nk_zero(&window->property, sizeof(window->property));
Ivan Mahonin b53a5c
    } else {
Ivan Mahonin b53a5c
        window->property.old = window->property.seq;
Ivan Mahonin b53a5c
        window->property.prev = window->property.active;
Ivan Mahonin b53a5c
        window->property.seq = 0;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    /* edit garbage collector */
Ivan Mahonin b53a5c
    if (window->edit.active && window->edit.old != window->edit.seq &&
Ivan Mahonin b53a5c
       window->edit.active == window->edit.prev) {
Ivan Mahonin b53a5c
        nk_zero(&window->edit, sizeof(window->edit));
Ivan Mahonin b53a5c
    } else {
Ivan Mahonin b53a5c
        window->edit.old = window->edit.seq;
Ivan Mahonin b53a5c
        window->edit.prev = window->edit.active;
Ivan Mahonin b53a5c
        window->edit.seq = 0;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    /* contextual garbage collector */
Ivan Mahonin b53a5c
    if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
Ivan Mahonin b53a5c
        window->popup.con_count = 0;
Ivan Mahonin b53a5c
        window->popup.con_old = 0;
Ivan Mahonin b53a5c
        window->popup.active_con = 0;
Ivan Mahonin b53a5c
    } else {
Ivan Mahonin b53a5c
        window->popup.con_old = window->popup.con_count;
Ivan Mahonin b53a5c
        window->popup.con_count = 0;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    window->popup.combo_count = 0;
Ivan Mahonin b53a5c
    /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
Ivan Mahonin b53a5c
    NK_ASSERT(!layout->row.tree_depth);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c