diff --git a/redo/unix/GNUmakeinc.mk b/redo/unix/GNUmakeinc.mk index d2080e03..607b4447 100644 --- a/redo/unix/GNUmakeinc.mk +++ b/redo/unix/GNUmakeinc.mk @@ -2,6 +2,7 @@ osCFILES = \ unix/alloc.c \ + unix/bin.c \ unix/box.c \ unix/button.c \ unix/checkbox.c \ diff --git a/redo/unix/bin.c b/redo/unix/bin.c new file mode 100644 index 00000000..ddb3470d --- /dev/null +++ b/redo/unix/bin.c @@ -0,0 +1,82 @@ +// 30 june 2015 +#include "uipriv_unix.h" + +// This is a uiControl wrapper a la GtkBin. +// It serves the function of tabPage on Windows: it allows uiWindow and uiTab to give their children a real uiControl as a parent while not screwing with the internal GtkWidget structure of those uiControls. +// It also provides margins. + +struct bin { + uiControl c; + GtkWidget *widget; + GtkContainer *container; + GtkBox *box; // GtkBin is abstract and none of the implementations seem adequate (GtkFrame is the closest but eh) + uiControl *child; + int margined; +}; + +uiDefineControlType(bin, binType, struct bin) + +static uintptr_t binHandle(uiControl *c) +{ + struct bin *b = (struct bin *) c; + + return (uintptr_t) (b->widget); +} + +uiControl *newBin(void) +{ + struct bin *b; + + b = (struct bin *) uiNewControl(binType()); + + b->widget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + b->container = GTK_CONTAINER(b->widget); + b->box = GTK_BOX(b->widget); + uiUnixMakeSingleWidgetControl(uiControl(b), b->widget); + + // a uiBox is theoretically used in a context where this shouldn't be necessary but because of uiWindow we'll do it anyway + gtk_widget_set_hexpand(b->widget, TRUE); + gtk_widget_set_halign(b->widget, GTK_ALIGN_FILL); + gtk_widget_set_vexpand(b->widget, TRUE); + gtk_widget_set_valign(b->widget, GTK_ALIGN_FILL); + + uiControl(b)->Handle = binHandle; + + return uiControl(b); +} + +void binSetChild(uiControl *c, uiControl *child) +{ + struct bin *b = (struct bin *) c; + GtkWidget *childWidget; + + if (b->child != NULL) + uiControlSetParent(b->child, NULL); + b->child = child; + if (b->child != NULL) { + uiControlSetParent(b->child, uiControl(b)); + childWidget = GTK_WIDGET(uiControlHandle(b->child)); + gtk_widget_set_hexpand(childWidget, TRUE); + gtk_widget_set_halign(childWidget, GTK_ALIGN_FILL); + gtk_widget_set_vexpand(childWidget, TRUE); + gtk_widget_set_valign(childWidget, GTK_ALIGN_FILL); + } +} + +int binMargined(uiControl *c) +{ + struct bin *b = (struct bin *) c; + + return b->margined; +} + +void binSetMargined(uiControl *c, int margined) +{ + struct bin *b = (struct bin *) c; + + b->margined = margined; + if (b->margined) + gtk_container_set_border_width(b->container, gtkXMargin); + else + gtk_container_set_border_width(b->container, 0); +} diff --git a/redo/unix/uipriv_unix.h b/redo/unix/uipriv_unix.h index 79d151ba..64faf5e2 100644 --- a/redo/unix/uipriv_unix.h +++ b/redo/unix/uipriv_unix.h @@ -22,5 +22,11 @@ extern void uninitMenus(void); extern void initAlloc(void); extern void uninitAlloc(void); +// bin.c +extern uiControl *newBin(void); +extern void binSetChild(uiControl *, uiControl *); +extern int binMargined(uiControl *); +extern void binSetMargined(uiControl *, int); + // TODO #define PUT_CODE_HERE 0 diff --git a/redo/unix/window.c b/redo/unix/window.c index 7e6b75c2..66840bb9 100644 --- a/redo/unix/window.c +++ b/redo/unix/window.c @@ -16,11 +16,11 @@ struct window { GtkWidget *menubar; + uiControl *bin; uiControl *child; int (*onClosing)(uiWindow *, void *); void *onClosingData; - int margined; void (*baseCommitDestroy)(uiControl *c); }; @@ -49,8 +49,10 @@ static void windowCommitDestroy(uiControl *c) // first hide ourselves gtk_widget_hide(w->widget); // now destroy the child - uiControlSetParent(w->child, NULL); + binSetChild(w->bin, NULL); uiControlDestroy(w->child); + // and destroy the bin + uiControlDestroy(w->bin); // now destroy the menus, if any if (w->menubar != NULL) freeMenubar(w->menubar); @@ -112,32 +114,24 @@ static void windowSetChild(uiWindow *ww, uiControl *child) struct window *w = (struct window *) ww; if (w->child != NULL) - uiControlSetParent(w->child, NULL); + binSetChild(w->bin, NULL); w->child = child; - if (w->child != NULL) { -//TODO uiControlSetParent(w->child, w->child); - gtk_widget_set_hexpand(GTK_WIDGET(uiControlHandle(w->child)), TRUE); - gtk_widget_set_halign(GTK_WIDGET(uiControlHandle(w->child)), GTK_ALIGN_FILL); - gtk_widget_set_vexpand(GTK_WIDGET(uiControlHandle(w->child)), TRUE); - gtk_widget_set_valign(GTK_WIDGET(uiControlHandle(w->child)), GTK_ALIGN_FILL); - gtk_container_add(w->vboxContainer, GTK_WIDGET(uiControlHandle(w->child))); - uiControlQueueResize(w->child); - } + if (w->child != NULL) + binSetChild(w->bin, w->child); } static int windowMargined(uiWindow *ww) { struct window *w = (struct window *) ww; - return w->margined; + return binMargined(w->bin); } static void windowSetMargined(uiWindow *ww, int margined) { struct window *w = (struct window *) ww; - w->margined = margined; - // TODO + binSetMargined(w->bin, margined); uiControlQueueResize(uiControl(w)); } @@ -178,6 +172,9 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) gtk_container_add(w->vboxContainer, w->menubar); } + w->bin = newBin(); + gtk_container_add(w->vboxContainer, GTK_WIDGET(uiControlHandle(w->bin))); + // show everything in the vbox, but not the GtkWindow itself gtk_widget_show_all(w->vboxWidget);