Blame src-nuklear/nuklear_window.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
 *                              WINDOW
Ivan Mahonin b53a5c
 *
Ivan Mahonin b53a5c
 * ===============================================================*/
Ivan Mahonin b53a5c
NK_LIB void*
Ivan Mahonin b53a5c
nk_create_window(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
    elem->data.win.seq = ctx->seq;
Ivan Mahonin b53a5c
    return &elem->data.win;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_free_window(struct nk_context *ctx, struct nk_window *win)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    /* unlink windows from list */
Ivan Mahonin b53a5c
    struct nk_table *it = win->tables;
Ivan Mahonin b53a5c
    if (win->popup.win) {
Ivan Mahonin b53a5c
        nk_free_window(ctx, win->popup.win);
Ivan Mahonin b53a5c
        win->popup.win = 0;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    win->next = 0;
Ivan Mahonin b53a5c
    win->prev = 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    while (it) {
Ivan Mahonin b53a5c
        /*free window state tables */
Ivan Mahonin b53a5c
        struct nk_table *n = it->next;
Ivan Mahonin b53a5c
        nk_remove_table(win, it);
Ivan Mahonin b53a5c
        nk_free_table(ctx, it);
Ivan Mahonin b53a5c
        if (it == win->tables)
Ivan Mahonin b53a5c
            win->tables = n;
Ivan Mahonin b53a5c
        it = n;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* link windows into freelist */
Ivan Mahonin b53a5c
    {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
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 struct nk_window*
Ivan Mahonin b53a5c
nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *iter;
Ivan Mahonin b53a5c
    iter = ctx->begin;
Ivan Mahonin b53a5c
    while (iter) {
Ivan Mahonin b53a5c
        NK_ASSERT(iter != iter->next);
Ivan Mahonin b53a5c
        if (iter->name == hash) {
Ivan Mahonin b53a5c
            int max_len = nk_strlen(iter->name_string);
Ivan Mahonin b53a5c
            if (!nk_stricmpn(iter->name_string, name, max_len))
Ivan Mahonin b53a5c
                return iter;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
        iter = iter->next;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    return 0;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_insert_window(struct nk_context *ctx, struct nk_window *win,
Ivan Mahonin b53a5c
    enum nk_window_insert_location loc)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    const struct nk_window *iter;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(win);
Ivan Mahonin b53a5c
    if (!win || !ctx) return;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    iter = ctx->begin;
Ivan Mahonin b53a5c
    while (iter) {
Ivan Mahonin b53a5c
        NK_ASSERT(iter != iter->next);
Ivan Mahonin b53a5c
        NK_ASSERT(iter != win);
Ivan Mahonin b53a5c
        if (iter == win) return;
Ivan Mahonin b53a5c
        iter = iter->next;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    if (!ctx->begin) {
Ivan Mahonin b53a5c
        win->next = 0;
Ivan Mahonin b53a5c
        win->prev = 0;
Ivan Mahonin b53a5c
        ctx->begin = win;
Ivan Mahonin b53a5c
        ctx->end = win;
Ivan Mahonin b53a5c
        ctx->count = 1;
Ivan Mahonin b53a5c
        return;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    if (loc == NK_INSERT_BACK) {
Ivan Mahonin b53a5c
        struct nk_window *end;
Ivan Mahonin b53a5c
        end = ctx->end;
Ivan Mahonin b53a5c
        end->flags |= NK_WINDOW_ROM;
Ivan Mahonin b53a5c
        end->next = win;
Ivan Mahonin b53a5c
        win->prev = ctx->end;
Ivan Mahonin b53a5c
        win->next = 0;
Ivan Mahonin b53a5c
        ctx->end = win;
Ivan Mahonin b53a5c
        ctx->active = ctx->end;
Ivan Mahonin b53a5c
        ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
Ivan Mahonin b53a5c
    } else {
Ivan Mahonin b53a5c
        /*ctx->end->flags |= NK_WINDOW_ROM;*/
Ivan Mahonin b53a5c
        ctx->begin->prev = win;
Ivan Mahonin b53a5c
        win->next = ctx->begin;
Ivan Mahonin b53a5c
        win->prev = 0;
Ivan Mahonin b53a5c
        ctx->begin = win;
Ivan Mahonin b53a5c
        ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    ctx->count++;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_remove_window(struct nk_context *ctx, struct nk_window *win)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    if (win == ctx->begin || win == ctx->end) {
Ivan Mahonin b53a5c
        if (win == ctx->begin) {
Ivan Mahonin b53a5c
            ctx->begin = win->next;
Ivan Mahonin b53a5c
            if (win->next)
Ivan Mahonin b53a5c
                win->next->prev = 0;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
        if (win == ctx->end) {
Ivan Mahonin b53a5c
            ctx->end = win->prev;
Ivan Mahonin b53a5c
            if (win->prev)
Ivan Mahonin b53a5c
                win->prev->next = 0;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
    } else {
Ivan Mahonin b53a5c
        if (win->next)
Ivan Mahonin b53a5c
            win->next->prev = win->prev;
Ivan Mahonin b53a5c
        if (win->prev)
Ivan Mahonin b53a5c
            win->prev->next = win->next;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    if (win == ctx->active || !ctx->active) {
Ivan Mahonin b53a5c
        ctx->active = ctx->end;
Ivan Mahonin b53a5c
        if (ctx->end)
Ivan Mahonin b53a5c
            ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    win->next = 0;
Ivan Mahonin b53a5c
    win->prev = 0;
Ivan Mahonin b53a5c
    ctx->count--;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_begin(struct nk_context *ctx, const char *title,
Ivan Mahonin b53a5c
    struct nk_rect bounds, nk_flags flags)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    return nk_begin_titled(ctx, title, title, bounds, flags);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
Ivan Mahonin b53a5c
    struct nk_rect bounds, nk_flags flags)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    struct nk_style *style;
Ivan Mahonin b53a5c
    nk_hash name_hash;
Ivan Mahonin b53a5c
    int name_len;
Ivan Mahonin b53a5c
    int ret = 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(name);
Ivan Mahonin b53a5c
    NK_ASSERT(title);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
Ivan Mahonin b53a5c
    NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
Ivan Mahonin b53a5c
    if (!ctx || ctx->current || !title || !name)
Ivan Mahonin b53a5c
        return 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* find or create window */
Ivan Mahonin b53a5c
    style = &ctx->style;
Ivan Mahonin b53a5c
    name_len = (int)nk_strlen(name);
Ivan Mahonin b53a5c
    name_hash = nk_murmur_hash(name, (int)name_len, NK_WINDOW_TITLE);
Ivan Mahonin b53a5c
    win = nk_find_window(ctx, name_hash, name);
Ivan Mahonin b53a5c
    if (!win) {
Ivan Mahonin b53a5c
        /* create new window */
Ivan Mahonin b53a5c
        nk_size name_length = (nk_size)name_len;
Ivan Mahonin b53a5c
        win = (struct nk_window*)nk_create_window(ctx);
Ivan Mahonin b53a5c
        NK_ASSERT(win);
Ivan Mahonin b53a5c
        if (!win) return 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        if (flags & NK_WINDOW_BACKGROUND)
Ivan Mahonin b53a5c
            nk_insert_window(ctx, win, NK_INSERT_FRONT);
Ivan Mahonin b53a5c
        else nk_insert_window(ctx, win, NK_INSERT_BACK);
Ivan Mahonin b53a5c
        nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        win->flags = flags;
Ivan Mahonin b53a5c
        win->bounds = bounds;
Ivan Mahonin b53a5c
        win->name = name_hash;
Ivan Mahonin b53a5c
        name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
Ivan Mahonin b53a5c
        NK_MEMCPY(win->name_string, name, name_length);
Ivan Mahonin b53a5c
        win->name_string[name_length] = 0;
Ivan Mahonin b53a5c
        win->popup.win = 0;
Ivan Mahonin b53a5c
        if (!ctx->active)
Ivan Mahonin b53a5c
            ctx->active = win;
Ivan Mahonin b53a5c
    } else {
Ivan Mahonin b53a5c
        /* update window */
Ivan Mahonin b53a5c
        win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
Ivan Mahonin b53a5c
        win->flags |= flags;
Ivan Mahonin b53a5c
        if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
Ivan Mahonin b53a5c
            win->bounds = bounds;
Ivan Mahonin b53a5c
        /* If this assert triggers you either:
Ivan Mahonin b53a5c
         *
Ivan Mahonin b53a5c
         * I.) Have more than one window with the same name or
Ivan Mahonin b53a5c
         * II.) You forgot to actually draw the window.
Ivan Mahonin b53a5c
         *      More specific you did not call `nk_clear` (nk_clear will be
Ivan Mahonin b53a5c
         *      automatically called for you if you are using one of the
Ivan Mahonin b53a5c
         *      provided demo backends). */
Ivan Mahonin b53a5c
        NK_ASSERT(win->seq != ctx->seq);
Ivan Mahonin b53a5c
        win->seq = ctx->seq;
Ivan Mahonin b53a5c
        if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) {
Ivan Mahonin b53a5c
            ctx->active = win;
Ivan Mahonin b53a5c
            ctx->end = win;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    if (win->flags & NK_WINDOW_HIDDEN) {
Ivan Mahonin b53a5c
        ctx->current = win;
Ivan Mahonin b53a5c
        win->layout = 0;
Ivan Mahonin b53a5c
        return 0;
Ivan Mahonin b53a5c
    } else nk_start(ctx, win);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* window overlapping */
Ivan Mahonin b53a5c
    if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
Ivan Mahonin b53a5c
    {
Ivan Mahonin b53a5c
        int inpanel, ishovered;
Ivan Mahonin b53a5c
        struct nk_window *iter = win;
Ivan Mahonin b53a5c
        float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
Ivan Mahonin b53a5c
            (2.0f * style->window.header.label_padding.y);
Ivan Mahonin b53a5c
        struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
Ivan Mahonin b53a5c
            win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* activate window if hovered and no other window is overlapping this window */
Ivan Mahonin b53a5c
        inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
Ivan Mahonin b53a5c
        inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
Ivan Mahonin b53a5c
        ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
Ivan Mahonin b53a5c
        if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
Ivan Mahonin b53a5c
            iter = win->next;
Ivan Mahonin b53a5c
            while (iter) {
Ivan Mahonin b53a5c
                struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
Ivan Mahonin b53a5c
                    iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
Ivan Mahonin b53a5c
                if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
Ivan Mahonin b53a5c
                    iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
Ivan Mahonin b53a5c
                    (!(iter->flags & NK_WINDOW_HIDDEN)))
Ivan Mahonin b53a5c
                    break;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
                if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
Ivan Mahonin b53a5c
                    NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
Ivan Mahonin b53a5c
                    iter->popup.win->bounds.x, iter->popup.win->bounds.y,
Ivan Mahonin b53a5c
                    iter->popup.win->bounds.w, iter->popup.win->bounds.h))
Ivan Mahonin b53a5c
                    break;
Ivan Mahonin b53a5c
                iter = iter->next;
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* activate window if clicked */
Ivan Mahonin b53a5c
        if (iter && inpanel && (win != ctx->end)) {
Ivan Mahonin b53a5c
            iter = win->next;
Ivan Mahonin b53a5c
            while (iter) {
Ivan Mahonin b53a5c
                /* try to find a panel with higher priority in the same position */
Ivan Mahonin b53a5c
                struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
Ivan Mahonin b53a5c
                iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
Ivan Mahonin b53a5c
                if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
Ivan Mahonin b53a5c
                    iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
Ivan Mahonin b53a5c
                    !(iter->flags & NK_WINDOW_HIDDEN))
Ivan Mahonin b53a5c
                    break;
Ivan Mahonin b53a5c
                if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
Ivan Mahonin b53a5c
                    NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
Ivan Mahonin b53a5c
                    iter->popup.win->bounds.x, iter->popup.win->bounds.y,
Ivan Mahonin b53a5c
                    iter->popup.win->bounds.w, iter->popup.win->bounds.h))
Ivan Mahonin b53a5c
                    break;
Ivan Mahonin b53a5c
                iter = iter->next;
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
        if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
Ivan Mahonin b53a5c
            win->flags |= (nk_flags)NK_WINDOW_ROM;
Ivan Mahonin b53a5c
            iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
Ivan Mahonin b53a5c
            ctx->active = iter;
Ivan Mahonin b53a5c
            if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
Ivan Mahonin b53a5c
                /* current window is active in that position so transfer to top
Ivan Mahonin b53a5c
                 * at the highest priority in stack */
Ivan Mahonin b53a5c
                nk_remove_window(ctx, iter);
Ivan Mahonin b53a5c
                nk_insert_window(ctx, iter, NK_INSERT_BACK);
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
        } else {
Ivan Mahonin b53a5c
            if (!iter && ctx->end != win) {
Ivan Mahonin b53a5c
                if (!(win->flags & NK_WINDOW_BACKGROUND)) {
Ivan Mahonin b53a5c
                    /* current window is active in that position so transfer to top
Ivan Mahonin b53a5c
                     * at the highest priority in stack */
Ivan Mahonin b53a5c
                    nk_remove_window(ctx, win);
Ivan Mahonin b53a5c
                    nk_insert_window(ctx, win, NK_INSERT_BACK);
Ivan Mahonin b53a5c
                }
Ivan Mahonin b53a5c
                win->flags &= ~(nk_flags)NK_WINDOW_ROM;
Ivan Mahonin b53a5c
                ctx->active = win;
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
            if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
Ivan Mahonin b53a5c
                win->flags |= NK_WINDOW_ROM;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    win->layout = (struct nk_panel*)nk_create_panel(ctx);
Ivan Mahonin b53a5c
    ctx->current = win;
Ivan Mahonin b53a5c
    ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
Ivan Mahonin b53a5c
    win->layout->offset_x = &win->scrollbar.x;
Ivan Mahonin b53a5c
    win->layout->offset_y = &win->scrollbar.y;
Ivan Mahonin b53a5c
    return ret;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_end(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_panel *layout;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current)
Ivan Mahonin b53a5c
        return;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    layout = ctx->current->layout;
Ivan Mahonin b53a5c
    if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
Ivan Mahonin b53a5c
        ctx->current = 0;
Ivan Mahonin b53a5c
        return;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    nk_panel_end(ctx);
Ivan Mahonin b53a5c
    nk_free_panel(ctx, ctx->current->layout);
Ivan Mahonin b53a5c
    ctx->current = 0;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API struct nk_rect
Ivan Mahonin b53a5c
nk_window_get_bounds(const struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
Ivan Mahonin b53a5c
    return ctx->current->bounds;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API struct nk_vec2
Ivan Mahonin b53a5c
nk_window_get_position(const struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current) return nk_vec2(0,0);
Ivan Mahonin b53a5c
    return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API struct nk_vec2
Ivan Mahonin b53a5c
nk_window_get_size(const struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current) return nk_vec2(0,0);
Ivan Mahonin b53a5c
    return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API float
Ivan Mahonin b53a5c
nk_window_get_width(const struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current) return 0;
Ivan Mahonin b53a5c
    return ctx->current->bounds.w;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API float
Ivan Mahonin b53a5c
nk_window_get_height(const struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current) return 0;
Ivan Mahonin b53a5c
    return ctx->current->bounds.h;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API struct nk_rect
Ivan Mahonin b53a5c
nk_window_get_content_region(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
Ivan Mahonin b53a5c
    return ctx->current->layout->clip;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API struct nk_vec2
Ivan Mahonin b53a5c
nk_window_get_content_region_min(struct nk_context *ctx)
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) return nk_vec2(0,0);
Ivan Mahonin b53a5c
    return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API struct nk_vec2
Ivan Mahonin b53a5c
nk_window_get_content_region_max(struct nk_context *ctx)
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) return nk_vec2(0,0);
Ivan Mahonin b53a5c
    return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
Ivan Mahonin b53a5c
        ctx->current->layout->clip.y + ctx->current->layout->clip.h);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API struct nk_vec2
Ivan Mahonin b53a5c
nk_window_get_content_region_size(struct nk_context *ctx)
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) return nk_vec2(0,0);
Ivan Mahonin b53a5c
    return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API struct nk_command_buffer*
Ivan Mahonin b53a5c
nk_window_get_canvas(struct nk_context *ctx)
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) return 0;
Ivan Mahonin b53a5c
    return &ctx->current->buffer;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API struct nk_panel*
Ivan Mahonin b53a5c
nk_window_get_panel(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current) return 0;
Ivan Mahonin b53a5c
    return ctx->current->layout;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current)
Ivan Mahonin b53a5c
        return ;
Ivan Mahonin b53a5c
    win = ctx->current;
Ivan Mahonin b53a5c
    if (offset_x)
Ivan Mahonin b53a5c
      *offset_x = win->scrollbar.x;
Ivan Mahonin b53a5c
    if (offset_y)
Ivan Mahonin b53a5c
      *offset_y = win->scrollbar.y;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_window_has_focus(const struct nk_context *ctx)
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) return 0;
Ivan Mahonin b53a5c
    return ctx->current == ctx->active;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_window_is_hovered(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current || (ctx->current->flags & NK_WINDOW_HIDDEN))
Ivan Mahonin b53a5c
        return 0;
Ivan Mahonin b53a5c
    else {
Ivan Mahonin b53a5c
        struct nk_rect actual_bounds = ctx->current->bounds;
Ivan Mahonin b53a5c
        if (ctx->begin->flags & NK_WINDOW_MINIMIZED) {
Ivan Mahonin b53a5c
            actual_bounds.h = ctx->current->layout->header_height;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
        return nk_input_is_mouse_hovering_rect(&ctx->input, actual_bounds);
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_window_is_any_hovered(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *iter;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return 0;
Ivan Mahonin b53a5c
    iter = ctx->begin;
Ivan Mahonin b53a5c
    while (iter) {
Ivan Mahonin b53a5c
        /* check if window is being hovered */
Ivan Mahonin b53a5c
        if(!(iter->flags & NK_WINDOW_HIDDEN)) {
Ivan Mahonin b53a5c
            /* check if window popup is being hovered */
Ivan Mahonin b53a5c
            if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
Ivan Mahonin b53a5c
                return 1;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
            if (iter->flags & NK_WINDOW_MINIMIZED) {
Ivan Mahonin b53a5c
                struct nk_rect header = iter->bounds;
Ivan Mahonin b53a5c
                header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
Ivan Mahonin b53a5c
                if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
Ivan Mahonin b53a5c
                    return 1;
Ivan Mahonin b53a5c
            } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
Ivan Mahonin b53a5c
                return 1;
Ivan Mahonin b53a5c
            }
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
        iter = iter->next;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    return 0;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_item_is_any_active(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int any_hovered = nk_window_is_any_hovered(ctx);
Ivan Mahonin b53a5c
    int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
Ivan Mahonin b53a5c
    return any_hovered || any_active;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_window_is_collapsed(struct nk_context *ctx, const char *name)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int title_len;
Ivan Mahonin b53a5c
    nk_hash title_hash;
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    title_len = (int)nk_strlen(name);
Ivan Mahonin b53a5c
    title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
Ivan Mahonin b53a5c
    win = nk_find_window(ctx, title_hash, name);
Ivan Mahonin b53a5c
    if (!win) return 0;
Ivan Mahonin b53a5c
    return win->flags & NK_WINDOW_MINIMIZED;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_window_is_closed(struct nk_context *ctx, const char *name)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int title_len;
Ivan Mahonin b53a5c
    nk_hash title_hash;
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return 1;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    title_len = (int)nk_strlen(name);
Ivan Mahonin b53a5c
    title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
Ivan Mahonin b53a5c
    win = nk_find_window(ctx, title_hash, name);
Ivan Mahonin b53a5c
    if (!win) return 1;
Ivan Mahonin b53a5c
    return (win->flags & NK_WINDOW_CLOSED);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_window_is_hidden(struct nk_context *ctx, const char *name)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int title_len;
Ivan Mahonin b53a5c
    nk_hash title_hash;
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return 1;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    title_len = (int)nk_strlen(name);
Ivan Mahonin b53a5c
    title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
Ivan Mahonin b53a5c
    win = nk_find_window(ctx, title_hash, name);
Ivan Mahonin b53a5c
    if (!win) return 1;
Ivan Mahonin b53a5c
    return (win->flags & NK_WINDOW_HIDDEN);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_window_is_active(struct nk_context *ctx, const char *name)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int title_len;
Ivan Mahonin b53a5c
    nk_hash title_hash;
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    title_len = (int)nk_strlen(name);
Ivan Mahonin b53a5c
    title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
Ivan Mahonin b53a5c
    win = nk_find_window(ctx, title_hash, name);
Ivan Mahonin b53a5c
    if (!win) return 0;
Ivan Mahonin b53a5c
    return win == ctx->active;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API struct nk_window*
Ivan Mahonin b53a5c
nk_window_find(struct nk_context *ctx, const char *name)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int title_len;
Ivan Mahonin b53a5c
    nk_hash title_hash;
Ivan Mahonin b53a5c
    title_len = (int)nk_strlen(name);
Ivan Mahonin b53a5c
    title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
Ivan Mahonin b53a5c
    return nk_find_window(ctx, title_hash, name);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_close(struct nk_context *ctx, const char *name)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return;
Ivan Mahonin b53a5c
    win = nk_window_find(ctx, name);
Ivan Mahonin b53a5c
    if (!win) return;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
Ivan Mahonin b53a5c
    if (ctx->current == win) return;
Ivan Mahonin b53a5c
    win->flags |= NK_WINDOW_HIDDEN;
Ivan Mahonin b53a5c
    win->flags |= NK_WINDOW_CLOSED;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_set_bounds(struct nk_context *ctx,
Ivan Mahonin b53a5c
    const char *name, struct nk_rect bounds)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return;
Ivan Mahonin b53a5c
    win = nk_window_find(ctx, name);
Ivan Mahonin b53a5c
    if (!win) return;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window");
Ivan Mahonin b53a5c
    win->bounds = bounds;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_set_position(struct nk_context *ctx,
Ivan Mahonin b53a5c
    const char *name, struct nk_vec2 pos)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *win = nk_window_find(ctx, name);
Ivan Mahonin b53a5c
    if (!win) return;
Ivan Mahonin b53a5c
    win->bounds.x = pos.x;
Ivan Mahonin b53a5c
    win->bounds.y = pos.y;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_set_size(struct nk_context *ctx,
Ivan Mahonin b53a5c
    const char *name, struct nk_vec2 size)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *win = nk_window_find(ctx, name);
Ivan Mahonin b53a5c
    if (!win) return;
Ivan Mahonin b53a5c
    win->bounds.w = size.x;
Ivan Mahonin b53a5c
    win->bounds.h = size.y;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current)
Ivan Mahonin b53a5c
        return;
Ivan Mahonin b53a5c
    win = ctx->current;
Ivan Mahonin b53a5c
    win->scrollbar.x = offset_x;
Ivan Mahonin b53a5c
    win->scrollbar.y = offset_y;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_collapse(struct nk_context *ctx, const char *name,
Ivan Mahonin b53a5c
                    enum nk_collapse_states c)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int title_len;
Ivan Mahonin b53a5c
    nk_hash title_hash;
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    title_len = (int)nk_strlen(name);
Ivan Mahonin b53a5c
    title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
Ivan Mahonin b53a5c
    win = nk_find_window(ctx, title_hash, name);
Ivan Mahonin b53a5c
    if (!win) return;
Ivan Mahonin b53a5c
    if (c == NK_MINIMIZED)
Ivan Mahonin b53a5c
        win->flags |= NK_WINDOW_MINIMIZED;
Ivan Mahonin b53a5c
    else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_collapse_if(struct nk_context *ctx, const char *name,
Ivan Mahonin b53a5c
    enum nk_collapse_states c, int cond)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx || !cond) return;
Ivan Mahonin b53a5c
    nk_window_collapse(ctx, name, c);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int title_len;
Ivan Mahonin b53a5c
    nk_hash title_hash;
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    title_len = (int)nk_strlen(name);
Ivan Mahonin b53a5c
    title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
Ivan Mahonin b53a5c
    win = nk_find_window(ctx, title_hash, name);
Ivan Mahonin b53a5c
    if (!win) return;
Ivan Mahonin b53a5c
    if (s == NK_HIDDEN) {
Ivan Mahonin b53a5c
        win->flags |= NK_WINDOW_HIDDEN;
Ivan Mahonin b53a5c
    } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_show_if(struct nk_context *ctx, const char *name,
Ivan Mahonin b53a5c
    enum nk_show_states s, int cond)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx || !cond) return;
Ivan Mahonin b53a5c
    nk_window_show(ctx, name, s);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_window_set_focus(struct nk_context *ctx, const char *name)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int title_len;
Ivan Mahonin b53a5c
    nk_hash title_hash;
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    title_len = (int)nk_strlen(name);
Ivan Mahonin b53a5c
    title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
Ivan Mahonin b53a5c
    win = nk_find_window(ctx, title_hash, name);
Ivan Mahonin b53a5c
    if (win && ctx->end != win) {
Ivan Mahonin b53a5c
        nk_remove_window(ctx, win);
Ivan Mahonin b53a5c
        nk_insert_window(ctx, win, NK_INSERT_BACK);
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    ctx->active = win;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_rule_horizontal(struct nk_context *ctx, struct nk_color color, nk_bool rounding)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_rect space;
Ivan Mahonin b53a5c
    enum nk_widget_layout_states state = nk_widget(&space, ctx);
Ivan Mahonin b53a5c
    struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
Ivan Mahonin b53a5c
    if (!state) return;
Ivan Mahonin b53a5c
    nk_fill_rect(canvas, space, rounding && space.h > 1.5f ? space.h / 2.0f : 0, color);
Ivan Mahonin b53a5c
}