diff --git a/unix/bin.c b/unix/bin.c index 1b87c5cb..a857cce9 100644 --- a/unix/bin.c +++ b/unix/bin.c @@ -1,117 +1,38 @@ // 28 april 2015 #include "uipriv_unix.h" -struct bin { - uiContainer c; - void (*baseDestroy)(uiControl *); - uiControl *mainControl; - intmax_t marginLeft; - intmax_t marginTop; - intmax_t marginRight; - intmax_t marginBottom; -}; - -static void binDestroy(uiControl *c) +int binHasOSParent(uiBin *b) { - struct bin *b = (struct bin *) c; GtkWidget *binWidget; - // ensure clean removal by making sure the bin has no OS parent binWidget = GTK_WIDGET(uiControlHandle(uiControl(b))); - if (gtk_widget_get_parent(binWidget) != NULL) - complain("attempt to destroy bin %p while it has an OS parent", b); - // don't chain up to base here; we need to destroy children ourselves first - if (b->mainControl != NULL) { - uiControlSetParent(b->mainControl, NULL); - uiControlDestroy(b->mainControl); - } - // NOW we can chain up to base - (*(b->baseDestroy))(uiControl(b)); - uiFree(b); + return gtk_widget_get_parent(binWidget) != NULL; } -static void binPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) +void binSetOSParent(uiBin *b, uintptr_t osParent) { - struct bin *b = (struct bin *) c; - intmax_t marginX, marginY; + GtkWidget *binWidget; - if (b->mainControl == NULL) { - *width = 0; - *height = 0; - return; - } - uiControlPreferredSize(b->mainControl, d, width, height); - marginX = b->marginLeft + b->marginRight; - marginY = b->marginTop + b->marginBottom; - *width += marginX; - *height += marginY; + binWidget = GTK_WIDGET(uiControlHandle(uiControl(b))); + gtk_container_add(GTK_CONTAINER(osParent), binWidget); } -static void binResizeChildren(uiContainer *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) +void binRemoveOSParent(uiBin *b) { - struct bin *b = (struct bin *) c; + GtkWidget *binWidget; + GtkWidget *oldparent; - if (b->mainControl == NULL) - return; - x += b->marginLeft; - y += b->marginTop; - width -= b->marginLeft + b->marginRight; - height -= b->marginTop + b->marginBottom; - uiControlResize(b->mainControl, x, y, width, height, d); + binWidget = GTK_WIDGET(uiControlHandle(uiControl(b))); + oldparent = gtk_widget_get_parent(binWidget); + gtk_container_remove(GTK_CONTAINER(oldparent), binWidget); } -uiContainer *newBin(void) +void binResizeRootAndUpdate(uiBin *b, intmax_t x, intmax_t y, intmax_t width, intmax_t height) { - struct bin *b; - - b = uiNew(struct bin); - - uiMakeContainer(uiContainer(b)); - - b->baseDestroy = uiControl(b)->Destroy; - uiControl(b)->Destroy = binDestroy; - uiControl(b)->PreferredSize = binPreferredSize; - - uiContainer(b)->ResizeChildren = binResizeChildren; - - return uiContainer(b); + // not used on GTK+ } -void binSetMainControl(uiContainer *c, uiControl *mainControl) +void binTranslateMargins(uiBin *b, intmax_t *left, intmax_t *top, intmax_t *right, intmax_t *bottom, uiSizing *d) { - struct bin *b = (struct bin *) c; - - if (b->mainControl != NULL) - uiControlSetParent(b->mainControl, NULL); - b->mainControl = mainControl; - if (b->mainControl != NULL) - uiControlSetParent(b->mainControl, uiContainer(b)); - uiContainerUpdate(uiContainer(b)); -} - -void binSetMargins(uiContainer *c, intmax_t left, intmax_t top, intmax_t right, intmax_t bottom) -{ - struct bin *b = (struct bin *) c; - - b->marginLeft = left; - b->marginRight = right; - b->marginTop = top; - b->marginBottom = bottom; - uiContainerUpdate(uiContainer(b)); -} - -void binSetParent(uiContainer *c, uintptr_t osParent) -{ - struct bin *b = (struct bin *) c; - GtkWidget *widget; - GtkContainer *newContainer, *oldContainer; - - widget = GTK_WIDGET(uiControlHandle(uiControl(b))); - if (osParent == 0) { - oldContainer = GTK_CONTAINER(gtk_widget_get_parent(widget)); - gtk_container_remove(oldContainer, widget); - return; - } - newContainer = GTK_CONTAINER(osParent); - gtk_container_add(newContainer, widget); + // not used on GTK+ } diff --git a/unix/tab.c b/unix/tab.c index 8ba228ba..5e89325b 100644 --- a/unix/tab.c +++ b/unix/tab.c @@ -10,7 +10,8 @@ struct tab { }; struct tabPage { - uiContainer *bin; + uiBin *bin; + // TODO remove the need for this GtkWidget *binWidget; int margined; }; @@ -27,8 +28,7 @@ static void onDestroy(void *data) // we need to remove them from the tab first; see below for (i = 0; i < t->pages->len; i++) { p = &g_array_index(t->pages, struct tabPage, i); - // this does the job of binSetParent() - gtk_container_remove(t->container, p->binWidget); + uiBinRemoveOSParent(p->bin); uiControlDestroy(uiControl(p->bin)); } // then free ourselves @@ -52,9 +52,9 @@ static void tabAppendPage(uiTab *tt, const char *name, uiControl *child) struct tabPage p; p.bin = newBin(); - binSetMainControl(p.bin, child); + uiBinSetMainControl(p.bin, child); // and add it as a tab page - binSetParent(p.bin, (uintptr_t) (t->container)); + uiBinSetOSParent(p.bin, (uintptr_t) (t->container)); p.binWidget = GTK_WIDGET(uiControlHandle(uiControl(p.bin))); gtk_notebook_set_tab_label_text(t->notebook, p.binWidget, name); @@ -67,9 +67,9 @@ static void tabInsertPageBefore(uiTab *tt, const char *name, uintmax_t n, uiCont struct tabPage p; p.bin = newBin(); - binSetMainControl(p.bin, child); + uiBinSetMainControl(p.bin, child); // and add it as a tab page - binSetParent(p.bin, (uintptr_t) (t->container)); + uiBinSetOSParent(p.bin, (uintptr_t) (t->container)); p.binWidget = GTK_WIDGET(uiControlHandle(uiControl(p.bin))); gtk_notebook_set_tab_label_text(t->notebook, p.binWidget, name); @@ -85,15 +85,15 @@ static void tabDeletePage(uiTab *tt, uintmax_t n) p = &g_array_index(t->pages, struct tabPage, n); // make sure the page's control isn't destroyed - binSetMainControl(p->bin, NULL); + uiBinSetMainControl(p->bin, NULL); // now destroy the page // this will also remove the tab // why? simple: both gtk_notebook_remove_tab() and gtk_widget_destroy() call gtk_container_remove() // we need to remove them from the tab first, though, otherwise they won't really be destroyed properly // (the GtkNotebook will still have the tab in it because its reference ISN'T destroyed, and we crash resizing a bin that no longer exists - // this also does the job of binSetParent() - gtk_container_remove(t->container, p->binWidget); + // TODO redo this comment + uiBinRemoveOSParent(p->bin); uiControlDestroy(uiControl(p->bin)); g_array_remove_index(t->pages, n); @@ -123,9 +123,9 @@ static void tabSetMargined(uiTab *tt, uintmax_t n, int margined) p = &g_array_index(t->pages, struct tabPage, n); p->margined = margined; if (p->margined) - binSetMargins(p->bin, gtkXMargin, gtkYMargin, gtkXMargin, gtkYMargin); + uiBinSetMargins(p->bin, gtkXMargin, gtkYMargin, gtkXMargin, gtkYMargin); else - binSetMargins(p->bin, 0, 0, 0, 0); + uiBinSetMargins(p->bin, 0, 0, 0, 0); } uiTab *uiNewTab(void) diff --git a/unix/window.c b/unix/window.c index 1dcbae2a..559cf89b 100644 --- a/unix/window.c +++ b/unix/window.c @@ -14,7 +14,7 @@ struct window { GtkWidget *menubar; - uiContainer *bin; + uiBin *bin; int hidden; @@ -47,7 +47,7 @@ static void windowDestroy(uiControl *c) gtk_widget_hide(w->widget); // now destroy the bin // we need to remove the bin from its parent first - binSetParent(w->bin, 0); + uiBinRemoveOSParent(w->bin); uiControlDestroy(uiControl(w->bin)); // now destroy the menus, if any if (w->menubar != NULL) @@ -146,7 +146,7 @@ static void windowSetChild(uiWindow *ww, uiControl *child) { struct window *w = (struct window *) ww; - binSetMainControl(w->bin, child); + uiBinSetMainControl(w->bin, child); } static int windowMargined(uiWindow *ww) @@ -162,9 +162,9 @@ static void windowSetMargined(uiWindow *ww, int margined) w->margined = margined; if (w->margined) - binSetMargins(w->bin, gtkXMargin, gtkYMargin, gtkXMargin, gtkYMargin); + uiBinSetMargins(w->bin, gtkXMargin, gtkYMargin, gtkXMargin, gtkYMargin); else - binSetMargins(w->bin, 0, 0, 0, 0); + uiBinSetMargins(w->bin, 0, 0, 0, 0); } uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) @@ -199,7 +199,7 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) gtk_widget_set_halign(binWidget, GTK_ALIGN_FILL); gtk_widget_set_vexpand(binWidget, TRUE); gtk_widget_set_valign(binWidget, GTK_ALIGN_FILL); - binSetParent(w->bin, (uintptr_t) (w->vboxContainer)); + uiBinSetOSParent(w->bin, (uintptr_t) (w->vboxContainer)); // show everything in the vbox, but not the GtkWindow itself gtk_widget_show_all(w->vboxWidget);