4 static void aspect_bin_size_request(GtkWidget *, GtkRequisition *);
5 static void aspect_bin_size_allocate(GtkWidget *, GtkAllocation *);
6 static void aspect_bin_remove(GtkContainer *, GtkWidget *);
7 static void aspect_bin_forall(GtkContainer *, gboolean, GtkCallback, gpointer);
9 G_DEFINE_TYPE(AspectBin, aspect_bin, GTK_TYPE_BIN)
11 static void aspect_bin_init(AspectBin *abin)
15 abin->constrain = FALSE;
19 static void aspect_bin_class_init(AspectBinClass *class)
21 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(class);
22 GtkContainerClass *container_class = GTK_CONTAINER_CLASS(class);
24 widget_class->size_request = aspect_bin_size_request;
25 widget_class->size_allocate = aspect_bin_size_allocate;
27 container_class->remove = aspect_bin_remove;
28 container_class->forall = aspect_bin_forall;
31 GtkWidget *aspect_bin_new(void)
33 return GTK_WIDGET(g_object_new(ASPECT_BIN_TYPE, NULL));
36 static void aspect_bin_remove(GtkContainer *container, GtkWidget *child)
38 AspectBin *abin = ASPECT_BIN(container);
40 if (abin->body == child) {
41 aspect_bin_set_body_widget(abin, NULL, 1);
43 GTK_CONTAINER_CLASS(aspect_bin_parent_class)->remove
48 static void aspect_bin_forall(GtkContainer *container,
49 gboolean include_internals,
51 gpointer callback_data)
53 AspectBin *abin = ASPECT_BIN(container);
54 GtkBin *bin = GTK_BIN(container);
57 callback(bin->child, callback_data);
60 callback(abin->body, callback_data);
64 aspect_bin_size_request(GtkWidget *widget, GtkRequisition *requisition)
66 AspectBin *abin = ASPECT_BIN(widget);
67 GtkBin *bin = GTK_BIN(widget);
68 GtkRequisition creq = {0}, areq = {0};
70 if (bin->child && GTK_WIDGET_VISIBLE(bin->child)) {
71 gtk_widget_size_request(bin->child, &creq);
74 if (abin->body && GTK_WIDGET_VISIBLE(abin->body)) {
76 gtk_widget_size_request(abin->body, &areq);
77 wtmp = areq.height * abin->ratio + 0.5;
78 htmp = areq.width / abin->ratio + 0.5;
80 if (wtmp > areq.width) {
87 requisition->width = areq.width + creq.width;
88 requisition->height = MAX(areq.height, creq.height);
92 aspect_bin_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
94 AspectBin *abin = ASPECT_BIN(widget);
95 GtkBin *bin = GTK_BIN(widget);
96 GtkRequisition creq = {0};
97 GtkAllocation csize = {0}, asize = {0};
99 /* First find the best fit for the constrained child. */
100 if (abin->body && GTK_WIDGET_VISIBLE(abin->body)) {
101 asize.height = allocation->height;
102 asize.width = asize.height * abin->ratio + 0.5;
104 if (asize.width > allocation->width) {
105 asize.width = allocation->width;
106 asize.height = asize.width / abin->ratio + 0.5;
110 /* Now try to fit the other child. */
111 if (bin->child && GTK_WIDGET_VISIBLE(bin->child)) {
112 gtk_widget_get_child_requisition(bin->child, &creq);
114 if (allocation->width - asize.width < creq.width) {
115 /* It didn't fit, squish the constrained guy. */
116 asize.width = allocation->width - creq.width;
117 asize.height = asize.width / abin->ratio + 0.5;
120 csize.width = allocation->width - asize.width;
121 csize.height = MIN(allocation->height, creq.height);
122 if (abin->constrain) {
123 csize.height = MAX(csize.height, asize.height);
125 csize.x = asize.width;
128 csize.y = (allocation->height - csize.height) * abin->align + 0.5;
129 asize.y = (allocation->height - asize.height) * abin->align + 0.5;
132 gtk_widget_size_allocate(bin->child, &csize);
134 gtk_widget_size_allocate(abin->body, &asize);
138 aspect_bin_set_body_widget(AspectBin *abin, GtkWidget *widget, gfloat ratio)
140 gboolean need_resize = FALSE;
142 g_return_if_fail(IS_ASPECT_BIN(abin));
143 g_return_if_fail(widget == NULL || GTK_IS_WIDGET(widget));
144 g_return_if_fail(widget == NULL || widget->parent == NULL);
146 if (abin->body == widget)
150 need_resize |= GTK_WIDGET_VISIBLE(abin->body);
151 gtk_widget_unparent(abin->body);
156 gtk_widget_set_parent(widget, GTK_WIDGET(abin));
157 need_resize |= GTK_WIDGET_VISIBLE(widget);
160 if (GTK_WIDGET_VISIBLE(abin) && need_resize)
161 gtk_widget_queue_resize(GTK_WIDGET(abin));