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
#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+
}

View File

@ -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)

View File

@ -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);