diff --git a/new/unix/OLDcontainer.c b/new/unix/OLDcontainer.c new file mode 100644 index 00000000..254865ae --- /dev/null +++ b/new/unix/OLDcontainer.c @@ -0,0 +1,72 @@ +// 13 august 2014 +#include "uipriv_unix.h" + +#define gtkXPadding 12 +#define gtkYPadding 6 + +static void uipOSContainer_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +{ + uipOSContainer *c = uipOSContainer(widget); + uiSizing d; + intmax_t x, y, width, height; + + gtk_widget_set_allocation(GTK_WIDGET(c), allocation); + if (c->mainControl == NULL) + return; + x = allocation->x + c->marginLeft; + y = allocation->y + c->marginTop; + width = allocation->width - (c->marginLeft + c->marginRight); + height = allocation->height - (c->marginTop + c->marginBottom); + d.xPadding = gtkXPadding; + d.yPadding = gtkYPadding; + uiControlResize(c->mainControl, x, y, width, height, &d); +} + + + +// TODO convert other methods of other backends to pp arg p instance variable + +static void parentDestroy(uiOSContainer *cc) +{ + uipOSContainer *c = uipOSContainer(cc->Internal); + + // first, destroy the main control + if (c->mainControl != NULL) { + // we have to do this before we can destroy controls + uiControlSetHasParent(c->mainControl, 0); + uiControlSetOSContainer(c->mainControl, NULL); + uiControlDestroy(c->mainControl); + c->mainControl = NULL; + } + // now we can mark the parent as ready to be destroyed + c->canDestroy = TRUE; + // finally, destroy the parent + g_object_unref(G_OBJECT(c)); + // and free ourselves + uiFree(cc); +} + +static void parentSetMainControl(uiOSContainer *cc, uiControl *mainControl) +{ + uipOSContainer *c = uipOSContainer(cc->Internal); + + if (c->mainControl != NULL) { + uiControlSetHasParent(c->mainControl, 0); + uiControlSetOSContainer(c->mainControl, NULL); + } + c->mainControl = mainControl; + if (c->mainControl != NULL) { + uiControlSetHasParent(c->mainControl, 1); + uiControlSetOSContainer(c->mainControl, cc); + } +} + +static void parentSetMargins(uiOSContainer *cc, intmax_t left, intmax_t top, intmax_t right, intmax_t bottom) +{ + uipOSContainer *c = uipOSContainer(cc->Internal); + + c->marginLeft = left; + c->marginTop = top; + c->marginRight = right; + c->marginBottom = bottom; +} diff --git a/new/unix/container.c b/new/unix/container.c new file mode 100644 index 00000000..4b537a51 --- /dev/null +++ b/new/unix/container.c @@ -0,0 +1,234 @@ +// 28 april 2015 +#include "uipriv_unix.h" + +#define containerWidgetType (containerWidget_get_type()) +#define containerWidget(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), containerWidgetType, containerWidget)) +#define IscontainerWidget(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), containerWidgetType)) +#define containerWidgetClass(class) (G_TYPE_CHECK_CLASS_CAST((class), containerWidgetType, containerWidgetClass)) +#define IscontainerWidgetClass(class) (G_TYPE_CHECK_CLASS_TYPE((class), containerWidget)) +#define GetcontainerWidgetClass(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), containerWidgetType, containerWidgetClass)) + +typedef struct containerWidget containerWidget; +typedef struct containerWidgetClass containerWidgetClass; + +struct containerWidget { + GtkContainer parent_instance; + uiContainer *c; + GPtrArray *widgets; // for for_each()/for_all() + uiContainer *parent; + int hidden; +}; + +struct containerWidgetClass { + GtkContainerClass parent_class; +}; + +G_DEFINE_TYPE(containerWidget, containerWidget, GTK_TYPE_CONTAINER) + +static void containerWidget_init(containerWidget *c) +{ + if (options.debugLogAllocations) + fprintf(stderr, "%p alloc containerWidget\n", c); + c->widgets = g_ptr_array_new(); + gtk_widget_set_has_window(GTK_WIDGET(c), FALSE); +} + +// TODO destroy blocking +static void containerWidget_dispose(GObject *obj) +{ + G_OBJECT_CLASS(containerWidget_parent_class)->dispose(obj); +} + +static void containerWidget_finalize(GObject *obj) +{ + containerWidget *c = containerWidget(obj); + + g_ptr_array_unref(c->widgets); + G_OBJECT_CLASS(containerWidget_parent_class)->finalize(obj); + if (options.debugLogAllocations) + fprintf(stderr, "%p free\n", obj); +} + +static void containerWidget_add(GtkContainer *container, GtkWidget *widget) +{ + containerWidget *c = containerWidget(container); + + gtk_widget_set_parent(widget, GTK_WIDGET(c)); + g_ptr_array_add(c->widgets, widget); +} + +static void containerWidget_remove(GtkContainer *container, GtkWidget *widget) +{ + containerWidget *c = containerWidget(container); + + gtk_widget_unparent(widget); + if (g_ptr_array_remove(c->widgets, widget) == FALSE) + complain("widget %p not found in containerWidget gtk_container_remove()", widget); +} + +static void containerWidget_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +{ + containerWidget *c = containerWidget(widget); + uiSizing d; + + gtk_widget_set_allocation(GTK_WIDGET(c), allocation); + d.xPadding = gtkXPadding; + d.yPadding = gtkYPadding; + uiContainerResizeChildren(c->c, allocation->x, allocation->y, allocation->width, allocation->height, &d); +} + +struct forall { + GtkCallback callback; + gpointer data; +}; + +static void doforall(gpointer obj, gpointer data) +{ + struct forall *s = (struct forall *) data; + + (*(s->callback))(GTK_WIDGET(obj), s->data); +} + +static void uipOSContainer_forall(GtkContainer *container, gboolean includeInternals, GtkCallback callback, gpointer data) +{ + uipOSContainer *c = uipOSContainer(container); + struct forall s; + + s.callback = callback; + s.data = data; + g_ptr_array_foreach(c->widgets, doforall, &s); +} + +static void containerWidget_class_init(containerWidgetClass *class) +{ + G_OBJECT_CLASS(class)->dispose = containerWidget_dispose; + G_OBJECT_CLASS(class)->finalize = containerWidget_finalize; + GTK_WIDGET_CLASS(class)->size_allocate = containerWidget_size_allocate; + GTK_CONTAINER_CLASS(class)->add = containerWidget_add; + GTK_CONTAINER_CLASS(class)->remove = containerWidget_remove; + GTK_CONTAINER_CLASS(class)->forall = containerWidget_forall; +} + +// subclasses override this and call back here when all children are destroyed +static void containerDestroy(uiControl *cc) +{ + containerWidget *c = containerWidget(cc->Internal); + + if (c->parent != NULL) + complain("attempt to destroy uiContainer %p while it has a parent", cc); + g_object_unref(c); // release our initial reference, which destroys the widget + uiFree(c); +} + +static uintptr_t containerHandle(uiControl *cc) +{ + containerWidget *c = containerWidget(cc->Internal); + + return (uintptr_t) c; +} + +static void containerSetParent(uiControl *cc, uiContainer *parent) +{ + containerWidget *c = containerWidget(cc->Internal); + uiContainer *oldparent; + GtkContainer *oldcontainer; + GtkContainer *newcontainer; + + oldparent = c->parent; + c->parent = parent; + if (oldparent != NULL) { + oldcontainer = GTK_CONTAINER(uiControlHandle(uiControl(oldparent))); + gtk_container_remove(oldcontainer, GTK_WIDGET(c)); + } + if (c->parent != NULL) { + newcontainer = GTK_CONTAINER(uiControlHandle(uiControl(c->parent))); + gtk_container_add(newcontainer, GTK_WIDGET(c)); + } + if (oldparent != NULL) + uiContainerUpdate(oldparent); + if (c->parent != NULL) + uiContainerUpdate(c->parent); +} + +static void containerResize(uiControl *cc, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) +{ + containerWidget *c = containerWidget(cc->Internal); + GtkAllocation a; + + a.x = x; + a.y = y; + a.width = width; + a.height = height; + gtk_widget_size_allocate(GTK_WIDGET(c), &a); +} + +static int containerVisible(uiControl *cc) +{ + containerWidget *c = containerWidget(cc->Internal); + + return !c->hidden; +} + +static void containerShow(uiControl *cc) +{ + containerWidget *c = containerWidget(cc->Internal); + + // don't use gtk_widget_show_all(); that'll show every widget, including ones hidden by the user + gtk_widget_show(GTK_WIDGET(c)); + c->hidden = 0; +} + +static void containerHide(uiControl *cc) +{ + containerWidget *c = containerWidget(cc->Internal); + + gtk_widget_hide(GTK_WIDGET(c)); + c->hidden = 1; +} + +static void containerEnable(uiControl *cc) +{ + containerWidget *c = containerWidget(cc->Internal); + + gtk_widget_set_sensitive(GTK_WIDGET(c), TRUE); +} + +static void containerDisable(uiControl *cc) +{ + containerWidget *c = containerWidget(cc->Internal); + + gtk_widget_set_sensitive(GTK_WIDGET(c), FALSE); +} + +static void containerUpdate(uiContainer *cc) +{ + containerWidget *c = containerWidget(cc->Internal); + + gtk_widget_queue_resize(GTK_WIDGET(c)); +} + +void uiMakeContainer(uiContainer *cc) +{ + containerWidget *c; + + c = containerWidget(g_object_new(containerWidgetType, NULL)); + // keep a reference to our container so it stays alive when reparented + g_object_ref_sink(c); + // and make it visible + gtk_widget_show_all(GTK_WIDGET(c)); + + uiControl(cc)->Internal = c; + uiControl(cc)->Destroy = containerDestroy; + uiControl(cc)->Handle = containerHandle; + uiControl(cc)->SetParent = containerSetParent; + // PreferredSize() is provided by subclasses + uiControl(cc)->Resize = containerResize; + uiControl(cc)->Visible = containerVisible; + uiControl(cc)->Show = containerShow; + uiControl(cc)->Hide = containerHide; + uiControl(cc)->Enable = containerEnable; + uiControl(cc)->Disable = containerDisable; + + // ResizeChildren() is provided by subclasses + uiContainer(cc)->Update = containerUpdate; +} diff --git a/new/unix/oscontainer.c b/new/unix/oscontainer.c deleted file mode 100644 index a690a63a..00000000 --- a/new/unix/oscontainer.c +++ /dev/null @@ -1,219 +0,0 @@ -// 13 august 2014 -#include "uipriv_unix.h" - -#define uipOSContainerType (uipOSContainer_get_type()) -#define uipOSContainer(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), uipOSContainerType, uipOSContainer)) -#define uipIsOSContainer(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), uipOSContainerType)) -#define uipOSContainerClass(class) (G_TYPE_CHECK_CLASS_CAST((class), uipOSContainerType, uipOSContainerClass)) -#define uipIsOSContainerClass(class) (G_TYPE_CHECK_CLASS_TYPE((class), uipOSContainer)) -#define uipGetParentClass(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), uipOSContainerType, uipOSContainerClass)) - -typedef struct uipOSContainer uipOSContainer; -typedef struct uipOSContainerClass uipOSContainerClass; - -struct uipOSContainer { - GtkContainer parent_instance; - uiControl *mainControl; - GPtrArray *children; // for forall() - intmax_t marginLeft; - intmax_t marginTop; - intmax_t marginRight; - intmax_t marginBottom; - gboolean canDestroy; -}; - -struct uipOSContainerClass { - GtkContainerClass parent_class; -}; - -G_DEFINE_TYPE(uipOSContainer, uipOSContainer, GTK_TYPE_CONTAINER) - -static void uipOSContainer_init(uipOSContainer *c) -{ - if (options.debugLogAllocations) - fprintf(stderr, "%p alloc uipOSContainer\n", c); - c->children = g_ptr_array_new(); - gtk_widget_set_has_window(GTK_WIDGET(c), FALSE); -} - -// instead of having GtkContainer itself unref all our controls, we'll run our own uiControlDestroy() functions for child, which will do that and more -// we still chain up because we need to, but by that point there will be no children for GtkContainer to free -static void uipOSContainer_dispose(GObject *obj) -{ - uipOSContainer *c = uipOSContainer(obj); - - // don't free mainControl here; that should have been done by uiOSContainerDestroy() - if (!c->canDestroy) - complain("attempt to dispose uiOSContainer with uipOSContainer at %p before uiOSContainerDestroy()", c); - if (c->children != NULL) { - if (c->children->len != 0) - complain("disposing uiOSContainer with uipOSContainer at %p while there are still children", c); - g_ptr_array_unref(c->children); - c->children = NULL; - } - G_OBJECT_CLASS(uipOSContainer_parent_class)->dispose(obj); -} - -static void uipOSContainer_finalize(GObject *obj) -{ - uipOSContainer *c = uipOSContainer(obj); - - if (!c->canDestroy) - complain("attempt to finalize uiOSContainer with uipOSContainer at %p before uiOSContainerDestroy()", c); - G_OBJECT_CLASS(uipOSContainer_parent_class)->finalize(obj); - if (options.debugLogAllocations) - fprintf(stderr, "%p free\n", obj); -} - -static void uipOSContainer_add(GtkContainer *container, GtkWidget *widget) -{ - uipOSContainer *c = uipOSContainer(container); - - gtk_widget_set_parent(widget, GTK_WIDGET(c)); - if (c->children != NULL) - g_ptr_array_add(c->children, widget); -} - -static void uipOSContainer_remove(GtkContainer *container, GtkWidget *widget) -{ - uipOSContainer *c = uipOSContainer(container); - - gtk_widget_unparent(widget); - if (c->children != NULL) - if (g_ptr_array_remove(c->children, widget) == FALSE) - complain("widget %p not found in uipOSContainer gtk_container_remove()", widget); -} - -#define gtkXPadding 12 -#define gtkYPadding 6 - -static void uipOSContainer_size_allocate(GtkWidget *widget, GtkAllocation *allocation) -{ - uipOSContainer *c = uipOSContainer(widget); - uiSizing d; - intmax_t x, y, width, height; - - gtk_widget_set_allocation(GTK_WIDGET(c), allocation); - if (c->mainControl == NULL) - return; - x = allocation->x + c->marginLeft; - y = allocation->y + c->marginTop; - width = allocation->width - (c->marginLeft + c->marginRight); - height = allocation->height - (c->marginTop + c->marginBottom); - d.xPadding = gtkXPadding; - d.yPadding = gtkYPadding; - uiControlResize(c->mainControl, x, y, width, height, &d); -} - -struct forall { - GtkCallback callback; - gpointer data; -}; - -static void doforall(gpointer obj, gpointer data) -{ - struct forall *s = (struct forall *) data; - - (*(s->callback))(GTK_WIDGET(obj), s->data); -} - -static void uipOSContainer_forall(GtkContainer *container, gboolean includeInternals, GtkCallback callback, gpointer data) -{ - uipOSContainer *c = uipOSContainer(container); - struct forall s; - - s.callback = callback; - s.data = data; - if (c->children != NULL) - g_ptr_array_foreach(c->children, doforall, &s); -} - -static void uipOSContainer_class_init(uipOSContainerClass *class) -{ - G_OBJECT_CLASS(class)->dispose = uipOSContainer_dispose; - G_OBJECT_CLASS(class)->finalize = uipOSContainer_finalize; - GTK_WIDGET_CLASS(class)->size_allocate = uipOSContainer_size_allocate; - GTK_CONTAINER_CLASS(class)->add = uipOSContainer_add; - GTK_CONTAINER_CLASS(class)->remove = uipOSContainer_remove; - GTK_CONTAINER_CLASS(class)->forall = uipOSContainer_forall; -} - -// TODO convert other methods of other backends to pp arg p instance variable - -static void parentDestroy(uiOSContainer *cc) -{ - uipOSContainer *c = uipOSContainer(cc->Internal); - - // first, destroy the main control - if (c->mainControl != NULL) { - // we have to do this before we can destroy controls - uiControlSetHasParent(c->mainControl, 0); - uiControlSetOSContainer(c->mainControl, NULL); - uiControlDestroy(c->mainControl); - c->mainControl = NULL; - } - // now we can mark the parent as ready to be destroyed - c->canDestroy = TRUE; - // finally, destroy the parent - g_object_unref(G_OBJECT(c)); - // and free ourselves - uiFree(cc); -} - -static uintptr_t parentHandle(uiOSContainer *cc) -{ - uipOSContainer *c = uipOSContainer(cc->Internal); - - return (uintptr_t) c; -} - -static void parentSetMainControl(uiOSContainer *cc, uiControl *mainControl) -{ - uipOSContainer *c = uipOSContainer(cc->Internal); - - if (c->mainControl != NULL) { - uiControlSetHasParent(c->mainControl, 0); - uiControlSetOSContainer(c->mainControl, NULL); - } - c->mainControl = mainControl; - if (c->mainControl != NULL) { - uiControlSetHasParent(c->mainControl, 1); - uiControlSetOSContainer(c->mainControl, cc); - } -} - -static void parentSetMargins(uiOSContainer *cc, intmax_t left, intmax_t top, intmax_t right, intmax_t bottom) -{ - uipOSContainer *c = uipOSContainer(cc->Internal); - - c->marginLeft = left; - c->marginTop = top; - c->marginRight = right; - c->marginBottom = bottom; -} - -static void parentUpdate(uiOSContainer *cc) -{ - uipOSContainer *c = uipOSContainer(cc->Internal); - - gtk_widget_queue_resize(GTK_WIDGET(c)); -} - -uiOSContainer *uiNewOSContainer(uintptr_t osParent) -{ - uiOSContainer *c; - - c = uiNew(uiOSContainer); - c->Internal = g_object_new(uipOSContainerType, NULL); - c->Destroy = parentDestroy; - c->Handle = parentHandle; - c->SetMainControl = parentSetMainControl; - c->SetMargins = parentSetMargins; - c->Update = parentUpdate; - gtk_container_add(GTK_CONTAINER(osParent), GTK_WIDGET(c->Internal)); - // make it visible by default - gtk_widget_show_all(GTK_WIDGET(c->Internal)); - // hold a reference to it to keep it alive - g_object_ref(G_OBJECT(c->Internal)); - return c; -}