vurtun / nuklear

A single-header ANSI C gui library
13.7k stars 1.11k forks source link

How to close a popup externally without leaving parents stuck? #850

Closed rswinkle closed 5 years ago

rswinkle commented 5 years ago

So I have a popup up setup like you have in overview.c

if (show_about) {
    struct nk_rect s = { 100, 100, 400, 400 };
    if (nk_popup_begin(ctx, NK_POPUP_STATIC, "About", NK_WINDOW_CLOSABLE, s)) {
        nk_label(ctx, "By rswinkle", NK_TEXT_LEFT);
        nk_popup_end(ctx);
    } show_about = nk_false;
}

The problem is I want to be able to have it close when the user hits ESCAPE, (or if I added an OK button, when the user hits ENTER). If I clear show_about on an ESCAPE key event, the popup obviously disappears but the rest of the GUI no longer accepts input because they're still invalidated from the last call to nk_popup_begin(). Calling nk_popup_close() externally doesn't help and calling nk_popup_end() segfaults because !ctx->current.

The only thing that "fixes" the problem is if another popup (in my case a button in the same window that had a tooltip) triggers and then everything responds again.

I've looked at the code and it seems like I could extract the important cleanup bits into a new function that you'd have to call inside the parent window before the popup. So maybe I'd have a new cleanup flag or make show_about have 3 states, yes, no, and cleanup or something like that.

Am I missing some existing obvious way to do this or am I on the right track that some minor changes to nuklear would be required?

Thanks for such a great library.

dumblob commented 5 years ago

Basically you're right, that popups are limited in several ways (and you came across one of them). Basically anything in Nuklear which overlaps something else is not first class citizen as Nuklear wasn't initially designed to support overlapping stuff. So I'm afraid you really need to track the state yourself and then do some Nuklear-fu to change the state.

Depending on your solution we might or might not merge the potential pull request (e.g. if it's a backward-compatible change to nuklear.h which is also extensible to potential other similar issues, then there is high chance of merging; or if you won't change nuklear.h at all and just update the demos and examples with your Nuklear-fu, then it's nearly 100% certain we'll merge it as demos and examples are community contributions and we're not maintaining them strictly speaking even though we actually are :wink:).

Either way though it would be nice to describe your solution here.

rswinkle commented 5 years ago

Thanks for the quick response. Ok I'll probably look into it but since I'm not actually done with the rest of my program's GUI and it's not really a deal breaker, it might be a week or two.

I did have another similar but unrelated question. Is there a better way to implement delayed tooltips than to just have a static hovered frame counter and an "is any tooltip thing hovered" flag that resets the counter to 0 if nothing was hovered for the current frame? I haven't looked into this at all as far a nuklear internals go since the external hack is simple and works well enough but I was just curious.

Lastly, for the app I'm working on I grabbed your old SDL1.2 gfx backend and updated it for SDL2 so I could use nuklear without having to convert to using OpenGL. I know there's another pull request/issue for an sdl_native backend but it seems stalled/buggy and it uses SDL_ttf which I wouldn't want since nuklear already has stb_truetype built in.

So mine works, both for my program and the demo programs as far as I can tell. The only issue is, like the old backend, I'm just using the SDL_gfx built in 8 px ascii font and having SDL scale the GUI as needed. Long term it should support the font_atlas stuff but I can't even get that stuff to run for the sdl_opengl3 demo (just crashes when I uncomment any font loading stuff) so I clearly don't grok it.

I can/will eventually submit a pull request but I guess consider this a very low key RFC?

dumblob commented 5 years ago

I can/will eventually submit a pull request but I guess consider this a very low key RFC?

You definitely can - every new backend is welcome. But please name it with a sane name to distinguish it from the SDL 1.2 and from the existing "pending" pull request.

rswinkle commented 5 years ago

I haven't ruled out looking into this more and adding this functionality but I went ahead and changed my popups to separate windows which they probably deserved to be anyway. There's really no downside to doing that, and it gives far more flexibility/power so it's probably generally the right decision even if I could externally close popups already.

So this comment is for anyone who finds this issue in the meantime, consider using separate windows. Combined with simple boolean flags, it's easy enough to not show other windows while any given "popup" is active and you can modify the flags in response to external input events.

dumblob commented 5 years ago

Thanks @rswinkle for the solution. Feel free to post some links to the source code if possible and close this issue :wink:.

rswinkle commented 5 years ago

Did you mean to my source code?

Well it's still a work in progress (but isn't software always) but you can see what I'm talking about here and modifying the flags to "exit" the popups through external events here.

If you meant something in this repo, I'm don't think there is an example of using external events to modify windows. The closest thing I can think of is here but that's showing and hiding an internal menu and only in response to actual GUI events. It is the same concept though.

dumblob commented 5 years ago

but isn't software always

Yep, that's both the nice and bad side of the matter :wink:.

If you meant something in this repo...

Not necessarily - just to have something to point others at.