diff options
Diffstat (limited to 'src/libui_sdl/libui/unix/box.c')
-rw-r--r-- | src/libui_sdl/libui/unix/box.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/unix/box.c b/src/libui_sdl/libui/unix/box.c new file mode 100644 index 0000000..23fb7f7 --- /dev/null +++ b/src/libui_sdl/libui/unix/box.c @@ -0,0 +1,159 @@ +// 7 april 2015 +#include "uipriv_unix.h" + +struct boxChild { + uiControl *c; + int stretchy; + gboolean oldhexpand; + GtkAlign oldhalign; + gboolean oldvexpand; + GtkAlign oldvalign; +}; + +struct uiBox { + uiUnixControl c; + GtkWidget *widget; + GtkContainer *container; + GtkBox *box; + GArray *controls; + int vertical; + int padded; + GtkSizeGroup *stretchygroup; // ensures all stretchy controls have the same size +}; + +uiUnixControlAllDefaultsExceptDestroy(uiBox) + +#define ctrl(b, i) &g_array_index(b->controls, struct boxChild, i) + +static void uiBoxDestroy(uiControl *c) +{ + uiBox *b = uiBox(c); + struct boxChild *bc; + guint i; + + // kill the size group + g_object_unref(b->stretchygroup); + // free all controls + for (i = 0; i < b->controls->len; i++) { + bc = ctrl(b, i); + uiControlSetParent(bc->c, NULL); + // and make sure the widget itself stays alive + uiUnixControlSetContainer(uiUnixControl(bc->c), b->container, TRUE); + uiControlDestroy(bc->c); + } + g_array_free(b->controls, TRUE); + // and then ourselves + g_object_unref(b->widget); + uiFreeControl(uiControl(b)); +} + +void uiBoxAppend(uiBox *b, uiControl *c, int stretchy) +{ + struct boxChild bc; + GtkWidget *widget; + + bc.c = c; + bc.stretchy = stretchy; + widget = GTK_WIDGET(uiControlHandle(bc.c)); + bc.oldhexpand = gtk_widget_get_hexpand(widget); + bc.oldhalign = gtk_widget_get_halign(widget); + bc.oldvexpand = gtk_widget_get_vexpand(widget); + bc.oldvalign = gtk_widget_get_valign(widget); + + if (bc.stretchy) { + if (b->vertical) { + gtk_widget_set_vexpand(widget, TRUE); + gtk_widget_set_valign(widget, GTK_ALIGN_FILL); + } else { + gtk_widget_set_hexpand(widget, TRUE); + gtk_widget_set_halign(widget, GTK_ALIGN_FILL); + } + gtk_size_group_add_widget(b->stretchygroup, widget); + } else + if (b->vertical) + gtk_widget_set_vexpand(widget, FALSE); + else + gtk_widget_set_hexpand(widget, FALSE); + // and make them fill the opposite direction + if (b->vertical) { + gtk_widget_set_hexpand(widget, TRUE); + gtk_widget_set_halign(widget, GTK_ALIGN_FILL); + } else { + gtk_widget_set_vexpand(widget, TRUE); + gtk_widget_set_valign(widget, GTK_ALIGN_FILL); + } + + uiControlSetParent(bc.c, uiControl(b)); + uiUnixControlSetContainer(uiUnixControl(bc.c), b->container, FALSE); + g_array_append_val(b->controls, bc); +} + +void uiBoxDelete(uiBox *b, int index) +{ + struct boxChild *bc; + GtkWidget *widget; + + bc = ctrl(b, index); + widget = GTK_WIDGET(uiControlHandle(bc->c)); + + uiControlSetParent(bc->c, NULL); + uiUnixControlSetContainer(uiUnixControl(bc->c), b->container, TRUE); + + if (bc->stretchy) + gtk_size_group_remove_widget(b->stretchygroup, widget); + gtk_widget_set_hexpand(widget, bc->oldhexpand); + gtk_widget_set_halign(widget, bc->oldhalign); + gtk_widget_set_vexpand(widget, bc->oldvexpand); + gtk_widget_set_valign(widget, bc->oldvalign); + + g_array_remove_index(b->controls, index); +} + +int uiBoxPadded(uiBox *b) +{ + return b->padded; +} + +void uiBoxSetPadded(uiBox *b, int padded) +{ + b->padded = padded; + if (b->padded) + if (b->vertical) + gtk_box_set_spacing(b->box, gtkYPadding); + else + gtk_box_set_spacing(b->box, gtkXPadding); + else + gtk_box_set_spacing(b->box, 0); +} + +static uiBox *finishNewBox(GtkOrientation orientation) +{ + uiBox *b; + + uiUnixNewControl(uiBox, b); + + b->widget = gtk_box_new(orientation, 0); + b->container = GTK_CONTAINER(b->widget); + b->box = GTK_BOX(b->widget); + + b->vertical = orientation == GTK_ORIENTATION_VERTICAL; + + if (b->vertical) + b->stretchygroup = gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL); + else + b->stretchygroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + + b->controls = g_array_new(FALSE, TRUE, sizeof (struct boxChild)); + + return b; +} + +uiBox *uiNewHorizontalBox(void) +{ + return finishNewBox(GTK_ORIENTATION_HORIZONTAL); +} + +uiBox *uiNewVerticalBox(void) +{ + return finishNewBox(GTK_ORIENTATION_VERTICAL); +} |