Migrated the GTK+ backend to the new uiBin system.

This commit is contained in:
Pietro Gagliardi 2015-05-10 14:05:59 -04:00
parent 41030b0a03
commit 8f24dffa01
3 changed files with 34 additions and 113 deletions

View File

@ -1,117 +1,38 @@
// 28 april 2015 // 28 april 2015
#include "uipriv_unix.h" #include "uipriv_unix.h"
struct bin { int binHasOSParent(uiBin *b)
uiContainer c;
void (*baseDestroy)(uiControl *);
uiControl *mainControl;
intmax_t marginLeft;
intmax_t marginTop;
intmax_t marginRight;
intmax_t marginBottom;
};
static void binDestroy(uiControl *c)
{ {
struct bin *b = (struct bin *) c;
GtkWidget *binWidget; GtkWidget *binWidget;
// ensure clean removal by making sure the bin has no OS parent
binWidget = GTK_WIDGET(uiControlHandle(uiControl(b))); binWidget = GTK_WIDGET(uiControlHandle(uiControl(b)));
if (gtk_widget_get_parent(binWidget) != NULL) return 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);
} }
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; GtkWidget *binWidget;
intmax_t marginX, marginY;
if (b->mainControl == NULL) { binWidget = GTK_WIDGET(uiControlHandle(uiControl(b)));
*width = 0; gtk_container_add(GTK_CONTAINER(osParent), binWidget);
*height = 0;
return;
}
uiControlPreferredSize(b->mainControl, d, width, height);
marginX = b->marginLeft + b->marginRight;
marginY = b->marginTop + b->marginBottom;
*width += marginX;
*height += marginY;
} }
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) binWidget = GTK_WIDGET(uiControlHandle(uiControl(b)));
return; oldparent = gtk_widget_get_parent(binWidget);
x += b->marginLeft; gtk_container_remove(GTK_CONTAINER(oldparent), binWidget);
y += b->marginTop;
width -= b->marginLeft + b->marginRight;
height -= b->marginTop + b->marginBottom;
uiControlResize(b->mainControl, x, y, width, height, d);
} }
uiContainer *newBin(void) void binResizeRootAndUpdate(uiBin *b, intmax_t x, intmax_t y, intmax_t width, intmax_t height)
{ {
struct bin *b; // not used on GTK+
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);
} }
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; // not used on GTK+
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);
} }

View File

@ -10,7 +10,8 @@ struct tab {
}; };
struct tabPage { struct tabPage {
uiContainer *bin; uiBin *bin;
// TODO remove the need for this
GtkWidget *binWidget; GtkWidget *binWidget;
int margined; int margined;
}; };
@ -27,8 +28,7 @@ static void onDestroy(void *data)
// we need to remove them from the tab first; see below // we need to remove them from the tab first; see below
for (i = 0; i < t->pages->len; i++) { for (i = 0; i < t->pages->len; i++) {
p = &g_array_index(t->pages, struct tabPage, i); p = &g_array_index(t->pages, struct tabPage, i);
// this does the job of binSetParent() uiBinRemoveOSParent(p->bin);
gtk_container_remove(t->container, p->binWidget);
uiControlDestroy(uiControl(p->bin)); uiControlDestroy(uiControl(p->bin));
} }
// then free ourselves // then free ourselves
@ -52,9 +52,9 @@ static void tabAppendPage(uiTab *tt, const char *name, uiControl *child)
struct tabPage p; struct tabPage p;
p.bin = newBin(); p.bin = newBin();
binSetMainControl(p.bin, child); uiBinSetMainControl(p.bin, child);
// and add it as a tab page // 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))); p.binWidget = GTK_WIDGET(uiControlHandle(uiControl(p.bin)));
gtk_notebook_set_tab_label_text(t->notebook, p.binWidget, name); 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; struct tabPage p;
p.bin = newBin(); p.bin = newBin();
binSetMainControl(p.bin, child); uiBinSetMainControl(p.bin, child);
// and add it as a tab page // 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))); p.binWidget = GTK_WIDGET(uiControlHandle(uiControl(p.bin)));
gtk_notebook_set_tab_label_text(t->notebook, p.binWidget, name); 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); p = &g_array_index(t->pages, struct tabPage, n);
// make sure the page's control isn't destroyed // make sure the page's control isn't destroyed
binSetMainControl(p->bin, NULL); uiBinSetMainControl(p->bin, NULL);
// now destroy the page // now destroy the page
// this will also remove the tab // this will also remove the tab
// why? simple: both gtk_notebook_remove_tab() and gtk_widget_destroy() call gtk_container_remove() // 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 // 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 // (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() // TODO redo this comment
gtk_container_remove(t->container, p->binWidget); uiBinRemoveOSParent(p->bin);
uiControlDestroy(uiControl(p->bin)); uiControlDestroy(uiControl(p->bin));
g_array_remove_index(t->pages, n); 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 = &g_array_index(t->pages, struct tabPage, n);
p->margined = margined; p->margined = margined;
if (p->margined) if (p->margined)
binSetMargins(p->bin, gtkXMargin, gtkYMargin, gtkXMargin, gtkYMargin); uiBinSetMargins(p->bin, gtkXMargin, gtkYMargin, gtkXMargin, gtkYMargin);
else else
binSetMargins(p->bin, 0, 0, 0, 0); uiBinSetMargins(p->bin, 0, 0, 0, 0);
} }
uiTab *uiNewTab(void) uiTab *uiNewTab(void)

View File

@ -14,7 +14,7 @@ struct window {
GtkWidget *menubar; GtkWidget *menubar;
uiContainer *bin; uiBin *bin;
int hidden; int hidden;
@ -47,7 +47,7 @@ static void windowDestroy(uiControl *c)
gtk_widget_hide(w->widget); gtk_widget_hide(w->widget);
// now destroy the bin // now destroy the bin
// we need to remove the bin from its parent first // we need to remove the bin from its parent first
binSetParent(w->bin, 0); uiBinRemoveOSParent(w->bin);
uiControlDestroy(uiControl(w->bin)); uiControlDestroy(uiControl(w->bin));
// now destroy the menus, if any // now destroy the menus, if any
if (w->menubar != NULL) if (w->menubar != NULL)
@ -146,7 +146,7 @@ static void windowSetChild(uiWindow *ww, uiControl *child)
{ {
struct window *w = (struct window *) ww; struct window *w = (struct window *) ww;
binSetMainControl(w->bin, child); uiBinSetMainControl(w->bin, child);
} }
static int windowMargined(uiWindow *ww) static int windowMargined(uiWindow *ww)
@ -162,9 +162,9 @@ static void windowSetMargined(uiWindow *ww, int margined)
w->margined = margined; w->margined = margined;
if (w->margined) if (w->margined)
binSetMargins(w->bin, gtkXMargin, gtkYMargin, gtkXMargin, gtkYMargin); uiBinSetMargins(w->bin, gtkXMargin, gtkYMargin, gtkXMargin, gtkYMargin);
else 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) 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_halign(binWidget, GTK_ALIGN_FILL);
gtk_widget_set_vexpand(binWidget, TRUE); gtk_widget_set_vexpand(binWidget, TRUE);
gtk_widget_set_valign(binWidget, GTK_ALIGN_FILL); 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 // show everything in the vbox, but not the GtkWindow itself
gtk_widget_show_all(w->vboxWidget); gtk_widget_show_all(w->vboxWidget);