From 88bb697bbdb5d6215e3be138550d9bfedced849a Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Thu, 16 Jun 2016 00:45:23 -0400 Subject: [PATCH] Implemented the new uiWindow stuff on GTK+. --- unix/window.c | 85 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 14 deletions(-) diff --git a/unix/window.c b/unix/window.c index cdb3ab84..f0d88be4 100644 --- a/unix/window.c +++ b/unix/window.c @@ -12,9 +12,12 @@ struct uiWindow { GtkContainer *vboxContainer; GtkBox *vbox; + GtkWidget *childHolderWidget; + GtkContainer *childHolderContainer; + GtkWidget *menubar; - struct child *child; + uiControl *child; int margined; int (*onClosing)(uiWindow *, void *); @@ -22,6 +25,9 @@ struct uiWindow { void (*onPositionChanged)(uiWindow *, void *); void *onPositionChangedData; gboolean changingPosition; + void (*onContentSizeChanged)(uiWindow *, void *); + void *onContentSizeChangedData; + gboolean changingSize; }; static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data) @@ -48,12 +54,22 @@ static gboolean onConfigure(GtkWidget *win, GdkEvent *e, gpointer data) return FALSE; } +static void onSizeAllocate(GtkWidget *widget, GdkRectangle *allocation, gpointer data) +{ + uiWindow *w = uiWindow(data); + + if (w->changingSize) + w->changingSize = FALSE; + else + (*(w->onContentSizeChanged))(w, w->onContentSizeChangedData); +} + static int defaultOnClosing(uiWindow *w, void *data) { return 0; } -static void defaultOnPositionChanged(uiWindow *w, void *data) +static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data) { // do nothing } @@ -65,11 +81,15 @@ static void uiWindowDestroy(uiControl *c) // first hide ourselves gtk_widget_hide(w->widget); // now destroy the child - if (w->child != NULL) - childDestroy(w->child); + if (w->child != NULL) { + uiControlSetParent(w->child, NULL); + uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, TRUE); + uiControlDestroy(w->child); + } // now destroy the menus, if any if (w->menubar != NULL) freeMenubar(w->menubar); + gtk_widget_destroy(w->childHolderWidget); gtk_widget_destroy(w->vboxWidget); // and finally free ourselves g_object_unref(w->widget); @@ -171,22 +191,50 @@ void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void w->onPositionChangedData = data; } +void uiWindowContentSize(uiWindow *w, int *width, int *height) +{ + GtkAllocation allocation; + + gtk_widget_get_allocation(w->childHolderWidget, &allocation); + *width = allocation.width; + *height = allocation.height; +} + +// TODO what happens if the size is already the current one? +// TODO a spurious size-allocate gets sent after this function returns +void uiWindowSetContentSize(uiWindow *w, int width, int height) +{ + w->changingSize = TRUE; + gtk_widget_set_size_request(w->childHolderWidget, width, height); + while (w->changingSize) + if (gtk_main_iteration() != FALSE) + break; // stop early if gtk_main_quit() called + gtk_widget_set_size_request(w->childHolderWidget, -1, -1); +} + +void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data) +{ + w->onContentSizeChanged = f; + w->onContentSizeChangedData = data; +} + void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data) { w->onClosing = f; w->onClosingData = data; } +// TODO save and restore expands and aligns void uiWindowSetChild(uiWindow *w, uiControl *child) { - if (w->child != NULL) - childRemove(w->child); - w->child = newChildWithBox(child, uiControl(w), w->vboxContainer, w->margined); if (w->child != NULL) { - gtk_widget_set_hexpand(childBox(w->child), TRUE); - gtk_widget_set_halign(childBox(w->child), GTK_ALIGN_FILL); - gtk_widget_set_vexpand(childBox(w->child), TRUE); - gtk_widget_set_valign(childBox(w->child), GTK_ALIGN_FILL); + uiControlSetParent(w->child, NULL); + uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, TRUE); + } + w->child = child; + if (w->child != NULL) { + uiControlSetParent(w->child, uiControl(w)); + uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, FALSE); } } @@ -198,8 +246,7 @@ int uiWindowMargined(uiWindow *w) void uiWindowSetMargined(uiWindow *w, int margined) { w->margined = margined; - if (w->child != NULL) - childSetMargined(w->child, w->margined); + setMargined(w->childHolderContainer, w->margined); } uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) @@ -227,14 +274,24 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) gtk_container_add(w->vboxContainer, w->menubar); } + w->childHolderWidget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + w->childHolderContainer = GTK_CONTAINER(w->childHolderWidget); + gtk_widget_set_hexpand(w->childHolderWidget, TRUE); + gtk_widget_set_halign(w->childHolderWidget, GTK_ALIGN_FILL); + gtk_widget_set_vexpand(w->childHolderWidget, TRUE); + gtk_widget_set_valign(w->childHolderWidget, GTK_ALIGN_FILL); + gtk_container_add(w->vboxContainer, w->childHolderWidget); + // show everything in the vbox, but not the GtkWindow itself gtk_widget_show_all(w->vboxWidget); // and connect our events g_signal_connect(w->widget, "delete-event", G_CALLBACK(onClosing), w); g_signal_connect(w->widget, "configure-event", G_CALLBACK(onConfigure), w); + g_signal_connect(w->childHolderWidget, "size-allocate", G_CALLBACK(onSizeAllocate), w); uiWindowOnClosing(w, defaultOnClosing, NULL); - uiWindowOnPositionChanged(w, defaultOnPositionChanged, NULL); + uiWindowOnPositionChanged(w, defaultOnPositionContentSizeChanged, NULL); + uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL); // normally it's SetParent() that does this, but we can't call SetParent() on a uiWindow // TODO we really need to clean this up