-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementing a message box #15
Comments
Hi! To avoid painting children widgets outside their parent geometry (clipping them), try using Your second alternative (a new window and renderer) may work for Desktop, but surely wouldn't for mobile. Also, I think it is overkill just for an editbox modal. I also agree that KiWi needs convenience functions for message boxes and prompts, that's a feature to keep in the radar. |
Using The only reason I suggested the second approach is because it allows you to spawn a new OS-specific window (as opposed to a widget drawn in KiWi) and would allow for making it modal by nesting SDL event loops (or non-modal by doing event-processing and rendering sequentially in one event loop). |
Program: #include "KW_gui.h"
#include "KW_frame.h"
#include "KW_label.h"
#include "KW_button.h"
#include "KW_renderdriver_sdl2.h"
KW_Widget * messagebox;
void ok_clicked(KW_Widget * widget, int button) {
KW_DestroyWidget(messagebox, KW_TRUE);
}
int main(int argc, char ** argv) {
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Renderer * renderer;
SDL_Window * window;
SDL_CreateWindowAndRenderer(320, 240, 0, &window, &renderer);
SDL_SetRenderDrawColor(renderer, 200, 150, 100, 1); /* pretty background */
KW_RenderDriver * driver = KW_CreateSDL2RenderDriver(renderer, window);
KW_Surface * set = KW_LoadSurface(driver, "tileset.png");
KW_GUI * gui = KW_Init(driver, set);
KW_Font * font = KW_LoadFont(driver, "Fontin-Regular.ttf", 12);
KW_SetFont(gui, font);
KW_Rect geometry = { x: 0, y: 0, w: 320, h: 240 };
KW_Widget * frame = KW_CreateFrame(gui, NULL, &geometry);
KW_Rect messagebox_geometry = { x: 0, y: 0, w: 192, h: 120 };
KW_RectCenterInParent(&geometry, &messagebox_geometry);
messagebox = KW_CreateFrame(gui, frame, &messagebox_geometry);
KW_Rect messagebox_label_geometry = { x: 0, y: 0, w: 192, h: 48 };
KW_Widget * messagebox_label = KW_CreateLabel(gui, messagebox, "Hello World!", &messagebox_label_geometry);
KW_Rect messagebox_button_geometry = { x: 120, y: 84, w: 48, h: 24 };
KW_Widget * messagebox_button = KW_CreateButton(gui, messagebox, "OK", &messagebox_button_geometry);
KW_AddWidgetMouseUpHandler(messagebox_button, ok_clicked);
while (!SDL_QuitRequested()) {
SDL_RenderClear(renderer);
KW_ProcessEvents(gui);
KW_Paint(gui);
SDL_Delay(1);
SDL_RenderPresent(renderer);
}
KW_Quit(gui);
KW_ReleaseSurface(driver, set);
KW_ReleaseFont(driver, font);
KW_ReleaseRenderDriver(driver);
SDL_Quit();
return 0;
} gdb interaction:
|
Ah. I'll look into these problems. |
I've implemented I'll look into the destroywidget bug later. From a quick look at your trace, I can tell the widget event handlers are not being removed after that widget is destroyed, there's no code to do that. |
Cool, that works! Somehow it's still feeling off for me, probably because this message box looks very much unlike anything else I've seen and is transparent. Code: #include "KW_gui.h"
#include "KW_frame.h"
#include "KW_label.h"
#include "KW_button.h"
#include "KW_renderdriver_sdl2.h"
KW_Widget * messagebox;
void ok_clicked(KW_Widget * widget, int button) {
KW_HideWidget(messagebox);
}
void greet_clicked(KW_Widget * widget, int button) {
KW_ShowWidget(messagebox);
}
KW_bool quit = KW_FALSE;
void quit_clicked(KW_Widget * widget, int button) {
quit = KW_TRUE;
}
int main(int argc, char ** argv) {
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Renderer * renderer;
SDL_Window * window;
SDL_CreateWindowAndRenderer(320, 240, 0, &window, &renderer);
SDL_SetRenderDrawColor(renderer, 200, 150, 100, 1); /* pretty background */
KW_RenderDriver * driver = KW_CreateSDL2RenderDriver(renderer, window);
KW_Surface * set = KW_LoadSurface(driver, "tileset.png");
KW_GUI * gui = KW_Init(driver, set);
KW_Font * font = KW_LoadFont(driver, "Fontin-Regular.ttf", 12);
KW_SetFont(gui, font);
KW_Rect geometry = { x: 0, y: 0, w: 320, h: 240 };
KW_Widget * frame = KW_CreateFrame(gui, NULL, &geometry);
KW_Rect greet_button_geometry = { x: 48, y: 144, w: 96, h: 48 };
KW_Widget * greet_button = KW_CreateButton(gui, frame, "Click Me!", &greet_button_geometry);
KW_AddWidgetMouseUpHandler(greet_button, greet_clicked);
KW_Rect quit_button_geometry = { x: 192, y: 144, w: 96, h: 48 };
KW_Widget * quit_button = KW_CreateButton(gui, frame, "Quit", &quit_button_geometry);
KW_AddWidgetMouseUpHandler(quit_button, quit_clicked);
KW_Rect messagebox_geometry = { x: 0, y: 0, w: 192, h: 120 };
KW_RectCenterInParent(&geometry, &messagebox_geometry);
messagebox = KW_CreateFrame(gui, frame, &messagebox_geometry);
KW_Rect messagebox_label_geometry = { x: 0, y: 0, w: 192, h: 48 };
KW_Widget * messagebox_label = KW_CreateLabel(gui, messagebox, "Hello World!", &messagebox_label_geometry);
KW_Rect messagebox_button_geometry = { x: 120, y: 84, w: 48, h: 24 };
KW_Widget * messagebox_button = KW_CreateButton(gui, messagebox, "OK", &messagebox_button_geometry);
KW_AddWidgetMouseUpHandler(messagebox_button, ok_clicked);
KW_HideWidget(messagebox);
while (!SDL_QuitRequested() && !quit) {
SDL_RenderClear(renderer);
KW_ProcessEvents(gui);
KW_Paint(gui);
SDL_Delay(1);
SDL_RenderPresent(renderer);
}
KW_Quit(gui);
KW_ReleaseSurface(driver, set);
KW_ReleaseFont(driver, font);
KW_ReleaseRenderDriver(driver);
SDL_Quit();
return 0;
} |
That helps, but if I were to use that tileset with the styleswitcher example, frames would look pretty weird as a frame is used there like a pane widget which must look flat to be used as visual groups. Perhaps it's time for extending the tileset for panes? Other problems are that the message box is partially covering the other buttons (something that wouldn't happen if one had a much larger "screen") and that the message box isn't modal at all, you can for instance still click the quit button partially covered by it. Is it possible to block all widgets except the ones belonging to the message box? |
It appears so. Maybe we could actually add styles for the frame, like raised, flat and sunken, and extend their tileset. For blocking events, I'd suggest you put everything you want to block in an empty, fake widget and then block inputs for that widget.
|
That does indeed look like a solution, but won't do as soon as there's some convenience function for opening a message box. |
I'm thinking on a KW_Modal composite widget, that generates a widget covering the whole parent widget geometry (possibly using new tileset slot, allowing it to serve like a mask/shade), blocking all widget events below it. This widget would have a frame as children which will conform to the requested widget geometry (the mask wouldn't, it would always have the parent geometry - we can have functions to enable/disable this) and would paint a frame (a slot below/above the mask tiles). This widget would be the parent of the user widgets. Does this sound like a good solution? Thoughts? KW_Widget * KW_CreateModal(KW_Widget * parent, KW_Rect * geometry) {
// Create an empty widget, whose geometry = parent->geometry
// Create another widget, children of the above widget , using the passed in geometry
// return second widget
}
KW_Widget * parent; // Assume lots of widgets children of this
KW_Widget * modal = KW_CreateModal(parent, geometry);
// create widgets that would go into the modal widget |
Hm, not sure. It doesn't sound much different from using two frames, one for the normal window, the other for a message box, then blocking input events for the former while the latter is still open. |
Yeah, it is absolutely simillar, except that this will be done automatically instead of manually by the user, taking care of event blocking, parent fading and even dragging support. It will serve as the basis for a KW_CreateMessageBox()-of-sorts function. KW_CreateModal() would fade the parent, create another frame on top. KW_CreateMessageBox() would use the return from KW_CreateModal() to setup editbox and buttons. |
Hi, I've fixed the DestroyWidget bug in commit c663dea |
Thanks, can confirm that this allows me to destroy widgets dynamically. Now I'm getting different kinds of mysterious failures instead in my wrapper code, will port it back to C again to see what that is about. It's not nearly as important to me as it appears that hiding widgets you don't need is the way to go. edit: Perhaps the need for deleting widgets can be explained and solved in a different way. I've thought of a more elaborate demo where it would be very useful to dynamically create and clean up screens, a game menu where one enters and leaves menus as they please. While one could solve this in SDL2 directly, I could imagine an abstraction for this usecase to help, similar to IUP's dialogs. You define a hierarchical dialog first, then display and close it. There are prebuilt dialogs for message and input boxes available which are displayed as normal dialogs, but with a modal flag. edit2: Fixed up my example now, no more mysterious failures :D |
How would you picture this being done with KiWI? Can you describe a would-be API? |
Not really, I've only used IUP from Scheme. |
What if u made a drop down box?? |
That is a good idea and not hard to do, but I don't have the time right now to invest on it. Also, a request like this should be in another issue :) |
oh ok sorry i’ll go put it in github ig sorry
…On Tue, Jul 31, 2018 at 6:56 AM Leonardo Guilherme de Freitas < ***@***.***> wrote:
That is a good idea and not hard to do, but I don't have the time right
now to invest on it. Also, a request like this should be in another issue :)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#15 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AnkwpjK0Q7v6kl0Ed30OnieyvEQG9koPks5uMEXlgaJpZM4ImaXJ>
.
|
I'm currently writing my custom hello world example which consists of a frame with two buttons, one of which quits the program and the other one displaying a (modal) message box with a single OK-button for closing it. Ideally the latter would be a matter of using a convenience function, but that doesn't apper to exist yet. Currently I have two ideas how one could implement it:
KW_DestroyWidget
is clearly not the right solution as that yields a SIGSEGV, setting the widget's geometry to an empty rectangle hides its frame, but leaves its child widgets still visible and drawn as children of the parent frame.KW_GUI
and draw the composite widget there. What I don't really understand for that approach is how one would modify the SDL2 event loop to deal with the new window as long as it's open.Thoughts on this?
edit: I've found out that SDL2 provides
SDL_ShowSimpleMessageBox
which is sort of OK as it has the desired behavior, but looks totally different from the rest of KiWi and doesn't update the parent window (leading to the infamous Windows dragging glitch).The text was updated successfully, but these errors were encountered: