libui/unix/grid.c

142 lines
3.5 KiB
C

// 9 june 2016
#include "uipriv_unix.h"
struct gridChild {
uiControl *c;
GtkWidget *label;
gboolean oldhexpand;
GtkAlign oldhalign;
gboolean oldvexpand;
GtkAlign oldvalign;
};
struct uiGrid {
uiUnixControl c;
GtkWidget *widget;
GtkContainer *container;
GtkGrid *grid;
GArray *children;
int padded;
};
uiUnixControlAllDefaultsExceptDestroy(uiGrid)
#define ctrl(g, i) &g_array_index(g->children, struct gridChild, i)
static void uiGridDestroy(uiControl *c)
{
uiGrid *g = uiGrid(c);
struct gridChild *gc;
guint i;
// free all controls
for (i = 0; i < g->children->len; i++) {
gc = ctrl(g, i);
uiControlSetParent(gc->c, NULL);
uiUnixControlSetContainer(uiUnixControl(gc->c), g->container, TRUE);
uiControlDestroy(gc->c);
}
g_array_free(g->children, TRUE);
// and then ourselves
g_object_unref(g->widget);
uiFreeControl(uiControl(g));
}
#define TODO_MASSIVE_HACK(c) \
if (!uiUnixControl(c)->addedBefore) { \
g_object_ref_sink(GTK_WIDGET(uiControlHandle(uiControl(c)))); \
gtk_widget_show(GTK_WIDGET(uiControlHandle(uiControl(c)))); \
uiUnixControl(c)->addedBefore = TRUE; \
}
static const GtkAlign gtkAligns[] = {
[uiAlignFill] = GTK_ALIGN_FILL,
[uiAlignStart] = GTK_ALIGN_START,
[uiAlignCenter] = GTK_ALIGN_CENTER,
[uiAlignEnd] = GTK_ALIGN_END,
};
static const GtkPositionType gtkPositions[] = {
[uiAtLeading] = GTK_POS_LEFT,
[uiAtTop] = GTK_POS_TOP,
[uiAtTrailing] = GTK_POS_RIGHT,
[uiAtBottom] = GTK_POS_BOTTOM,
};
static GtkWidget *prepare(struct gridChild *gc, uiControl *c, int hexpand, uiAlign halign, int vexpand, uiAlign valign)
{
GtkWidget *widget;
gc->c = c;
widget = GTK_WIDGET(uiControlHandle(gc->c));
gc->oldhexpand = gtk_widget_get_hexpand(widget);
gc->oldhalign = gtk_widget_get_halign(widget);
gc->oldvexpand = gtk_widget_get_vexpand(widget);
gc->oldvalign = gtk_widget_get_valign(widget);
gtk_widget_set_hexpand(widget, hexpand != 0);
gtk_widget_set_halign(widget, gtkAligns[halign]);
gtk_widget_set_vexpand(widget, vexpand != 0);
gtk_widget_set_valign(widget, gtkAligns[valign]);
return widget;
}
void uiGridAppend(uiGrid *g, uiControl *c, int left, int top, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign)
{
struct gridChild gc;
GtkWidget *widget;
widget = prepare(&gc, c, hexpand, halign, vexpand, valign);
uiControlSetParent(gc.c, uiControl(g));
TODO_MASSIVE_HACK(uiUnixControl(gc.c));
gtk_grid_attach(g->grid, widget,
left, top,
xspan, yspan);
g_array_append_val(g->children, gc);
}
void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign)
{
struct gridChild gc;
GtkWidget *widget;
widget = prepare(&gc, c, hexpand, halign, vexpand, valign);
uiControlSetParent(gc.c, uiControl(g));
TODO_MASSIVE_HACK(uiUnixControl(gc.c));
gtk_grid_attach_next_to(g->grid, widget,
GTK_WIDGET(uiControlHandle(existing)), gtkPositions[at],
xspan, yspan);
g_array_append_val(g->children, gc);
}
int uiGridPadded(uiGrid *g)
{
return g->padded;
}
void uiGridSetPadded(uiGrid *g, int padded)
{
g->padded = padded;
if (g->padded) {
gtk_grid_set_row_spacing(g->grid, gtkYPadding);
gtk_grid_set_column_spacing(g->grid, gtkXPadding);
} else {
gtk_grid_set_row_spacing(g->grid, 0);
gtk_grid_set_column_spacing(g->grid, 0);
}
}
uiGrid *uiNewGrid(void)
{
uiGrid *g;
uiUnixNewControl(uiGrid, g);
g->widget = gtk_grid_new();
g->container = GTK_CONTAINER(g->widget);
g->grid = GTK_GRID(g->widget);
g->children = g_array_new(FALSE, TRUE, sizeof (struct gridChild));
return g;
}