Implemented the new uiWindow stuff on GTK+.

This commit is contained in:
Pietro Gagliardi 2016-06-16 00:45:23 -04:00
parent e5064de86b
commit 88bb697bbd
1 changed files with 71 additions and 14 deletions

View File

@ -12,9 +12,12 @@ struct uiWindow {
GtkContainer *vboxContainer; GtkContainer *vboxContainer;
GtkBox *vbox; GtkBox *vbox;
GtkWidget *childHolderWidget;
GtkContainer *childHolderContainer;
GtkWidget *menubar; GtkWidget *menubar;
struct child *child; uiControl *child;
int margined; int margined;
int (*onClosing)(uiWindow *, void *); int (*onClosing)(uiWindow *, void *);
@ -22,6 +25,9 @@ struct uiWindow {
void (*onPositionChanged)(uiWindow *, void *); void (*onPositionChanged)(uiWindow *, void *);
void *onPositionChangedData; void *onPositionChangedData;
gboolean changingPosition; gboolean changingPosition;
void (*onContentSizeChanged)(uiWindow *, void *);
void *onContentSizeChangedData;
gboolean changingSize;
}; };
static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data) static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data)
@ -48,12 +54,22 @@ static gboolean onConfigure(GtkWidget *win, GdkEvent *e, gpointer data)
return FALSE; 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) static int defaultOnClosing(uiWindow *w, void *data)
{ {
return 0; return 0;
} }
static void defaultOnPositionChanged(uiWindow *w, void *data) static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data)
{ {
// do nothing // do nothing
} }
@ -65,11 +81,15 @@ static void uiWindowDestroy(uiControl *c)
// first hide ourselves // first hide ourselves
gtk_widget_hide(w->widget); gtk_widget_hide(w->widget);
// now destroy the child // now destroy the child
if (w->child != NULL) if (w->child != NULL) {
childDestroy(w->child); uiControlSetParent(w->child, NULL);
uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, TRUE);
uiControlDestroy(w->child);
}
// now destroy the menus, if any // now destroy the menus, if any
if (w->menubar != NULL) if (w->menubar != NULL)
freeMenubar(w->menubar); freeMenubar(w->menubar);
gtk_widget_destroy(w->childHolderWidget);
gtk_widget_destroy(w->vboxWidget); gtk_widget_destroy(w->vboxWidget);
// and finally free ourselves // and finally free ourselves
g_object_unref(w->widget); g_object_unref(w->widget);
@ -171,22 +191,50 @@ void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void
w->onPositionChangedData = data; 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) void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data)
{ {
w->onClosing = f; w->onClosing = f;
w->onClosingData = data; w->onClosingData = data;
} }
// TODO save and restore expands and aligns
void uiWindowSetChild(uiWindow *w, uiControl *child) 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) { if (w->child != NULL) {
gtk_widget_set_hexpand(childBox(w->child), TRUE); uiControlSetParent(w->child, NULL);
gtk_widget_set_halign(childBox(w->child), GTK_ALIGN_FILL); uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, TRUE);
gtk_widget_set_vexpand(childBox(w->child), TRUE); }
gtk_widget_set_valign(childBox(w->child), GTK_ALIGN_FILL); 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) void uiWindowSetMargined(uiWindow *w, int margined)
{ {
w->margined = margined; w->margined = margined;
if (w->child != NULL) setMargined(w->childHolderContainer, w->margined);
childSetMargined(w->child, w->margined);
} }
uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) 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); 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 // show everything in the vbox, but not the GtkWindow itself
gtk_widget_show_all(w->vboxWidget); gtk_widget_show_all(w->vboxWidget);
// and connect our events // and connect our events
g_signal_connect(w->widget, "delete-event", G_CALLBACK(onClosing), w); 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->widget, "configure-event", G_CALLBACK(onConfigure), w);
g_signal_connect(w->childHolderWidget, "size-allocate", G_CALLBACK(onSizeAllocate), w);
uiWindowOnClosing(w, defaultOnClosing, NULL); 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 // normally it's SetParent() that does this, but we can't call SetParent() on a uiWindow
// TODO we really need to clean this up // TODO we really need to clean this up