1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
// 13 august 2014
#include "uipriv_unix.h"
G_DEFINE_TYPE(uiContainer, uiContainer, GTK_TYPE_CONTAINER)
static void uiContainer_init(uiContainer *c)
{
if (options.debugLogAllocations)
fprintf(stderr, "%p alloc uiContainer\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 uiContainer_dispose(GObject *obj)
{
uiContainer *c = uiContainer(obj);
if (c->children != NULL) {
g_ptr_array_unref(c->children);
c->children = NULL;
}
if (c->child != NULL) {
uiControlDestroy(c->child);
c->child = NULL;
}
G_OBJECT_CLASS(uiContainer_parent_class)->dispose(obj);
}
static void uiContainer_finalize(GObject *obj)
{
G_OBJECT_CLASS(uiContainer_parent_class)->finalize(obj);
if (options.debugLogAllocations)
fprintf(stderr, "%p free\n", obj);
}
static void uiContainer_add(GtkContainer *container, GtkWidget *widget)
{
uiContainer *c = uiContainer(container);
gtk_widget_set_parent(widget, GTK_WIDGET(c));
if (c->children != NULL)
g_ptr_array_add(c->children, widget);
}
static void uiContainer_remove(GtkContainer *container, GtkWidget *widget)
{
uiContainer *c = uiContainer(container);
gtk_widget_unparent(widget);
if (c->children != NULL)
g_ptr_array_remove(c->children, widget);
}
#define gtkXMargin 12
#define gtkYMargin 12
#define gtkXPadding 12
#define gtkYPadding 6
static void uiContainer_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
{
uiContainer *c = uiContainer(widget);
uiSizing d;
intmax_t x, y, width, height;
gtk_widget_set_allocation(GTK_WIDGET(c), allocation);
if (c->child == NULL)
return;
x = allocation->x;
y = allocation->y;
width = allocation->width;
height = allocation->height;
if (c->margined) {
x += gtkXMargin;
y += gtkYMargin;
width -= 2 * gtkXMargin;
height -= 2 * gtkYMargin;
}
d.xPadding = gtkXPadding;
d.yPadding = gtkYPadding;
uiControlResize(c->child, 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 uiContainer_forall(GtkContainer *container, gboolean includeInternals, GtkCallback callback, gpointer data)
{
uiContainer *c = uiContainer(container);
struct forall s;
s.callback = callback;
s.data = data;
if (c->children != NULL)
g_ptr_array_foreach(c->children, doforall, &s);
}
static void uiContainer_class_init(uiContainerClass *class)
{
G_OBJECT_CLASS(class)->dispose = uiContainer_dispose;
G_OBJECT_CLASS(class)->finalize = uiContainer_finalize;
GTK_WIDGET_CLASS(class)->size_allocate = uiContainer_size_allocate;
GTK_CONTAINER_CLASS(class)->add = uiContainer_add;
GTK_CONTAINER_CLASS(class)->remove = uiContainer_remove;
GTK_CONTAINER_CLASS(class)->forall = uiContainer_forall;
}
GtkWidget *newContainer(void)
{
GtkWidget *w;
w = GTK_WIDGET(g_object_new(uiContainerType, NULL));
// call gtk_widget_show_all() here to make the container visible
gtk_widget_show_all(w);
return w;
}
void updateParent(uintptr_t parent)
{
if (parent != 0)
gtk_widget_queue_resize(GTK_WIDGET(parent));
}
|