Exemplo n.º 1
0
NK_LIB void
nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
    const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
    const struct nk_rect *scroll)
{
    const struct nk_style_item *background;
    const struct nk_style_item *cursor;

    /* select correct colors/images to draw */
    if (state & NK_WIDGET_STATE_ACTIVED) {
        background = &style->active;
        cursor = &style->cursor_active;
    } else if (state & NK_WIDGET_STATE_HOVER) {
        background = &style->hover;
        cursor = &style->cursor_hover;
    } else {
        background = &style->normal;
        cursor = &style->cursor_normal;
    }

    /* draw background */
    if (background->type == NK_STYLE_ITEM_COLOR) {
        nk_fill_rect(out, *bounds, style->rounding, background->data.color);
        nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
    } else {
        nk_draw_image(out, *bounds, &background->data.image, nk_white);
    }

    /* draw cursor */
    if (cursor->type == NK_STYLE_ITEM_COLOR) {
        nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
        nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
    } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
}
/* ===============================================================
 *
 *                          CUSTOM WIDGET
 *
 * ===============================================================*/
static int
ui_piemenu(struct nk_context *ctx, struct nk_vec2 pos, float radius,
            struct nk_image *icons, int item_count)
{
    int ret = -1;
    struct nk_rect total_space;
    struct nk_rect bounds;
    int active_item = 0;

    /* pie menu popup */
    struct nk_color border = ctx->style.window.border_color;
    struct nk_style_item background = ctx->style.window.fixed_background;
    ctx->style.window.fixed_background = nk_style_item_hide();
    ctx->style.window.border_color = nk_rgba(0,0,0,0);

    total_space  = nk_window_get_content_region(ctx);
    ctx->style.window.spacing = nk_vec2(0,0);
    ctx->style.window.padding = nk_vec2(0,0);

    if (nk_popup_begin(ctx, NK_POPUP_STATIC, "piemenu", NK_WINDOW_NO_SCROLLBAR,
        nk_rect(pos.x - total_space.x - radius, pos.y - radius - total_space.y,
        2*radius,2*radius)))
    {
        int i = 0;
        struct nk_command_buffer* out = nk_window_get_canvas(ctx);
        const struct nk_input *in = &ctx->input;

        total_space = nk_window_get_content_region(ctx);
        ctx->style.window.spacing = nk_vec2(4,4);
        ctx->style.window.padding = nk_vec2(8,8);
        nk_layout_row_dynamic(ctx, total_space.h, 1);
        nk_widget(&bounds, ctx);

        /* outer circle */
        nk_fill_circle(out, bounds, nk_rgb(50,50,50));
        {
            /* circle buttons */
            float step = (2 * 3.141592654f) / (float)(MAX(1,item_count));
            float a_min = 0; float a_max = step;

            struct nk_vec2 center = nk_vec2(bounds.x + bounds.w / 2.0f, bounds.y + bounds.h / 2.0f);
            struct nk_vec2 drag = nk_vec2(in->mouse.pos.x - center.x, in->mouse.pos.y - center.y);
            float angle = (float)atan2(drag.y, drag.x);
            if (angle < -0.0f) angle += 2.0f * 3.141592654f;
            active_item = (int)(angle/step);

            for (i = 0; i < item_count; ++i) {
                struct nk_rect content;
                float rx, ry, dx, dy, a;
                nk_fill_arc(out, center.x, center.y, (bounds.w/2.0f),
                    a_min, a_max, (active_item == i) ? nk_rgb(45,100,255): nk_rgb(60,60,60));

                /* separator line */
                rx = bounds.w/2.0f; ry = 0;
                dx = rx * (float)cos(a_min) - ry * (float)sin(a_min);
                dy = rx * (float)sin(a_min) + ry * (float)cos(a_min);
                nk_stroke_line(out, center.x, center.y,
                    center.x + dx, center.y + dy, 1.0f, nk_rgb(50,50,50));

                /* button content */
                a = a_min + (a_max - a_min)/2.0f;
                rx = bounds.w/2.5f; ry = 0;
                content.w = 30; content.h = 30;
                content.x = center.x + ((rx * (float)cos(a) - ry * (float)sin(a)) - content.w/2.0f);
                content.y = center.y + (rx * (float)sin(a) + ry * (float)cos(a) - content.h/2.0f);
                nk_draw_image(out, content, &icons[i], nk_rgb(255,255,255));
                a_min = a_max; a_max += step;
            }
        }
        {
            /* inner circle */
            struct nk_rect inner;
            inner.x = bounds.x + bounds.w/2 - bounds.w/4;
            inner.y = bounds.y + bounds.h/2 - bounds.h/4;
            inner.w = bounds.w/2; inner.h = bounds.h/2;
            nk_fill_circle(out, inner, nk_rgb(45,45,45));

            /* active icon content */
            bounds.w = inner.w / 2.0f;
            bounds.h = inner.h / 2.0f;
            bounds.x = inner.x + inner.w/2 - bounds.w/2;
            bounds.y = inner.y + inner.h/2 - bounds.h/2;
            nk_draw_image(out, bounds, &icons[active_item], nk_rgb(255,255,255));
        }
        nk_layout_space_end(ctx);
        if (!nk_input_is_mouse_down(&ctx->input, NK_BUTTON_RIGHT)) {
            nk_popup_close(ctx);
            ret = active_item;
        }
    } else ret = -2;
    ctx->style.window.spacing = nk_vec2(4,4);
    ctx->style.window.padding = nk_vec2(8,8);
    nk_popup_end(ctx);

    ctx->style.window.fixed_background = background;
    ctx->style.window.border_color = border;
    return ret;
}
Exemplo n.º 3
0
int main(int argc, char *argv[]) {

	/* register callbacks */
		mpx_register_vc(&this_vc);
  
    /* GUI */
    static struct nk_context ctx;
    static struct nk_canvas canvas;
    

    uint32_t width = 0, 
        height = 0;

    static struct nk_user_font font;
    font.userdata.ptr = &width;
    font.height = font_vga_8x16.height;
    font.width = your_text_width_calculation;
    nk_init_default(&ctx, &font);
    
    width = this_vc.fb->var.xres;
    height = this_vc.fb->var.yres;
    
    /* Draw */
    while (1) 
    {
        /* what to draw */
        canvas_begin(&ctx, &canvas, 0, 0, 0, width, height, nk_rgb(100,100,100));
        {         
            canvas.painter->use_clipping = NK_CLIPPING_OFF;  

            nk_fill_rect(canvas.painter, nk_rect(15,15,140,140), 5, nk_rgb(247, 230, 154));
            nk_fill_rect(canvas.painter, nk_rect(20,20,135,135), 5, nk_rgb(188, 174, 118));
            nk_draw_text(canvas.painter, nk_rect(30, 30, 100, 20), "Text to draw", 12, &font, nk_rgb(188,174,118), nk_rgb(0,0,0));
            nk_fill_rect(canvas.painter, nk_rect(160,20,70,70), 0, nk_rgb(0,0,255));
            nk_fill_circle(canvas.painter, nk_rect(20,160,60,60), nk_rgb(255,0,0));
            nk_fill_triangle(canvas.painter, 160, 160, 230, 160, 195, 220, nk_rgb(0,255,0));
            nk_fill_arc(canvas.painter, 195, 120, 30, 0, 3.141592654f * 3.0f / 4.0f, nk_rgb(255,255,0));
            nk_stroke_line(canvas.painter, 15, 10, 100, 10, 2.0f, nk_rgb(189,45,75));
            nk_stroke_rect(canvas.painter, nk_rect(235, 20, 70, 70), 10, 3, nk_rgb(0,0,255));
            nk_stroke_curve(canvas.painter, 235, 130, 252, 170, 288, 80, 305, 130, 1, nk_rgb(0,150,220));
            nk_stroke_triangle(canvas.painter, 235, 160, 305, 160, 270, 220, 10, nk_rgb(255,0,143));
            nk_stroke_circle(canvas.painter, nk_rect(90, 160, 60, 60), 2, nk_rgb(0,255,120));
            

            /* load some image */
            // uint32_t im_w, im_h, im_format;
            // images[0] = stbi_load("SPBGU_logo.png", &im_w, &im_h, &im_format, 0);
            // if (images[0] == NULL)
            //     printf("\nstbi_load doesn't work. :(\n");
            // else {
            //     printf("\nLoaded image: id = %i   width = %i\theight = %i\tformat = %i", (int)*images[0], im_w, im_h, im_format);

                struct nk_image im;
                im.handle.ptr = "SPBGU_logo.png";
                im.handle.id = 0;
                im.w = 0;
                im.h = 0;
                im.region[0] = 0;
                im.region[1] = 0;
                im.region[2] = 267;
                im.region[3] = 333;
                
                nk_draw_image(canvas.painter, nk_rect(320, 10, 130, 150), &im, nk_rgb(100, 0, 0));
           // }

           // stbi_image_free(images[0]);            
        }
        canvas_end(&ctx, &canvas);

         /* Draw each element */
         draw(&this_vc, &ctx, width, height);
    }
    nk_free(&ctx);

    printf("\nEnd of program.\nIf you see it then something goes wrong.\n");
    return 0;
}
Exemplo n.º 4
0
    CharacterDialoguePopup::UpdateResult CharacterDialoguePopup::update(struct nk_context* ctx)
    {
        auto renderer = FARender::Renderer::get();

        auto boxTex = renderer->loadImage(this->mWide ? "data/textbox.cel" : "data/textbox2.cel");
        int32_t screenW, screenH;
        renderer->getWindowDimensions(screenW, screenH);

        nk_flags flags = NK_WINDOW_NO_SCROLLBAR;

        auto dialogRectangle =
            nk_rect(screenW / 2.0f - (boxTex->getWidth() / 2.0f), screenH / 2.0f - (boxTex->getHeight() / 2.0f), boxTex->getWidth(), boxTex->getHeight());

        UpdateResult result = UpdateResult::DoNothing;

        mGuiManager.nk_fa_begin_image_window(ctx,
                                             "dialog",
                                             dialogRectangle,
                                             flags,
                                             boxTex->getNkImage(),
                                             [&]() {
                                                 // apply black checkerboard in background
                                                 {
                                                     auto blackTex = renderer->loadImage("resources/black.png");
                                                     auto cbRect =
                                                         nk_rect(dialogRectangle.x + 3, dialogRectangle.y + 3, dialogRectangle.w - 6, dialogRectangle.h - 6);

                                                     ScopedApplyEffect effect(ctx, EffectType::checkerboarded);
                                                     auto nkImage =
                                                         nk_subimage_handle(blackTex->getNkImage().handle, blackTex->getWidth(), blackTex->getHeight(), cbRect);
                                                     nk_draw_image(nk_window_get_canvas(ctx), cbRect, &nkImage, nk_rgb(0, 0, 0));
                                                 }

                                                 nk_layout_row_dynamic(ctx, 30, 1);

                                                 DialogData data = getDialogData();

                                                 for (const auto& line : data.introduction)
                                                     GuiManager::smallText(ctx, line.c_str());

                                                 // fill the rest of the window
                                                 struct nk_rect bounds = nk_widget_bounds(ctx);
                                                 struct nk_rect panelSize = nk_window_get_bounds(ctx);
                                                 float contentHeight = panelSize.h + panelSize.y - bounds.y;
                                                 nk_layout_row_dynamic(ctx, contentHeight, 1);

                                                 Misc::ScopedSetter<nk_style> styleSetter(ctx->style);

                                                 // setup style for scrollbar
                                                 {
                                                     constexpr int32_t scrollUpButtonIndex = 9;
                                                     constexpr int32_t scrollDownButtonIndex = 8;
                                                     constexpr int32_t scrollbarBackgroundIndex = 13;

                                                     // TODO: the "cursor" of the scrollbar is still the default nuklear look, which should change

                                                     auto sliderImg = renderer->loadImage("data/textslid.cel");

                                                     // TODO: this image should repeat, not stretch
                                                     ctx->style.scrollv.normal = nk_style_item_image(sliderImg->getNkImage(scrollbarBackgroundIndex));

                                                     ctx->style.scrollv.active = ctx->style.scrollv.normal;
                                                     ctx->style.scrollv.hover = ctx->style.scrollv.normal;
                                                     ctx->style.scrollv.cursor_active = ctx->style.scrollv.cursor_normal;
                                                     ctx->style.scrollv.cursor_hover = ctx->style.scrollv.cursor_normal;

                                                     ctx->style.scrollv.show_buttons = true;

                                                     ctx->style.scrollv.dec_button.normal = nk_style_item_image(sliderImg->getNkImage(scrollUpButtonIndex));
                                                     ctx->style.scrollv.dec_symbol = NK_SYMBOL_NONE;
                                                     ctx->style.scrollv.inc_button.normal = nk_style_item_image(sliderImg->getNkImage(scrollDownButtonIndex));
                                                     ctx->style.scrollv.inc_symbol = NK_SYMBOL_NONE;

                                                     ctx->style.scrollv.dec_button.active = ctx->style.scrollv.dec_button.normal;
                                                     ctx->style.scrollv.dec_button.hover = ctx->style.scrollv.dec_button.normal;

                                                     ctx->style.scrollv.inc_button.active = ctx->style.scrollv.inc_button.normal;
                                                     ctx->style.scrollv.inc_button.hover = ctx->style.scrollv.inc_button.normal;

                                                     ctx->style.window.group_padding = nk_vec2(10, 10);

                                                     ctx->style.window.scrollbar_size = nk_vec2(sliderImg->getWidth(), 0);
                                                 }

                                                 nk_group_scrolled_begin(ctx, &mScroll, "dialog_main", 0);
                                                 {
                                                     if (mDialogMenu.update(ctx, data.dialogOptions, mScroll) == MouseAndClickMenu::Result::Activated)
                                                         result = data.dialogActions[mDialogMenu.getSelectedIndex()]();
                                                 }
                                                 nk_group_scrolled_end(ctx);

                                             },
                                             true);

        return result;
    }
Exemplo n.º 5
0
int main(int argc, char** argv)
{
    if (argc > 2)
        message_and_abort_fmt("Usage: %s [filename]", argv[0]);

    Render::RenderSettings renderSettings;
    renderSettings.windowWidth = 800;
    renderSettings.windowHeight = 600;
    renderSettings.fullscreen = false;

    NuklearMisc::StandaloneGuiHandler guiHandler("Cel Viewer", renderSettings);

    nk_context* ctx = guiHandler.getNuklearContext();

    Settings::Settings settings;
    settings.loadFromFile("resources/celview.ini");

    bool faioInitDone = false;
    std::string listFile = settings.get<std::string>("celview", "listFile", "Diablo I.txt");
    std::string mpqFile = settings.get<std::string>("celview", "mpqFile", "DIABDAT.MPQ");

    std::vector<std::string> celFiles;

    std::string selectedImage = "";
    std::unique_ptr<NuklearMisc::GuiSprite> image;

    std::unique_ptr<NuklearMisc::GuiSprite> nextImage;

    int animate = false;
    int32_t frame = 0;

    float rowHeight = 30;
    auto lastFrame = std::chrono::high_resolution_clock::now();

    bool quit = false;
    while (!quit)
    {
        auto now = std::chrono::high_resolution_clock::now();

        if (nextImage)
            image = std::unique_ptr<NuklearMisc::GuiSprite>(nextImage.release());

        renderSettings = Render::getWindowSize();

        if (nk_begin(ctx, "main_window", nk_rect(0, 0, renderSettings.windowWidth, renderSettings.windowHeight), NK_WINDOW_NO_SCROLLBAR))
        {
            struct nk_rect bounds = nk_window_get_content_region(ctx);

            nk_layout_row_dynamic(ctx, bounds.h, 2);

            if (nk_group_begin(ctx, "image", 0))
            {
                nk_layout_row_dynamic(ctx, rowHeight, 1);

                std::string label = selectedImage;

                if (selectedImage == "")
                    label = "No image selected";

                nk_label(ctx, label.c_str(), NK_TEXT_CENTERED);

                nk_checkbox_label(ctx, "Animate", &animate);

                if (image)
                {
                    nk_label(ctx, (boost::format("Number of Frames: %1%") % image.get()->getSprite()->size()).str().c_str(), NK_TEXT_LEFT);
                    nk_label(ctx, (boost::format("Width: %1%") % image->getSprite()->getWidth()).str().c_str(), NK_TEXT_LEFT);
                    nk_label(ctx, (boost::format("Height: %1%") % image->getSprite()->getHeight()).str().c_str(), NK_TEXT_LEFT);
                    frame = nk_propertyi(ctx, "Frame", 0, frame, image->getSprite()->size(), 1, 0.2f);

                    if (nk_button_label(ctx, "save as png"))
                    {
                        nfdchar_t* outPath = NULL;
                        nfdresult_t result = NFD_SaveDialog("png", NULL, &outPath);
                        if (result == NFD_OKAY)
                        {
                            Render::SpriteGroup::toPng(selectedImage, outPath);
                            free(outPath);
                        }
                    }

                    if (nk_button_label(ctx, "save as gif"))
                    {
                        nfdchar_t* outPath = NULL;
                        nfdresult_t result = NFD_SaveDialog("gif", NULL, &outPath);
                        if (result == NFD_OKAY)
                        {
                            Render::SpriteGroup::toGif(selectedImage, outPath);
                            free(outPath);
                        }
                    }

                    auto msSinceLastFrame = std::chrono::duration_cast<std::chrono::milliseconds>(now - lastFrame).count();
                    if (animate && msSinceLastFrame > 100)
                    {
                        lastFrame = now;
                        frame++;
                    }

                    if (frame >= (int32_t)image.get()->getSprite()->size())
                        frame = 0;

                    Render::Sprite sprite = image.get()->getSprite()->operator[](frame);

                    int32_t w, h;
                    Render::spriteSize(sprite, w, h);

                    nk_layout_space_begin(ctx, NK_STATIC, h, 1);
                    {
                        nk_layout_space_push(ctx, nk_rect(0, 0, w, h));

                        auto canvas = nk_window_get_canvas(ctx);

                        struct nk_rect imageRect;
                        nk_widget(&imageRect, ctx);
                        nk_fill_rect(canvas, imageRect, 0.0, nk_rgb(0, 255, 0));

                        auto img = image.get()->getNkImage(frame);
                        nk_draw_image(canvas, imageRect, &img, nk_rgb(255, 255, 255));
                    }
                    nk_layout_space_end(ctx);
                }

                nk_group_end(ctx);
            }

            if (nk_group_begin(ctx, "file list", 0))
            {
                if (!faioInitDone)
                {
                    nk_layout_row_dynamic(ctx, rowHeight * 2, 1);

                    NuklearMisc::nk_file_pick(ctx, "DIABDAT.MPQ", mpqFile, "mpq,MPQ", rowHeight);
                    NuklearMisc::nk_file_pick(ctx, "Diablo listfile", listFile, "txt", rowHeight);

                    if (nk_button_label(ctx, "load"))
                    {
                        FAIO::init(mpqFile, listFile);
                        celFiles = FAIO::listMpqFiles("*.cel");
                        auto tmp = FAIO::listMpqFiles("*.cl2");
                        celFiles.insert(celFiles.end(), tmp.begin(), tmp.end());

                        std::sort(celFiles.begin(), celFiles.end());

                        settings.set<std::string>("celview", "listFile", listFile);
                        settings.set<std::string>("celview", "mpqFile", mpqFile);
                        settings.save();

                        faioInitDone = true;

                        if (argc > 1)
                        {
                            selectedImage = argv[1];
                            frame = 0;
                            nextImage = std::unique_ptr<NuklearMisc::GuiSprite>(guiHandler.getSprite(new Render::SpriteGroup(selectedImage)));
                        }
                    }
                }

                nk_layout_row_dynamic(ctx, rowHeight, 1);

                for (size_t i = 0; i < celFiles.size(); i++)
                {
                    auto buttonStyle = ctx->style.button;

                    if (selectedImage == celFiles[i])
                        buttonStyle.normal = buttonStyle.hover;

                    if (nk_button_label_styled(ctx, &buttonStyle, celFiles[i].c_str()))
                    {
                        selectedImage = celFiles[i];
                        frame = 0;
                        nextImage = std::unique_ptr<NuklearMisc::GuiSprite>(guiHandler.getSprite(new Render::SpriteGroup(selectedImage)));
                    }
                }

                nk_group_end(ctx);
            }
        }
        nk_end(ctx);

        quit = guiHandler.update();
    }

    FAIO::quit();

    return 0;
}
Exemplo n.º 6
0
NK_API int
nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
    struct nk_image img, struct nk_vec2 size)
{
    struct nk_window *win;
    struct nk_style *style;
    struct nk_input *in;

    struct nk_rect header;
    int is_clicked = nk_false;
    enum nk_widget_layout_states s;
    const struct nk_style_item *background;
    struct nk_text text;

    NK_ASSERT(ctx);
    NK_ASSERT(ctx->current);
    NK_ASSERT(ctx->current->layout);
    if (!ctx || !ctx->current || !ctx->current->layout)
        return 0;

    win = ctx->current;
    style = &ctx->style;
    s = nk_widget(&header, ctx);
    if (!s) return 0;

    in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
    if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
        is_clicked = nk_true;

    /* draw combo box header background and border */
    if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
        background = &style->combo.active;
        text.text = style->combo.label_active;
    } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
        background = &style->combo.hover;
        text.text = style->combo.label_hover;
    } else {
        background = &style->combo.normal;
        text.text = style->combo.label_normal;
    }
    if (background->type == NK_STYLE_ITEM_IMAGE) {
        text.background = nk_rgba(0,0,0,0);
        nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
    } else {
        text.background = background->data.color;
        nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
        nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
    }
    {
        struct nk_rect content;
        struct nk_rect button;
        struct nk_rect label;
        struct nk_rect image;

        enum nk_symbol_type sym;
        if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
            sym = style->combo.sym_hover;
        else if (is_clicked)
            sym = style->combo.sym_active;
        else sym = style->combo.sym_normal;

        /* calculate button */
        button.w = header.h - 2 * style->combo.button_padding.y;
        button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
        button.y = header.y + style->combo.button_padding.y;
        button.h = button.w;

        content.x = button.x + style->combo.button.padding.x;
        content.y = button.y + style->combo.button.padding.y;
        content.w = button.w - 2 * style->combo.button.padding.x;
        content.h = button.h - 2 * style->combo.button.padding.y;
        nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
            &ctx->style.combo.button, sym, style->font);

        /* draw image */
        image.x = header.x + style->combo.content_padding.x;
        image.y = header.y + style->combo.content_padding.y;
        image.h = header.h - 2 * style->combo.content_padding.y;
        image.w = image.h;
        nk_draw_image(&win->buffer, image, &img, nk_white);

        /* draw label */
        text.padding = nk_vec2(0,0);
        label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
        label.y = header.y + style->combo.content_padding.y;
        label.w = (button.x - style->combo.content_padding.x) - label.x;
        label.h = header.h - 2 * style->combo.content_padding.y;
        nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
    }
    return nk_combo_begin(ctx, win, size, is_clicked, header);
}
Exemplo n.º 7
0
NK_API int
nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
{
    struct nk_window *win;
    struct nk_style *style;
    const struct nk_input *in;

    struct nk_rect header;
    int is_clicked = nk_false;
    enum nk_widget_layout_states s;
    const struct nk_style_item *background;

    NK_ASSERT(ctx);
    NK_ASSERT(ctx->current);
    NK_ASSERT(ctx->current->layout);
    if (!ctx || !ctx->current || !ctx->current->layout)
        return 0;

    win = ctx->current;
    style = &ctx->style;
    s = nk_widget(&header, ctx);
    if (s == NK_WIDGET_INVALID)
        return 0;

    in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
    if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
        is_clicked = nk_true;

    /* draw combo box header background and border */
    if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
        background = &style->combo.active;
    else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
        background = &style->combo.hover;
    else background = &style->combo.normal;

    if (background->type == NK_STYLE_ITEM_IMAGE) {
        nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
    } else {
        nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
        nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
    }
    {
        struct nk_rect bounds = {0,0,0,0};
        struct nk_rect content;
        struct nk_rect button;

        enum nk_symbol_type sym;
        if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
            sym = style->combo.sym_hover;
        else if (is_clicked)
            sym = style->combo.sym_active;
        else sym = style->combo.sym_normal;

        /* calculate button */
        button.w = header.h - 2 * style->combo.button_padding.y;
        button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
        button.y = header.y + style->combo.button_padding.y;
        button.h = button.w;

        content.x = button.x + style->combo.button.padding.x;
        content.y = button.y + style->combo.button.padding.y;
        content.w = button.w - 2 * style->combo.button.padding.x;
        content.h = button.h - 2 * style->combo.button.padding.y;

        /* draw image */
        bounds.h = header.h - 2 * style->combo.content_padding.y;
        bounds.y = header.y + style->combo.content_padding.y;
        bounds.x = header.x + style->combo.content_padding.x;
        bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
        nk_draw_image(&win->buffer, bounds, &img, nk_white);

        /* draw open/close button */
        nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
            &ctx->style.combo.button, sym, style->font);
    }
    return nk_combo_begin(ctx, win, size, is_clicked, header);
}